{$resourceIdColumn} = $resourceId; $logItem->created_at = time(); $logItem->log_type = $logType; $logItem->track_format_id = $formatId; $logItem->ip_address = Request::getClientIp(); if (Auth::check()) { $logItem->user_id = Auth::user()->id; } $logItem->save(); $resourceTable = $resourceType . 's'; $countColumn = ''; if ($logType == self::VIEW) $countColumn = 'view_count'; else if ($logType == self::DOWNLOAD) $countColumn = 'download_count'; else if ($logType == self::PLAY) $countColumn = 'play_count'; // We do this to prevent a race condition. Sure I could simply increment the count columns and re-save back to the db // but that would require an additional SELECT and the operation would be non-atomic. If two log items are created // for the same resource at the same time, the cached values will still be correct with this method. DB::table($resourceTable)->whereId($resourceId)->update([$countColumn => DB::raw('(SELECT COUNT(id) FROM resource_log_items WHERE ' . $resourceIdColumn . ' = ' . $resourceId . ' AND log_type = ' . $logType . ')')]); if (Auth::check()) { $resourceUserId = ResourceUser::getId(Auth::user()->id, $resourceType, $resourceId); DB::table('resource_users')->whereId($resourceUserId)->update([$countColumn => DB::raw('(SELECT COUNT(id) FROM resource_log_items WHERE user_id = ' . Auth::user()->id . ' AND ' . $resourceIdColumn . ' = ' . $resourceId . ' AND log_type = ' . $logType . ')')]); } } }