PHPackages                             romdh4ne/laravel-querycraft - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. romdh4ne/laravel-querycraft

ActiveLibrary[Database &amp; ORM](/categories/database)

romdh4ne/laravel-querycraft
===========================

Find and fix Laravel performance issues automatically

v1.1.0(3mo ago)2219↓55.6%MITBladePHP ^8.1

Since Feb 15Pushed 3mo ago1 watchersCompare

[ Source](https://github.com/romdh4ne/laravel-querycraft)[ Packagist](https://packagist.org/packages/romdh4ne/laravel-querycraft)[ RSS](/packages/romdh4ne-laravel-querycraft/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (5)Versions (8)Used By (0)

 [![QueryCraft Logo](public/logo-horizontal.svg)](public/logo-horizontal.svg)

 **A Laravel performance analysis dashboard for detecting N+1 queries, slow queries, missing indexes, and duplicate queries — in real time.**

 [![Laravel](https://camo.githubusercontent.com/45323f7a6aeefa7a2c5f461c42c34ea002a1f00c4e85e14fa1abf70741d74762/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d392532422532302537432532303130253242253230253743253230313125324225323025374325323031322532422d7265643f7374796c653d666c61742d737175617265266c6f676f3d6c61726176656c)](https://camo.githubusercontent.com/45323f7a6aeefa7a2c5f461c42c34ea002a1f00c4e85e14fa1abf70741d74762/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d392532422532302537432532303130253242253230253743253230313125324225323025374325323031322532422d7265643f7374796c653d666c61742d737175617265266c6f676f3d6c61726176656c) [![PHP](https://camo.githubusercontent.com/9847427b3ad37d5f2f3122f63983977e1b0ab038e06a24272d8c4514725c11a0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e312532422d626c75653f7374796c653d666c61742d737175617265266c6f676f3d706870)](https://camo.githubusercontent.com/9847427b3ad37d5f2f3122f63983977e1b0ab038e06a24272d8c4514725c11a0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e312532422d626c75653f7374796c653d666c61742d737175617265266c6f676f3d706870) [![License](https://camo.githubusercontent.com/422db9fd40f5831c765cf6530b6750c081b696bd18d904cf89554df98c676277/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e3f7374796c653d666c61742d737175617265)](https://camo.githubusercontent.com/422db9fd40f5831c765cf6530b6750c081b696bd18d904cf89554df98c676277/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e3f7374796c653d666c61742d737175617265) [![Packagist](https://camo.githubusercontent.com/79472c24ee1d67d48c93572ae17bd36796ca82801430e9272ae9a8a5c8ed5d6a/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f726f6d6468346e652f6c61726176656c2d717565727963726166743f7374796c653d666c61742d737175617265)](https://camo.githubusercontent.com/79472c24ee1d67d48c93572ae17bd36796ca82801430e9272ae9a8a5c8ed5d6a/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f726f6d6468346e652f6c61726176656c2d717565727963726166743f7374796c653d666c61742d737175617265) [![Downloads](https://camo.githubusercontent.com/b5ce1f2f6b499f4f1c2f2362ef489e7714cec98efc31a586d5562b7c24913606/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f726f6d6468346e652f6c61726176656c2d717565727963726166743f7374796c653d666c61742d737175617265)](https://camo.githubusercontent.com/b5ce1f2f6b499f4f1c2f2362ef489e7714cec98efc31a586d5562b7c24913606/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f726f6d6468346e652f6c61726176656c2d717565727963726166743f7374796c653d666c61742d737175617265)

---

✨ Features
----------

[](#-features)

- 🔁 **N+1 Detection** — catches repeated query patterns caused by missing eager loading
- 🐢 **Slow Query Detection** — flags queries exceeding your configured time limit
- 🗂 **Missing Index Detection** — identifies full table scans using MySQL `EXPLAIN`
- 📋 **Duplicate Query Detection** — finds identical queries (including bindings) fired multiple times
- 📍 **Source Location** — shows the exact file and line number in your app that triggered the issue
- 💯 **Performance Score** — grades your endpoint from 0–100 with a letter grade (A–F)
- 🛠 **Live Config Panel** — toggle detectors and adjust thresholds from the dashboard UI
- 🌙 **Dark Mode** — built-in dark/light mode toggle
- 🚨 **500 Error Inspector** — displays full exception details with app-only stack trace
- ⌨️ **Artisan Command** — analyze endpoints directly from your terminal with full body and header support

---

📦 Installation
--------------

[](#-installation)

### 1. Require the package via Composer

[](#1-require-the-package-via-composer)

```
composer require romdh4ne/laravel-querycraft
```

### 2. Publish the config file

[](#2-publish-the-config-file)

```
php artisan vendor:publish --tag=querycraft-config
```

### 3. Publish the assets (logo, favicon)

[](#3-publish-the-assets-logo-favicon)

```
php artisan vendor:publish --tag=querycraft-assets
```

### 4. Publish the views *(optional — only if you want to customize the UI)*

[](#4-publish-the-views-optional--only-if-you-want-to-customize-the-ui)

```
php artisan vendor:publish --tag=querycraft-views
```

### 5. Clear caches

[](#5-clear-caches)

```
php artisan config:clear
php artisan view:clear
```

### 6. Visit the dashboard

[](#6-visit-the-dashboard)

```
http://your-app.test/querycraft

```

---

🖥 Web Dashboard
---------------

[](#-web-dashboard)

### Opening the dashboard

[](#opening-the-dashboard)

```
http://your-app.test/querycraft

```

Or with a custom route prefix set in `.env`:

```
http://your-app.test/your-custom-prefix

```

### Analyzing an endpoint

[](#analyzing-an-endpoint)

1. Enter your endpoint URL (e.g. `/api/users`)
2. Select the HTTP method (`GET`, `POST`, `PUT`, `PATCH`, `DELETE`)
3. Optionally add custom headers (e.g. `Authorization: Bearer token`)
4. Optionally add a JSON request body for `POST`/`PUT` requests
5. Click **Analyze Request**

QueryCraft fires an internal request to your endpoint, collects all queries, runs them through all detectors, and displays the results instantly.

### Reading the results

[](#reading-the-results)

ElementDescription**Score card**0–100 performance grade with letter (A–F) and emoji indicator**Query count**Total number of queries executed by the endpoint**Total time**Combined execution time of all queries in milliseconds**Issue cards**Each problem with severity, stats, source location and fix suggestion**Source Location**Exact file path and line number in your app (vendor files filtered out)**All Queries**Collapsible list of every query fired with individual execution time### 500 Error Inspector

[](#500-error-inspector)

When your endpoint crashes, QueryCraft catches it and displays:

- Exception class (e.g. `ErrorException`, `QueryException`)
- Error message
- Exact file and line number in your app where it crashed
- Stack trace showing only your app files — no vendor noise
- Number of queries captured before the crash

> Set `APP_DEBUG=true` in your `.env` for full exception details.

### Client Error Display

[](#client-error-display)

When your endpoint returns a 4xx response (e.g. 422 validation error, 404), QueryCraft shows:

- The HTTP status code
- The error message returned by your API
- Suggestions for similar routes if 404

### Config Panel

[](#config-panel)

Click the ⚙️ icon in the top-right header to open the config panel:

- Toggle each detector on/off individually
- Adjust thresholds using sliders
- Tune score weights (must total 100%)
- Click **Save** — changes are written to your `.env` immediately
- Click **Reset** to restore all defaults

---

⌨️ Artisan Command
------------------

[](#️-artisan-command)

Analyze endpoints directly from your terminal without opening a browser.

### Signature

[](#signature)

```
php artisan querycraft:analyze
    {--url=         : The endpoint URL to analyze}
    {--method=GET   : HTTP method (GET, POST, PUT, PATCH, DELETE)}
    {--user=        : Authenticate as a specific user ID}
    {--show-queries : Print all executed queries in the output}
    {--body=        : JSON body as an inline string}
    {--body-file=   : Path to a JSON file to use as the request body}
    {--header=*     : Custom headers in Key:Value format (repeatable)}

```

### Examples

[](#examples)

```
# Simple GET
php artisan querycraft:analyze --url=/users

# With authentication
php artisan querycraft:analyze --url=/dashboard --user=1

# POST with inline JSON body
php artisan querycraft:analyze --url=/api/posts --method=POST \
  --body='{"title":"Hello","body":"World","category_id":1}'

# POST with many fields — use --body-file to keep it clean
php artisan querycraft:analyze --url=/api/orders --method=POST \
  --body-file=./payload.json

# PUT with body and auth
php artisan querycraft:analyze --url=/api/users/1 --method=PUT --user=1 \
  --body='{"name":"John","email":"john@example.com"}'

# With custom headers
php artisan querycraft:analyze --url=/api/secret \
  --header="Authorization:Bearer your-token" \
  --header="X-Team-Id:42"

# Everything combined
php artisan querycraft:analyze --url=/api/orders --method=POST --user=1 \
  --body-file=./payload.json \
  --header="X-Source:querycraft" \
  --show-queries
```

### Sending a large body with `--body-file`

[](#sending-a-large-body-with---body-file)

When your request has many fields, create a `payload.json` file instead of cramming everything inline:

```
{
  "customer_id": 5,
  "shipping_address": {
    "street": "123 Main St",
    "city": "Paris",
    "zip": "75001"
  },
  "items": [
    { "product_id": 1, "qty": 2, "price": 29.99 },
    { "product_id": 3, "qty": 1, "price": 49.99 }
  ],
  "coupon": "SAVE10",
  "notes": "Leave at door"
}
```

Then run:

```
php artisan querycraft:analyze --url=/api/orders --method=POST \
  --body-file=./payload.json --user=1 --show-queries
```

> Use `--body` for small payloads. Use `--body-file` for large or complex payloads — it avoids shell escaping issues and is much easier to read and reuse.

### Example output

[](#example-output)

```
🔍 Analyzing: GET /users

✅ Response: 200

📊 Summary:
+----------------+----------+
| Metric         | Value    |
+----------------+----------+
| Total Queries  | 23       |
| Total Time     | 182.5 ms |
| Avg Query Time | 7.93 ms  |
| Response Status| 200      |
+----------------+----------+

⚠️  Found 2 issue(s):

🔴 Issue #1: N+1
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Severity: HIGH
Occurrences: 20
Total Time: 140ms
Location: /app/Http/Controllers/UserController.php:45

Query:
  select * from `companies` where `id` = ?

💡 Suggestion:
  Add eager loading: ->with('company')

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚡ Performance Score: 62/100 (Grade: D) 🟠
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

🎯 Top Improvements:
  • Too many queries (+25 points)
  • 2 performance issues detected (+20 points)

```

> If your endpoint requires authentication, pass `--user=1` to run as a specific user. QueryCraft calls `auth()->login($user)` before firing the request.

---

⚙️ Configuration
----------------

[](#️-configuration)

After publishing, the config file is at `config/querycraft.php`. All values can be overridden via `.env`:

```
# Enable or disable the package entirely
QUERY_DEBUGGER_ENABLED=true

# Detectors — toggle individually
QUERYCRAFT_DETECTOR_N1=true
QUERYCRAFT_DETECTOR_SLOW_QUERY=true
QUERYCRAFT_DETECTOR_MISSING_INDEX=true
QUERYCRAFT_DETECTOR_DUPLICATE_QUERY=true

# Thresholds
QUERY_DEBUGGER_N1_THRESHOLD=5        # Flag N+1 after this many repetitions (default: 5)
QUERY_DEBUGGER_SLOW_THRESHOLD=100    # Flag queries slower than this in ms (default: 100)
QUERYCRAFT_DUPLICATE_COUNT=2         # Flag duplicates after this many repeats (default: 2)

# Score weights — must total 100
QUERYCRAFT_WEIGHT_QUERY_COUNT=40
QUERYCRAFT_WEIGHT_QUERY_TIME=30
QUERYCRAFT_WEIGHT_ISSUES=30

# Dashboard route prefix (default: querycraft)
QUERYCRAFT_DASHBOARD_ROUTE=querycraft
```

### Full config reference

[](#full-config-reference)

```
// config/querycraft.php
return [
    'enabled' => env('QUERY_DEBUGGER_ENABLED', true),

    'detectors' => [
        'n1'             => env('QUERYCRAFT_DETECTOR_N1', true),
        'slow_query'     => env('QUERYCRAFT_DETECTOR_SLOW_QUERY', true),
        'missing_index'  => env('QUERYCRAFT_DETECTOR_MISSING_INDEX', true),
        'duplicate_query'=> env('QUERYCRAFT_DETECTOR_DUPLICATE_QUERY', true),
    ],

    'thresholds' => [
        'n1_count'        => env('QUERY_DEBUGGER_N1_THRESHOLD', 5),
        'slow_query_ms'   => env('QUERY_DEBUGGER_SLOW_THRESHOLD', 100),
        'duplicate_count' => env('QUERYCRAFT_DUPLICATE_COUNT', 2),
    ],

    'weights' => [
        'query_count' => env('QUERYCRAFT_WEIGHT_QUERY_COUNT', 40),
        'query_time'  => env('QUERYCRAFT_WEIGHT_QUERY_TIME', 30),
        'issues'      => env('QUERYCRAFT_WEIGHT_ISSUES', 30),
    ],
];
```

> **Tip:** All settings can also be changed from the dashboard ⚙️ config panel — changes are saved directly to your `.env`.

---

🔬 How Detectors Work
--------------------

[](#-how-detectors-work)

### 🔁 N+1 Detection

[](#-n1-detection)

Normalizes every query (replaces values with `?`) and groups them by pattern. If the same pattern fires more than `n1_count` times, it's flagged. The exact file and line in your app that triggered the repeated query is shown.

**Example:**

```
// ❌ N+1 — fires one query per user
$users = User::all();
foreach ($users as $user) {
    echo $user->company->name;
}

// ✅ Fix — one query total
$users = User::with('company')->get();
```

CountSeverity5–10×low10–20×medium20–50×high50×+critical---

### 🐢 Slow Query Detection

[](#-slow-query-detection)

Flags any query exceeding `slow_query_ms` milliseconds (default: 100ms). Automatically suggests a fix based on the query structure.

TimeSeverity&gt; 200mslow&gt; 500msmedium&gt; 1000mshigh&gt; 1000mscritical**Suggestions shown:**

- `SELECT *` → use specific columns
- `ORDER BY` without `LIMIT` → add a limit
- `LIKE` queries → consider full-text search
- `COUNT(*)` on large tables → consider caching

---

### 🗂 Missing Index Detection

[](#-missing-index-detection)

Runs MySQL `EXPLAIN` on each query and flags full table scans, filesorts, and temporary table usage.

**Triggers:**

- `type = ALL` with more than 1,000 rows examined
- `Extra` contains `Using filesort`
- `Extra` contains `Using temporary`

**Example:**

```
User::where('email', $email)->first(); // no index on email

// Fix — in a migration:
$table->index('email');
$table->index(['status', 'created_at']); // composite
```

Rows examinedSeverity&gt; 1,000low&gt; 10,000medium&gt; 100,000high&gt; 100,000critical---

### 📋 Duplicate Query Detection

[](#-duplicate-query-detection)

Creates an `md5` fingerprint of `sql + bindings`. If the exact same query with the same parameter values runs more than `duplicate_count` times (default: 2), it's flagged.

**Example:**

```
// ❌ Duplicate — same query + same values fired twice
$settings = Setting::all();
// ... somewhere else in the same request ...
$settings = Setting::all();

// ✅ Fix
$settings = Cache::remember('settings', 3600, fn() => Setting::all());
```

---

💯 Performance Score
-------------------

[](#-performance-score)

Calculated as a weighted average across three dimensions:

DimensionDefault WeightDescriptionQuery Count40%Fewer queries = higher scoreQuery Time30%Faster total time = higher scoreIssues Found30%Fewer/lower severity issues = higher scoreScoreGradeStatus90–100A 🟢Excellent80–89B 🟡Good70–79C 🟡Acceptable60–69D 🟠Below average0–59F 🔴Critical issuesWeights are configurable from the dashboard config panel or via `.env`.

---

🔒 Security
----------

[](#-security)

QueryCraft is intended for **local development only**. Always disable it in production:

```
# .env.production
QUERY_DEBUGGER_ENABLED=false
```

---

🔄 Updating
----------

[](#-updating)

```
composer update romdh4ne/laravel-querycraft
php artisan vendor:publish --tag=querycraft-views --force
php artisan vendor:publish --tag=querycraft-assets --force
php artisan config:clear
php artisan view:clear
```

---

🗑 Uninstalling
--------------

[](#-uninstalling)

```
composer remove romdh4ne/laravel-querycraft
rm config/querycraft.php
rm -rf resources/views/vendor/querycraft
rm -rf public/vendor/querycraft
# Remove QUERYCRAFT_* and QUERY_DEBUGGER_* lines from your .env
```

---

🤝 Contributing
--------------

[](#-contributing)

### Setup

[](#setup)

```
git clone https://github.com/YOUR_USERNAME/laravel-querycraft.git
cd laravel-querycraft
composer install
```

### Local test app (separate project)

[](#local-test-app-separate-project)

In a separate Laravel app, add to `composer.json`:

```
"repositories": [
    {
        "type": "path",
        "url": "../laravel-querycraft",
        "options": { "symlink": true }
    }
]
```

Then:

```
composer require romdh4ne/laravel-querycraft:@dev
php artisan vendor:publish --tag=querycraft-config
php artisan vendor:publish --tag=querycraft-assets
php artisan config:clear
php artisan serve
```

Visit `http://localhost:8000/querycraft`. Any change you make in the package reflects instantly thanks to the symlink.

📄 License
---------

[](#-license)

QueryCraft is open-source software licensed under the [MIT license](LICENSE).

---

👨‍💻 Author
----------

[](#‍-author)

Made by [Romdh4ne](https://github.com/Romdh4ne)

If this package helps you, give it a ⭐ on GitHub!

###  Health Score

40

—

FairBetter than 88% of packages

Maintenance82

Actively maintained with recent releases

Popularity16

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

5

Last Release

91d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/49535083?v=4)[Mohamed Romdhane](/maintainers/romdh4ne)[@romdh4ne](https://github.com/romdh4ne)

---

Top Contributors

[![romdh4ne](https://avatars.githubusercontent.com/u/49535083?v=4)](https://github.com/romdh4ne "romdh4ne (7 commits)")

---

Tags

laraveldatabaseperformanceoptimizationqueriesn-plus-one

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/romdh4ne-laravel-querycraft/health.svg)

```
[![Health](https://phpackages.com/badges/romdh4ne-laravel-querycraft/health.svg)](https://phpackages.com/packages/romdh4ne-laravel-querycraft)
```

###  Alternatives

[clickbar/laravel-magellan

This package provides functionality for working with the postgis extension in Laravel.

423715.4k1](/packages/clickbar-laravel-magellan)[sarfraznawaz2005/meter

laravel package to find performance bottlenecks in your laravel application.

2498.1k](/packages/sarfraznawaz2005-meter)[sarfraznawaz2005/indexer

Laravel package to monitor SELECT queries and offer best possible INDEX fields.

562.7k](/packages/sarfraznawaz2005-indexer)[toponepercent/baum

Baum is an implementation of the Nested Set pattern for Eloquent models.

3154.7k](/packages/toponepercent-baum)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
