Chartjs-Get a data from user table for line chart (chart.js)

1👍

I would suggest creating a table or view calculating the number of users by the end of the day. That way you don’t have to run the same query and calculations every time the chart is loaded.

  1. Make a command php artisan make:command GenerateUserCounts, the command should generate the users count for an input of $date, by default is today()
  2. Schedule command to run by end of the day
$schedule->command('users:log-count')->dailyAt('00:00');
  1. Run command manually for the days before

0👍

foreach ($records as $record) {
  $date = Carbon::parse($record->created_at)->format('M d');
  $prevDate = Carbon::parse($record->created_at)->subDay()->format('M d');
  $days[$date] = $days[$date] + ($days[$prevDate] ?? 0);

  if($allUsers != 0){
    $days[$date] += $record->deleted_at ? -1 : 1;
  }
}

0👍

From your code, it seems you were trying to achieve something on the lines of:

  1. Pre-populate an array of days with the count on users on the beginning of the period (there is a bug here);
  2. Iterate through days adding the count of created users and removing the count of deleted users.

The bug I see is that you started your count at the end of the period instead of the beginning. You should not pre-populate all days with $allUsers but only the users at the beginning, $usersAtBeginning = User::where('created_at', '<' $startDate).

Nonetheless, as I’ve mentioned, your code can be more straightforward (and faster) by making better use of Laravel feature. In this case, Collection’s methods. Your function could look like this:

$startDate = now()->subDays(30)->startOfDay();
$endDate = now()->endOfDay();

/** @var Collection<int, User> */
$users = User::query()
    ->withTrashed()
    ->whereBetween('created_at', [$startDate, $endDate])
    ->get(['created_at', 'deleted_at']);

$totalAtTime = User::query()
    ->where('created_at', '<', $startDate)
    ->whereNull('deleted_at')
    ->count();

$current = $startDate;
while ($current <= $endDate) {
    $next = (clone $current)->endOfDay();

    $created = $users->whereBetween('created_at', [
        $current,
         $next,
    ])
        ->count();

    $deleted = $users->whereBetween('deleted_at', [
        $current,
        $next,
    ])
        ->count();

    $totalAtTime += $created - $deleted;

    $data[$current->format('M d')] = $totalAtTime;
    $current->addDay();
}

Leave a comment