├── .php-cs-fixer.dist.php ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── composer.json ├── config └── sql-commenter.php └── src ├── Comment.php ├── Commenters ├── Commenter.php ├── ControllerCommenter.php ├── CurrentUserCommenter.php ├── DbDriverCommenter.php ├── FileCommenter.php ├── FrameworkVersionCommenter.php ├── JobCommenter.php └── RouteCommenter.php ├── Exceptions └── InvalidSqlCommenter.php ├── SqlCommenter.php └── SqlCommenterServiceProvider.php /.php-cs-fixer.dist.php: -------------------------------------------------------------------------------- 1 | in([ 5 | __DIR__ . '/src', 6 | __DIR__ . '/tests', 7 | ]) 8 | ->name('*.php') 9 | ->notName('*.blade.php') 10 | ->ignoreDotFiles(true) 11 | ->ignoreVCS(true); 12 | 13 | return (new PhpCsFixer\Config()) 14 | ->setRules([ 15 | '@PSR12' => true, 16 | 'array_syntax' => ['syntax' => 'short'], 17 | 'ordered_imports' => ['sort_algorithm' => 'alpha'], 18 | 'no_unused_imports' => true, 19 | 'not_operator_with_successor_space' => true, 20 | 'trailing_comma_in_multiline' => true, 21 | 'phpdoc_scalar' => true, 22 | 'unary_operator_spaces' => true, 23 | 'binary_operator_spaces' => true, 24 | 'blank_line_before_statement' => [ 25 | 'statements' => ['break', 'continue', 'declare', 'return', 'throw', 'try'], 26 | ], 27 | 'phpdoc_single_line_var_spacing' => true, 28 | 'phpdoc_var_without_name' => true, 29 | 'class_attributes_separation' => [ 30 | 'elements' => [ 31 | 'method' => 'one', 32 | ], 33 | ], 34 | 'method_argument_space' => [ 35 | 'on_multiline' => 'ensure_fully_multiline', 36 | 'keep_multiple_spaces_after_comma' => true, 37 | ], 38 | 'single_trait_insert_per_statement' => true, 39 | ]) 40 | ->setFinder($finder); 41 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to `laravel-sql-commenter` will be documented in this file. 4 | 5 | ## 2.1.1 - 2025-02-21 6 | 7 | ### What's Changed 8 | 9 | * Bump dependabot/fetch-metadata from 2.2.0 to 2.3.0 by @dependabot in https://github.com/spatie/laravel-sql-commenter/pull/29 10 | * Laravel 12.x Compatibility by @laravel-shift in https://github.com/spatie/laravel-sql-commenter/pull/30 11 | 12 | ### New Contributors 13 | 14 | * @laravel-shift made their first contribution in https://github.com/spatie/laravel-sql-commenter/pull/30 15 | 16 | **Full Changelog**: https://github.com/spatie/laravel-sql-commenter/compare/2.1.0...2.1.1 17 | 18 | ## 2.1.0 - 2024-10-18 19 | 20 | ### What's Changed 21 | 22 | * Bump dependabot/fetch-metadata from 1.6.0 to 2.2.0 by @dependabot in https://github.com/spatie/laravel-sql-commenter/pull/25 23 | * Bump dependabot/fetch-metadata from 1.6.0 to 2.2.0 by @dependabot in https://github.com/spatie/laravel-sql-commenter/pull/27 24 | * Add support for adding connections after boot by @jholloman in https://github.com/spatie/laravel-sql-commenter/pull/26 25 | 26 | ### New Contributors 27 | 28 | * @jholloman made their first contribution in https://github.com/spatie/laravel-sql-commenter/pull/26 29 | 30 | **Full Changelog**: https://github.com/spatie/laravel-sql-commenter/compare/2.0.0...2.1.0 31 | 32 | ## 2.0.0 - 2024-03-14 33 | 34 | ### Upgrade guide 35 | 36 | You can no longer call `SqlCommenter::addComment` statically, you now need to fetch the commenter instance from the container or have it dependency injected into your code. 37 | 38 | ```diff 39 | - SqlCommenter::addComment('My comment'); 40 | + app(SqlCommenter::class)->addComment('My comment'); 41 | 42 | 43 | 44 | ``` 45 | ### What's Changed 46 | 47 | * Bump spatie/invade version to 2.0 by @vigneshgurusamy in https://github.com/spatie/laravel-sql-commenter/pull/19 48 | * Add support for laravel 11 by @shuvroroy in https://github.com/spatie/laravel-sql-commenter/pull/20 49 | * Add Octane compatibility by @riasvdv in https://github.com/spatie/laravel-sql-commenter/pull/22 50 | 51 | ### New Contributors 52 | 53 | * @shuvroroy made their first contribution in https://github.com/spatie/laravel-sql-commenter/pull/20 54 | * @riasvdv made their first contribution in https://github.com/spatie/laravel-sql-commenter/pull/22 55 | 56 | **Full Changelog**: https://github.com/spatie/laravel-sql-commenter/compare/1.4.0...2.0.0 57 | 58 | ## 1.4.0 - 2023-07-11 59 | 60 | ### What's Changed 61 | 62 | - Bump dependabot/fetch-metadata from 1.3.5 to 1.3.6 by @dependabot in https://github.com/spatie/laravel-sql-commenter/pull/12 63 | - Bump dependabot/fetch-metadata from 1.3.6 to 1.4.0 by @dependabot in https://github.com/spatie/laravel-sql-commenter/pull/14 64 | - Bump dependabot/fetch-metadata from 1.4.0 to 1.5.1 by @dependabot in https://github.com/spatie/laravel-sql-commenter/pull/15 65 | - Bump dependabot/fetch-metadata from 1.5.1 to 1.6.0 by @dependabot in https://github.com/spatie/laravel-sql-commenter/pull/16 66 | - Add support for commenting multiple database connections by @alexthekiwi in https://github.com/spatie/laravel-sql-commenter/pull/13 67 | 68 | ### New Contributors 69 | 70 | - @alexthekiwi made their first contribution in https://github.com/spatie/laravel-sql-commenter/pull/13 71 | 72 | **Full Changelog**: https://github.com/spatie/laravel-sql-commenter/compare/1.3.1...1.4.0 73 | 74 | ## 1.3.1 - 2023-01-26 75 | 76 | - support L10 77 | 78 | ## 1.3.0 - 2023-01-16 79 | 80 | ### What's Changed 81 | 82 | - Bump dependabot/fetch-metadata from 1.3.4 to 1.3.5 by @dependabot in https://github.com/spatie/laravel-sql-commenter/pull/8 83 | - Added ability to use relative path in FileCommenter by @peresmishnyk in https://github.com/spatie/laravel-sql-commenter/pull/11 84 | 85 | ### New Contributors 86 | 87 | - @peresmishnyk made their first contribution in https://github.com/spatie/laravel-sql-commenter/pull/11 88 | 89 | **Full Changelog**: https://github.com/spatie/laravel-sql-commenter/compare/1.2.0...1.3.0 90 | 91 | ## 1.2.0 - 2022-10-14 92 | 93 | ### What's Changed 94 | 95 | - Bump dependabot/fetch-metadata from 1.3.3 to 1.3.4 by @dependabot in https://github.com/spatie/laravel-sql-commenter/pull/6 96 | - Add exclude path segment property for FileCommenter by @vigneshgurusamy in https://github.com/spatie/laravel-sql-commenter/pull/7 97 | 98 | ### New Contributors 99 | 100 | - @vigneshgurusamy made their first contribution in https://github.com/spatie/laravel-sql-commenter/pull/7 101 | 102 | **Full Changelog**: https://github.com/spatie/laravel-sql-commenter/compare/1.1.1...1.2.0 103 | 104 | ## 1.1.1 - 2022-07-04 105 | 106 | - prevent infinite loop when getting authenticated user 107 | 108 | ## 1.1.0 - 2022-07-04 109 | 110 | - add user commenter 111 | - fix config:cache issue 112 | - filter empty comments 113 | 114 | ## 1.0.0 - 2022-07-02 115 | 116 | - initial release 117 | 118 | ## 0.0.3 - 2022-07-02 119 | 120 | - experimental release 121 | 122 | ## 0.0.2 - 2022-07-02 123 | 124 | - experimental release 125 | 126 | ## 0.0.1 - 2022-07-02 127 | 128 | - experimental release 129 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) spatie 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Add comments to SQL queries made by Laravel 2 | 3 | [![Latest Version on Packagist](https://img.shields.io/packagist/v/spatie/laravel-sql-commenter.svg?style=flat-square)](https://packagist.org/packages/spatie/laravel-sql-commenter) 4 | [![GitHub Tests Action Status](https://img.shields.io/github/workflow/status/spatie/laravel-sql-commenter/run-tests?label=tests)](https://github.com/spatie/laravel-sql-commenter/actions?query=workflow%3Arun-tests+branch%3Amain) 5 | [![GitHub Code Style Action Status](https://img.shields.io/github/workflow/status/spatie/laravel-sql-commenter/Check%20&%20fix%20styling?label=code%20style)](https://github.com/spatie/laravel-sql-commenter/actions?query=workflow%3A"Check+%26+fix+styling"+branch%3Amain) 6 | [![Total Downloads](https://img.shields.io/packagist/dt/spatie/laravel-sql-commenter.svg?style=flat-square)](https://packagist.org/packages/spatie/laravel-sql-commenter) 7 | 8 | This package can add comments to queries performed by Laravel. These comments will use the [sqlcommenter](https://google.github.io/sqlcommenter/) format, which is understood by various tools and services, such as [PlanetScale's Query Insights](https://docs.planetscale.com/concepts/query-insights). 9 | 10 | Here's what a query looks like by default: 11 | 12 | ```mysql 13 | select * from users 14 | ``` 15 | 16 | Using this package, comments like this one will be added. 17 | 18 | ```mysql 19 | select * from "users"/*controller='UsersController',action='index'*/; 20 | ``` 21 | 22 | The comments allow you easily pinpoint the source of the query in your codebase. 23 | 24 | 25 | ## Support us 26 | 27 | [](https://spatie.be/github-ad-click/laravel-sql-commenter) 28 | 29 | We invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us). 30 | 31 | We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on [our contact page](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards). 32 | 33 | ## Installation 34 | 35 | You can install the package via composer: 36 | 37 | ```bash 38 | composer require spatie/laravel-sql-commenter 39 | ``` 40 | 41 | Optionally, you can publish the config file with: 42 | 43 | ```bash 44 | php artisan vendor:publish --tag="sql-commenter-config" 45 | ``` 46 | 47 | This is the content of the published config file: 48 | 49 | ```php 50 | return [ 51 | /* 52 | * When set to true, comments will be added to all your queries 53 | */ 54 | 'enabled' => true, 55 | 56 | /* 57 | * These classes add comments to an executed query. 58 | */ 59 | 'commenters' => [ 60 | Spatie\SqlCommenter\Commenters\ControllerCommenter::class => ['includeNamespace' => false], 61 | Spatie\SqlCommenter\Commenters\RouteCommenter::class, 62 | Spatie\SqlCommenter\Commenters\JobCommenter::class => ['includeNamespace' => false], 63 | Spatie\SqlCommenter\Commenters\FileCommenter::class => [ 64 | 'backtraceLimit' => 20, 65 | 'excludePathSegments' => [], 66 | 'useRelativePath' => false, 67 | ], 68 | Spatie\SqlCommenter\Commenters\CurrentUserCommenter::class, 69 | // Spatie\SqlCommenter\Commenters\FrameworkVersionCommenter::class, 70 | // Spatie\SqlCommenter\Commenters\DbDriverCommenter::class, 71 | ], 72 | 73 | /* 74 | * If you need fine-grained control over the logging, you can extend 75 | * the SqlCommenter class and specify your custom class here 76 | */ 77 | 'commenter_class' => Spatie\SqlCommenter\SqlCommenter::class, 78 | ]; 79 | ``` 80 | 81 | ## Usage 82 | 83 | With the package installed, comments are automatically added. By publishing the config file, you can choose which things are added to the comments. 84 | 85 | ### Adding arbitrary comments 86 | 87 | If you want to add other arbitrary comments to the SqlComment, you can use the `addComment` method. The given comment will be added to the next performed query. 88 | 89 | ```php 90 | use Spatie\SqlCommenter\SqlCommenter; 91 | 92 | app(SqlCommenter::class)->addComment('foo', 'bar'); 93 | 94 | // select * from "users"/*foo='bar'*/; 95 | ``` 96 | 97 | ### Dynamically enabling and disabling adding comments 98 | 99 | You can dynamically enable and disable query logging. 100 | 101 | Let's assume that you only want to add comments for a certain part in your code base. First, you would need to set the value of the `enabled` key in the `sql-commenter` config file to `false`. This will stop the package from adding comments to all queries. Right before the part where you want to add comments, call `SqlCommenter::enable()` and at the end call `SqlCommenter::disable()` 102 | 103 | ```php 104 | use \Spatie\SqlCommenter\SqlCommenter; 105 | 106 | // queries performed here won't have comments 107 | 108 | SqlCommenter::enable(); 109 | 110 | // queries performed here will have comments 111 | 112 | SqlCommenter::disable(); 113 | 114 | // queries performed here won't have comments 115 | ``` 116 | 117 | ### Adding you own commentator 118 | 119 | If you want to add a comment to all performed queries, you can create your own `Commentator` class. It should implement the `Spatie\SqlCommenter\Commenters\Commenter` interface. The `comments` function should return a single or an array of `Spatie\SqlCommenter\Comment`. 120 | 121 | Here's an example: 122 | 123 | ```php 124 | namespace App\Support\SqlCommenters; 125 | 126 | use Illuminate\Database\Connection; 127 | use Spatie\SqlCommenter\Comment; 128 | 129 | class MyCustomCommenter implements Commenter 130 | { 131 | /** @return Comment|array|null */ 132 | public function comments(string $query, Connection $connection): Comment|array|null 133 | { 134 | return new Comment('my-custom-key', 'my-custom-value'); 135 | } 136 | } 137 | ``` 138 | 139 | ## Testing 140 | 141 | ```bash 142 | composer test 143 | ``` 144 | 145 | ## Changelog 146 | 147 | Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. 148 | 149 | ## Contributing 150 | 151 | Please see [CONTRIBUTING](https://github.com/riasvdv/.github/blob/main/CONTRIBUTING.md) for details. 152 | 153 | ## Security Vulnerabilities 154 | 155 | Please review [our security policy](../../security/policy) on how to report security vulnerabilities. 156 | 157 | ## Credits 158 | 159 | - [Rias Van der Veken](https://github.com/riasvdv) 160 | - [Freek Van der Herten](https://github.com/freekmurze) 161 | - [All Contributors](../../contributors) 162 | 163 | ## License 164 | 165 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 166 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spatie/laravel-sql-commenter", 3 | "description": "Add comments to SQL queries made by Laravel", 4 | "keywords": [ 5 | "spatie", 6 | "laravel", 7 | "sqlcommenter", 8 | "sql-commenter" 9 | ], 10 | "homepage": "https://github.com/spatie/laravel-sql-commenter", 11 | "license": "MIT", 12 | "authors": [ 13 | { 14 | "name": "Rias Van der Veken", 15 | "email": "rias@spatie.be", 16 | "role": "Developer" 17 | }, 18 | { 19 | "name": "Freek Van der Herten", 20 | "email": "freek@spatie.be", 21 | "role": "Developer" 22 | } 23 | ], 24 | "require": { 25 | "php": "^8.1", 26 | "illuminate/contracts": "^9.0|^10.0|^11.0|^12.0", 27 | "spatie/backtrace": "^1.2", 28 | "spatie/invade": "^1.1|^2.0", 29 | "spatie/laravel-package-tools": "^1.12" 30 | }, 31 | "require-dev": { 32 | "nunomaduro/collision": "^6.2|^8.0", 33 | "orchestra/testbench": "^7.6|^8.0|^9.0|^10.0", 34 | "pestphp/pest": "^1.21|^2.0|^3.7", 35 | "pestphp/pest-plugin-laravel": "^1.2|^2.0|^3.1", 36 | "phpstan/extension-installer": "^1.1", 37 | "phpstan/phpstan-deprecation-rules": "^1.0|^2.0", 38 | "phpstan/phpstan-phpunit": "^1.1|^2.0", 39 | "phpunit/phpunit": "^9.5|^10.0|^11.5.3", 40 | "spatie/laravel-ray": "^1.29" 41 | }, 42 | "autoload": { 43 | "psr-4": { 44 | "Spatie\\SqlCommenter\\": "src", 45 | "Spatie\\SqlCommenter\\Database\\Factories\\": "database/factories" 46 | } 47 | }, 48 | "autoload-dev": { 49 | "psr-4": { 50 | "Spatie\\SqlCommenter\\Tests\\": "tests" 51 | } 52 | }, 53 | "scripts": { 54 | "analyse": "vendor/bin/phpstan analyse", 55 | "test": "vendor/bin/pest", 56 | "test-coverage": "vendor/bin/pest --coverage", 57 | "format": "vendor/bin/php-cs-fixer fix --allow-risky=yes" 58 | }, 59 | "config": { 60 | "sort-packages": true, 61 | "allow-plugins": { 62 | "pestphp/pest-plugin": true, 63 | "phpstan/extension-installer": true 64 | } 65 | }, 66 | "extra": { 67 | "laravel": { 68 | "providers": [ 69 | "Spatie\\SqlCommenter\\SqlCommenterServiceProvider" 70 | ] 71 | } 72 | }, 73 | "minimum-stability": "dev", 74 | "prefer-stable": true 75 | } 76 | -------------------------------------------------------------------------------- /config/sql-commenter.php: -------------------------------------------------------------------------------- 1 | true, 8 | 9 | /* 10 | * These classes add comments to an executed query. 11 | */ 12 | 'commenters' => [ 13 | Spatie\SqlCommenter\Commenters\ControllerCommenter::class => ['includeNamespace' => false], 14 | Spatie\SqlCommenter\Commenters\RouteCommenter::class, 15 | Spatie\SqlCommenter\Commenters\JobCommenter::class => ['includeNamespace' => false], 16 | Spatie\SqlCommenter\Commenters\FileCommenter::class => [ 17 | 'backtraceLimit' => 20, 18 | 'excludePathSegments' => [], 19 | 'useRelativePath' => false, 20 | ], 21 | Spatie\SqlCommenter\Commenters\CurrentUserCommenter::class, 22 | // Spatie\SqlCommenter\Commenters\FrameworkVersionCommenter::class, 23 | // Spatie\SqlCommenter\Commenters\DbDriverCommenter::class, 24 | ], 25 | 26 | /* 27 | * If you need fine-grained control over the logging, you can extend 28 | * the SqlCommenter class and specify your custom class here 29 | */ 30 | 'commenter_class' => Spatie\SqlCommenter\SqlCommenter::class, 31 | 32 | /** 33 | * The database connections for which you want to add comments. 34 | * Defaults to the default connection defined in config/database.php 35 | */ 36 | 'connections' => [ 37 | // 'mysql', 38 | ], 39 | ]; 40 | -------------------------------------------------------------------------------- /src/Comment.php: -------------------------------------------------------------------------------- 1 | $comments 17 | * 18 | * @return string 19 | */ 20 | public static function formatCollection(Collection $comments): string 21 | { 22 | if ($comments->isEmpty()) { 23 | return ''; 24 | } 25 | 26 | $commentsAsString = $comments 27 | ->map(fn (Comment $comment) => (string)$comment) 28 | ->join(","); 29 | 30 | return str($commentsAsString) 31 | ->prepend('/*') 32 | ->append("*/"); 33 | } 34 | 35 | public function __construct( 36 | public string $key, 37 | public ?string $value, 38 | ) { 39 | } 40 | 41 | public function __toString(): string 42 | { 43 | return urlencode($this->key) . "=" . "'" . urlencode($this->value) . "'"; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Commenters/Commenter.php: -------------------------------------------------------------------------------- 1 | route()) { 20 | return null; 21 | } 22 | 23 | [$controller, $action] = $this->getControllerAndAction(); 24 | 25 | return [ 26 | Comment::make('controller', $controller), 27 | Comment::make('action', $action), 28 | ]; 29 | } 30 | 31 | /** 32 | * @return array{ 33 | * 0: class-string, 34 | * 1: string, 35 | * } 36 | */ 37 | protected function getControllerAndAction(): array 38 | { 39 | $action = request()->route()->getAction('uses'); 40 | 41 | if ($action instanceof Closure) { 42 | $reflection = new ReflectionClosure($action); 43 | $controller = 'Closure'; 44 | $action = $reflection->getFileName(); 45 | 46 | return [$controller, $action]; 47 | } 48 | 49 | $controller = explode('@', $action)[0] ?? null; 50 | 51 | if (! $this->includeNamespace) { 52 | $controller = class_basename($controller); 53 | } 54 | 55 | $action = explode('@', $action)[1] ?? null; 56 | 57 | return [$controller, $action]; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Commenters/CurrentUserCommenter.php: -------------------------------------------------------------------------------- 1 | user(); 17 | 18 | SqlCommenter::enable(); 19 | 20 | if (! $user) { 21 | return null; 22 | } 23 | 24 | return [ 25 | Comment::make('user_id', $user->getKey()), 26 | Comment::make('user_email', $user->email ?? ''), 27 | ]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Commenters/DbDriverCommenter.php: -------------------------------------------------------------------------------- 1 | getConfig('driver')); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Commenters/FileCommenter.php: -------------------------------------------------------------------------------- 1 | limit($this->backtraceLimit)->frames(); 25 | 26 | $frame = collect($frames) 27 | ->first(function (Frame $frame) { 28 | if ($frame->lineNumber === 0) { 29 | return false; 30 | } 31 | 32 | $ignoredPathSegments = array_merge([ 33 | 'laravel-sql-commenter/src', 34 | 'laravel/framework', 35 | ], $this->excludePathSegments); 36 | 37 | foreach ($ignoredPathSegments as $ignoredPathSegment) { 38 | $segment = str_replace('/', DIRECTORY_SEPARATOR, "/{$ignoredPathSegment}/"); 39 | 40 | if (str_contains($frame->file, $segment)) { 41 | return false; 42 | } 43 | } 44 | 45 | return true; 46 | }); 47 | 48 | if (! $frame) { 49 | return null; 50 | } 51 | 52 | $filePath = $this->useRelativePath && str_starts_with($frame->file, base_path()) 53 | ? substr($frame->file, strlen(base_path()) + 1) 54 | : $frame->file; 55 | 56 | return [ 57 | Comment::make('file', $filePath), 58 | Comment::make('line', $frame->lineNumber), 59 | ]; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Commenters/FrameworkVersionCommenter.php: -------------------------------------------------------------------------------- 1 | version()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Commenters/JobCommenter.php: -------------------------------------------------------------------------------- 1 | runningInConsole()) { 20 | return null; 21 | } 22 | 23 | try { 24 | /** @phpstan-ignore-next-line */ 25 | $pipeline = invade(app(Dispatcher::class))->pipeline; 26 | 27 | /** @phpstan-ignore-next-line */ 28 | $job = invade($pipeline)->passable; 29 | } catch (Throwable) { 30 | return null; 31 | } 32 | 33 | if ($job) { 34 | $job = $job::class; 35 | 36 | if (! $this->includeNamespace) { 37 | $job = class_basename($job); 38 | } 39 | } 40 | 41 | return Comment::make('job', $job); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Commenters/RouteCommenter.php: -------------------------------------------------------------------------------- 1 | getPathInfo()), 15 | Comment::make('route', request()->route()?->getName()), 16 | ]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Exceptions/InvalidSqlCommenter.php: -------------------------------------------------------------------------------- 1 | */ 14 | protected array $extraComments = []; 15 | 16 | public function addComment(string $key, ?string $value): void 17 | { 18 | $this->extraComments[$key] = Comment::make($key, $value); 19 | } 20 | 21 | public static function enable(): void 22 | { 23 | config()->set('sql-commenter.enabled', true); 24 | } 25 | 26 | public static function disable(): void 27 | { 28 | config()->set('sql-commenter.enabled', false); 29 | } 30 | 31 | public function commentQuery(string $query, Connection $connection, array $commenters): string 32 | { 33 | if (! $this->shouldAddComments($query, $connection)) { 34 | return $query; 35 | } 36 | 37 | if (str_contains($query, '/*')) { 38 | return $query; 39 | } 40 | 41 | $commenters = $this->getCommenters($query, $connection, $commenters); 42 | 43 | $comments = $this->getCommentsFromCommenters($commenters, $connection, $query); 44 | 45 | $this->addExtraComments($comments, $query, $connection); 46 | 47 | $comments = $this->filterEmptyComments($comments); 48 | 49 | return $this->addCommentsToQuery($query, $comments); 50 | } 51 | 52 | protected function shouldAddComments(string $query, Connection $connection): bool 53 | { 54 | return config('sql-commenter.enabled'); 55 | } 56 | 57 | /** 58 | * @param string $query 59 | * @param Connection $connection 60 | * @param array $commenters 61 | * 62 | * @return array 63 | */ 64 | protected function getCommenters(string $query, Connection $connection, array $commenters): array 65 | { 66 | return $commenters; 67 | } 68 | 69 | /** 70 | * @param array $commenters 71 | * @param \Illuminate\Database\Connection $connection 72 | * @param string $query 73 | * 74 | * @return Collection 75 | */ 76 | protected function getCommentsFromCommenters( 77 | array $commenters, 78 | Connection $connection, 79 | string $query, 80 | ): Collection { 81 | return collect($commenters) 82 | ->flatMap(function (Commenter $commenter) use ($connection, $query) { 83 | $comments = $commenter->comments($query, $connection) ?? []; 84 | 85 | return Arr::wrap($comments); 86 | }) 87 | ->filter(); 88 | } 89 | 90 | /** 91 | * @param Collection $comments 92 | * @param string $query 93 | * @param Connection $connection 94 | * 95 | * @return void 96 | */ 97 | protected function addExtraComments(Collection $comments, string $query, Connection $connection): void 98 | { 99 | $comments->push(...$this->extraComments); 100 | 101 | $this->extraComments = []; 102 | } 103 | 104 | /** 105 | * @param string $query 106 | * @param Collection $comments 107 | * 108 | * @return string 109 | */ 110 | protected function addCommentsToQuery(string $query, Collection $comments): string 111 | { 112 | $query = Str::finish(trim($query), ';'); 113 | 114 | if (Str::endsWith($query, ';')) { 115 | return rtrim($query, ";") . Comment::formatCollection($comments) . ';'; 116 | } 117 | 118 | return $query . Comment::formatCollection($comments); 119 | } 120 | 121 | /** 122 | * @param Collection $comments 123 | * 124 | * @return Collection 125 | */ 126 | protected function filterEmptyComments(Collection $comments): Collection 127 | { 128 | return $comments->filter(fn (Comment $comment) => ! empty($comment->value)); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/SqlCommenterServiceProvider.php: -------------------------------------------------------------------------------- 1 | name('laravel-sql-commenter') 18 | ->hasConfigFile(); 19 | } 20 | 21 | public function packageBooted(): void 22 | { 23 | $this->app->scoped(SqlCommenter::class, function () { 24 | $commenterClass = config('sql-commenter.commenter_class'); 25 | 26 | if (! is_a($commenterClass, SqlCommenter::class, true)) { 27 | throw InvalidSqlCommenter::make($commenterClass); 28 | } 29 | 30 | return new $commenterClass(); 31 | }); 32 | 33 | 34 | $connections = config('sql-commenter.connections', []); 35 | 36 | if (empty($connections)) { 37 | $connections = [config('database.default')]; 38 | } 39 | 40 | collect($connections)->each(fn (string $conn) => $this->initiateForConnection($conn)); 41 | } 42 | 43 | public function initiateForConnection(string $conn): void 44 | { 45 | DB::connection($conn)->beforeExecuting(function ( 46 | string &$query, 47 | array &$bindings, 48 | Connection $connection, 49 | ) { 50 | $sqlCommenter = app(SqlCommenter::class); 51 | 52 | $commenters = $this->instanciateCommenters(config('sql-commenter.commenters')); 53 | 54 | $query = $sqlCommenter->commentQuery($query, $connection, $commenters); 55 | }); 56 | } 57 | 58 | /** 59 | * @param array> $commenterClasses 60 | * 61 | * @return array 62 | */ 63 | protected function instanciateCommenters(array $commenterClasses): array 64 | { 65 | return collect($commenterClasses) 66 | ->mapWithKeys(function (array|string $options, string $commenterClass) { 67 | if (! is_array($options)) { 68 | $commenterClass = $options; 69 | 70 | $options = []; 71 | } 72 | 73 | return [$commenterClass => $options]; 74 | }) 75 | ->map(function (array $options, string $commenterClass) { 76 | return app($commenterClass, $options); 77 | }) 78 | ->toArray(); 79 | } 80 | } 81 | --------------------------------------------------------------------------------