{"id":22328152,"url":"https://github.com/shimabox/laqu","last_synced_at":"2026-05-03T04:41:41.651Z","repository":{"id":43886592,"uuid":"266645007","full_name":"shimabox/laqu","owner":"shimabox","description":"Laqu is Laravel Db Query Helper.","archived":false,"fork":false,"pushed_at":"2022-12-17T04:45:01.000Z","size":121,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-31T08:14:24.464Z","etag":null,"topics":["assertion","eloquent","laravel","query"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shimabox.png","metadata":{"files":{"readme":"README-en.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-05-24T23:56:29.000Z","updated_at":"2022-01-17T00:45:15.000Z","dependencies_parsed_at":"2023-01-29T16:45:44.249Z","dependency_job_id":null,"html_url":"https://github.com/shimabox/laqu","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shimabox%2Flaqu","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shimabox%2Flaqu/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shimabox%2Flaqu/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shimabox%2Flaqu/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shimabox","download_url":"https://codeload.github.com/shimabox/laqu/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245600160,"owners_count":20642252,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["assertion","eloquent","laravel","query"],"created_at":"2024-12-04T03:11:44.170Z","updated_at":"2026-05-03T04:41:36.602Z","avatar_url":"https://github.com/shimabox.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Laqu\n\n[ [Japanese](README.md) | English ]\n\nLaqu is **La**ravel Db **Qu**ery Helper.\n\n![Run Tests](https://github.com/shimabox/laqu/workflows/Run%20Tests/badge.svg?branch=master)\n[![License](https://poser.pugx.org/shimabox/laqu/license)](//packagist.org/packages/shimabox/laqu)\n[![Latest Stable Version](https://poser.pugx.org/shimabox/laqu/v)](//packagist.org/packages/shimabox/laqu)\n[![Maintainability](https://api.codeclimate.com/v1/badges/85b239b6865150a8acc3/maintainability)](https://codeclimate.com/github/shimabox/laqu/maintainability)\n[![Test Coverage](https://api.codeclimate.com/v1/badges/85b239b6865150a8acc3/test_coverage)](https://codeclimate.com/github/shimabox/laqu/test_coverage)\n\n## Features\n\n- Can check the executed db query\n  - Assertions in PHPUnit, sort by execution time, check queries after build, etc\n\n#### Attention\nThis library is intended to be used during development.\n\n## See Also\n\n[【Laravel】実行されたDBクエリの確認ができるやつを書いた - Qiita](https://qiita.com/shimabox/items/11b5d3e3c02e7413fc9e \"【Laravel】実行されたDBクエリの確認ができるやつを書いた - Qiita\")\n\n## Requirement\n\n- PHP 7.4+ or newer(7.4, 8.0)\n- Laravel `6.x`, `7.x`, `8.x`\n\n## Installation\n\nVia composer.\n```\n$ composer require --dev shimabox/laqu\n```\n\nDevelop.\n```\n$ git clone https://github.com/shimabox/laqu.git\n$ cd laqu\n$ composer install\n```\n\n## Usage\n\n### QueryAssertion\n\nTo assert with PHPUnit whether the expected query is flowing.\n\n```php\n\u003c?php\n\nuse App\\Repositories\\ExampleRepository; // example.\nuse Laqu\\QueryAssertion;\nuse Tests\\TestCase;\n\nclass QueryAssertionTest extends TestCase\n{\n    use QueryAssertion;\n\n    private $exampleRepository;\n\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this-\u003eexampleRepository = new ExampleRepository();\n    }\n\n    public function queryTest()\n    {\n        // Basic usage.\n        $this-\u003eassertQuery(\n            // Pass the process in which the query will be executed in the closure.\n            fn () =\u003e $this-\u003eexampleRepository-\u003efindById('a123'),\n            // Write the expected query.\n            'select from user where id = ? and is_active = ?',\n            // Define the expected bind values as an array.\n            // (If there is nothing to bind, pass an empty array or do not pass the argument)\n            [\n                'a123',\n                1,\n            ]\n        );\n\n        // Assert multiple queries.\n        // Basically, it's a good idea to look at one query in one method,\n        // but there are cases where one method executes multiple queries.\n        // In that case, define the query and bind value as an array pair as shown below.\n        $this-\u003eassertQuery(\n            // For example, if multiple queries are executed in this process\n            fn () =\u003e $this-\u003eexampleRepository-\u003efindAll(),\n            // Define an array for each expected query.\n            [\n                'select from user where is_active = ?', // ※1\n                'select from admin_user where id = ? and is_active = ?', // ※2\n                'select from something', // ※3\n            ],\n            // Define the bind values ​​as a two-dimensional array (pass empty array if there is nothing to bind).\n            [\n                [ // ※1.\n                    1,\n                ],\n                [ // ※2.\n                    'b123',\n                    1,\n                ],\n                // ※3 is no bind.\n                [],\n            ]\n        );\n    }\n}\n```\n\n### QueryAnalyzer\n\nYou can check what queries were flowed by passing the method by which the queries were flowed.  \nYou can get the result (`LaqueryAnalyzer\\QueryList`) of the query executed by `QueryAnalyzer::analyze()`.  \nThe `QueryList` has a `LaquAnalyzerQuery`.\n\n```php\n\u003c?php\n\nuse Laqu\\Facades\\QueryAnalyzer;\n\n/** @var Laqu\\Analyzer\\QueryList **/\n$analyzed = QueryAnalyzer::analyze(function () {\n    $author = Author::find(1);\n    $author-\u003edelete();\n});\n\n/*\nLaqu\\Analyzer\\QueryList {#345\n  -queries: array:2 [\n    0 =\u003e Laqu\\Analyzer\\Query {#344\n      -query: \"select * from \"authors\" where \"authors\".\"id\" = ? limit 1\"\n      -bindings: array:1 [\n        0 =\u003e 1\n      ]\n      -time: 0.08\n      -buildedQuery: \"select * from \"authors\" where \"authors\".\"id\" = 1 limit 1\"\n    }\n    1 =\u003e Laqu\\Analyzer\\Query {#337\n      -query: \"delete from \"authors\" where \"id\" = ?\"\n      -bindings: array:1 [\n        0 =\u003e \"1\"\n      ]\n      -time: 0.03\n      -buildedQuery: \"delete from \"authors\" where \"id\" = '1'\"\n    }\n  ]\n}\n*/\ndump($analyzed);\n\n// select * from \"authors\" where \"authors\".\"id\" = 1 limit 1\necho $analyzed[0]-\u003egetBuildedQuery();\n// delete from \"authors\" where \"id\" = '1'\necho $analyzed[1]-\u003egetBuildedQuery();\n\n/*\nLaqu\\Analyzer\\Query {#337\n  -query: \"delete from \"authors\" where \"id\" = ?\"\n  -bindings: array:1 [\n    0 =\u003e \"1\"\n  ]\n  -time: 0.03\n  -buildedQuery: \"delete from \"authors\" where \"id\" = '1'\"\n}\n*/\ndump($analyzed-\u003eextractFastestQuery());\n\n/*\nLaqu\\Analyzer\\Query {#344\n  -query: \"select * from \"authors\" where \"authors\".\"id\" = ? limit 1\"\n  -bindings: array:1 [\n    0 =\u003e 1\n  ]\n  -time: 0.08\n  -buildedQuery: \"select * from \"authors\" where \"authors\".\"id\" = 1 limit 1\"\n}\n*/\ndump($analyzed-\u003eextractSlowestQuery());\n\n/*\narray:2 [\n  0 =\u003e Laqu\\Analyzer\\Query {#337\n    -query: \"delete from \"authors\" where \"id\" = ?\"\n    -bindings: array:1 [\n      0 =\u003e \"1\"\n    ]\n    -time: 0.03\n    -buildedQuery: \"delete from \"authors\" where \"id\" = '1'\"\n  }\n  1 =\u003e Laqu\\Analyzer\\Query {#344\n    -query: \"select * from \"authors\" where \"authors\".\"id\" = ? limit 1\"\n    -bindings: array:1 [\n      0 =\u003e 1\n    ]\n    -time: 0.08\n    -buildedQuery: \"select * from \"authors\" where \"authors\".\"id\" = 1 limit 1\"\n  }\n]\n*/\ndump($analyzed-\u003esortByFast());\n\n/*\narray:2 [\n  0 =\u003e Laqu\\Analyzer\\Query {#344\n    -query: \"select * from \"authors\" where \"authors\".\"id\" = ? limit 1\"\n    -bindings: array:1 [\n      0 =\u003e 1\n    ]\n    -time: 0.08\n    -buildedQuery: \"select * from \"authors\" where \"authors\".\"id\" = 1 limit 1\"\n  }\n  1 =\u003e Laqu\\Analyzer\\Query {#337\n    -query: \"delete from \"authors\" where \"id\" = ?\"\n    -bindings: array:1 [\n      0 =\u003e \"1\"\n    ]\n    -time: 0.02\n    -buildedQuery: \"delete from \"authors\" where \"id\" = '1'\"\n  }\n]\n*/\ndump($analyzed-\u003esortBySlow());\n```\n\n### Helper\n\n#### QueryLog\n\nQueryLog is a wrap on [Basic Database Usage - Laravel - The PHP Framework For Web Artisans](https://laravel.com/docs/5.0/database#query-logging \"Basic Database Usage - Laravel - The PHP Framework For Web Artisans\") process.  \n※ Execution time is not that precise.\n\n```php\n\u003c?php\n\nuse Laqu\\Facades\\QueryLog;\n\n$queryLog = QueryLog::getQueryLog(fn () =\u003e Author::find(1));\n\n/*\narray:1 [\n  0 =\u003e array:3 [\n    \"query\" =\u003e \"select * from \"authors\" where \"authors\".\"id\" = ? limit 1\"\n    \"bindings\" =\u003e array:1 [\n      0 =\u003e 1\n    ]\n    \"time\" =\u003e 0.12\n  ]\n]\n*/\ndump($queryLog);\n```\n\n#### QueryHelper\n\nYou can pass a query and bind parameters to see the query to be executed.  \nReferenced from [pdo-debug/pdo-debug.php at master · panique/pdo-debug](https://github.com/panique/pdo-debug/blob/master/pdo-debug.php \"pdo-debug/pdo-debug.php at master · panique/pdo-debug\").\n\n```php\n\u003c?php\n\nuse Laqu\\Facades\\QueryHelper;\n\n$now  = Carbon::now();\n$from = $now-\u003ecopy()-\u003esubDay();\n$to   = $now-\u003ecopy()-\u003eaddDay();\n\n$query = 'select * from authors where id in (?, ?) and name like :name and updated_at between ? and ?';\n\n$bindings = [\n    1,\n    2,\n    '%Shakespeare',\n    $from,\n    $to,\n];\n\n$buildedQuery = QueryHelper::buildedQuery($query, $bindings);\n\n// select * from authors where id in (1, 2) and name like '%Shakespeare' and updated_at between '2020-07-07 00:37:55' and '2020-07-09 00:37:55'\necho $buildedQuery;\n```\n\n### QueryFormatter\n\nQueryFormatter is a wrapper for `Doctrine\\SqlFormatter\\SqlFormatter`.  \n@see [doctrine/sql-formatter: A lightweight php class for formatting sql statements. Handles automatic indentation and syntax highlighting.](https://github.com/doctrine/sql-formatter \"doctrine/sql-formatter: A lightweight php class for formatting sql statements. Handles automatic indentation and syntax highlighting.\")\n\nThe default is to use `NullHighlighter`, but it can also be formatted in CLI or HTML.\n\n#### format()\n\nThe default Highlighter is `Doctrine\\SqlFormatter\\NullHighlighter`.\n\n```php\n\u003c?php\n\nuse Laqu\\Facades\\QueryFormatter;\n\n$query = \"SELECT count(*),`Column1`,`Testing`, `Testing Three` FROM `Table1`\n    WHERE Column1 = 'testing' AND ( (`Column2` = `Column3` OR Column4 \u003e= NOW()) )\n    GROUP BY Column1 ORDER BY Column3 DESC LIMIT 5,10\";\n\n/*\nSELECT\n  count(*),\n  `Column1`,\n  `Testing`,\n  `Testing Three`\nFROM\n  `Table1`\nWHERE\n  Column1 = 'testing'\n  AND (\n    (\n      `Column2` = `Column3`\n      OR Column4 \u003e= NOW()\n    )\n  )\nGROUP BY\n  Column1\nORDER BY\n  Column3 DESC\nLIMIT\n  5, 10\n*/\necho QueryFormatter::format($query);\n```\n\nIf you use `Doctrine\\SqlFormatter\\CliHighlighter`, please inject `CliHighlighter` as follows.\n\n```php\n\u003c?php\n\nuse Doctrine\\SqlFormatter\\CliHighlighter;\nuse Laqu\\Formatter\\QueryFormatter;\n\n/** @var QueryFormatter */\n$formatter = app()-\u003emake(QueryFormatter::class/* or 'queryFormatter' */, [new CliHighlighter()]);\n\necho $formatter-\u003eformat($query);\n```\nOutput is  \n![example_CliHighlighter](https://github.com/shimabox/assets/raw/master/laqu/example_CliHighlighter.png)\n\nIf you use `Doctrine\\SqlFormatter\\HtmlHighlighter`, please inject `HtmlHighlighter` as follows.\n\n```php\n\u003c?php\n\nuse Doctrine\\SqlFormatter\\HtmlHighlighter;\nuse Laqu\\Formatter\\QueryFormatter;\n\n/** @var QueryFormatter */\n$formatter = app()-\u003emake(QueryFormatter::class/* or 'queryFormatter' */, [new HtmlHighlighter()]);\n\necho $formatter-\u003eformat($query);\n```\nOutput is  \n![example_HtmlHighlighter](https://github.com/shimabox/assets/raw/master/laqu/example_HtmlHighlighter.png)\n\n#### highlight()\n\nThe usage is almost the same as the `format()`.  \nPlease refer to https://github.com/doctrine/sql-formatter#syntax-highlighting-only.\n\n```php\n\u003c?php\n\nuse Laqu\\Facades\\QueryFormatter;\n\n$query = '...';\n\necho QueryFormatter::highlight($query);\n```\n\n#### compress()\n\n`compress()` returns a query with all comments and superfluous whitespace stripped out.  \nPlease refer to https://github.com/doctrine/sql-formatter#compress-query.\n\n```php\n\u003c?php\n\nuse Laqu\\Facades\\QueryFormatter;\n\n$query = \u003c\u003c\u003cSQL\n-- This is a comment\nSELECT\n    /* This is another comment\n    On more than one line */\n    Id #This is one final comment\n    as temp, DateCreated as Created FROM MyTable;\nSQL;\n\n// SELECT Id as temp, DateCreated as Created FROM MyTable;\necho QueryFormatter::compress($query);\n```\n\n## Develop\n\n### Run php-cs-fixer.\n\ncheck.\n```\n$ composer phpcs\n```\n\nfix.\n```\n$ composer phpcs:fix\n```\n\n### Run phpstan(larastan).\n\ncheck.\n```\n$ composer phpstan\n```\n\n### Run test.\n\n```\n$ composer test\n```\n\n### Run ci.\n\nRun all the above commands at once.\n\n```\n$ composer ci\n```\n\n## TODO\n\nThere are not yet enough query patterns.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshimabox%2Flaqu","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshimabox%2Flaqu","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshimabox%2Flaqu/lists"}