1. Go to this page and download the library: Download halilcosdu/laravel-slower library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
halilcosdu / laravel-slower example snippets
use Illuminate\Support\Facades\Gate;
Gate::define('viewSlower', function ($user = null) {
return $user?->email === '[email protected]';
});
namespace App\Support;
use HalilCosdu\Slower\Contracts\PayloadRedactor;
class SlowerRedactor implements PayloadRedactor
{
public function redactBindings(array $bindings): array
{
return array_map(
fn ($value) => is_string($value) && str_contains($value, '@') ? '[email]' : $value,
$bindings,
);
}
public function redactRawSql(string $rawSql): string
{
return preg_replace('/\b[\w.+-]+@[\w-]+\.[\w.]+\b/', '[email]', $rawSql);
}
}
// app/Providers/AppServiceProvider.php
use HalilCosdu\Slower\Events\SlowQueryFirstSeen;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Notification;
public function boot(): void
{
Event::listen(function (SlowQueryFirstSeen $event) {
Notification::route('slack', config('services.slack.alerts_webhook'))
->notify(new \App\Notifications\NewSlowQuery($event->record));
});
}
// app/Notifications/NewSlowQuery.php (the interesting part)
public function toSlack(object $notifiable): SlackMessage
{
$origin = $this->record->origin['action'] ?? $this->record->origin['job'] ?? 'unknown origin';
return (new SlackMessage)
->text(sprintf(
'🐌 New slow query (%.0f ms) from %s: %s',
$this->record->time,
$origin,
\Illuminate\Support\Str::limit($this->record->sql, 120),
));
}
use HalilCosdu\Slower\Http\Middleware\Authorize;
use HalilCosdu\Slower\Models\SlowLog;
return [
'enabled' => env('SLOWER_ENABLED', true),
'threshold' => env('SLOWER_THRESHOLD', 10000), // ms
'ai_service' => env('SLOWER_AI_SERVICE', 'openai'),
'capture' => [
'sample_rate' => env('SLOWER_SAMPLE_RATE', 1.0),
'max_per_execution' => env('SLOWER_MAX_PER_EXECUTION', 50),
'origin' => [
'enabled' => env('SLOWER_CAPTURE_ORIGIN', true),
'user_id' => env('SLOWER_CAPTURE_USER_ID', false),
],
],
'resources' => [
'table_name' => (new SlowLog)->getTable(),
'model' => SlowLog::class,
],
'dashboard' => [
'enabled' => env('SLOWER_DASHBOARD_ENABLED', true),
'path' => env('SLOWER_DASHBOARD_PATH', 'slower'),
'domain' => env('SLOWER_DASHBOARD_DOMAIN'),
'middleware' => [
'web',
Authorize::class,
],
'per_page' => 25,
'analyze_pending_limit' => 10,
],
'ai_recommendation' => env('SLOWER_AI_RECOMMENDATION', true),
// null = analyze synchronously; a queue name = analyze as background jobs
'analyze_queue' => env('SLOWER_ANALYZE_QUEUE'),
'ai_payload' => [
'send_raw_sql' => env('SLOWER_AI_SEND_RAW_SQL', false),
'send_bindings' => env('SLOWER_AI_SEND_BINDINGS', false),
'redactor' => null, // class-string implementing Contracts\PayloadRedactor
],
// null → a sensible low-cost default for the selected provider
'recommendation_model' => env('SLOWER_AI_RECOMMENDATION_MODEL'),
'recommendation_use_explain' => env('SLOWER_AI_RECOMMENDATION_USE_EXPLAIN', true),
'ignore_explain_queries' => env('SLOWER_IGNORE_EXPLAIN_QUERIES', true),
'ignore_insert_queries' => env('SLOWER_IGNORE_INSERT_QUERIES', true),
'prompt' => env('SLOWER_PROMPT', '...'), // the system prompt sent to the AI
];
use HalilCosdu\Slower\AiServiceDrivers\AiServiceManager;
use HalilCosdu\Slower\AiServiceDrivers\Contracts\AiServiceDriver;
app(AiServiceManager::class)->extend('my-llm', fn () => new class implements AiServiceDriver
{
public function analyze(string $userMessage): ?string
{
// Call your model. Return the recommendation text, or null to retry later.
}
});
use HalilCosdu\Slower\Commands\AnalyzeQuery;
use HalilCosdu\Slower\Commands\SlowLogCleaner;
protected function schedule(Schedule $schedule): void
{
$schedule->command(AnalyzeQuery::class)->runInBackground()->daily();
$schedule->command(SlowLogCleaner::class)->runInBackground()->daily();
}
use HalilCosdu\Slower\Facades\Slower;
use HalilCosdu\Slower\Models\SlowLog;
// Analyze a single captured query — returns the analyzed model.
$record = SlowLog::first();
Slower::analyze($record);
$record->raw_sql; // select count(*) as aggregate from "product_prices" where ...
$record->recommendation; // the AI's optimization advice (markdown)
use HalilCosdu\Slower\Facades\Slower;
use HalilCosdu\Slower\Models\SlowLog;
// How many queries are still waiting for analysis?
$pending = SlowLog::where('is_analyzed', false)->count();
// Analyze the twenty slowest unanalyzed queries.
SlowLog::query()
->where('is_analyzed', false)
->orderByDesc('time')
->limit(20)
->get()
->each(fn (SlowLog $log) => Slower::analyze($log));
// The most frequent slow query shapes (what the Grouped view shows).
SlowLog::query()
->whereNotNull('fingerprint')
->selectRaw('fingerprint, count(*) as occurrences, max(time) as max_time')
->groupBy('fingerprint')
->orderByDesc('occurrences')
->limit(5)
->get();
// Where did this one come from?
$record->fingerprint; // 40-char shape hash, shared by all repeats
$record->origin; // ['type' => 'http', 'route' => 'orders.index',
// 'action' => 'App\...\OrderController@index',
// 'frame' => 'app/Http/Controllers/OrderController.php:38']
bash
php artisan slower:analyze # analyze every record where is_analyzed=false
php artisan slower:analyze --queue # ...as unique background jobs instead
php artisan slower:clean 15 # delete records older than 15 days
php artisan slower:fingerprint # one-time: fingerprint records captured before v3.2
sql
SELECT COUNT(*) AS aggregate
FROM product_prices
WHERE product_id = 1 AND price = 0 AND discount_total > 0;
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.