{"id":37007723,"url":"https://github.com/xtompie/aql","last_synced_at":"2026-01-14T00:49:14.268Z","repository":{"id":57085124,"uuid":"434326365","full_name":"xtompie/aql","owner":"xtompie","description":null,"archived":false,"fork":false,"pushed_at":"2024-09-05T09:25:26.000Z","size":53,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-04T12:52:17.981Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xtompie.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-12-02T18:09:56.000Z","updated_at":"2024-09-05T09:25:30.000Z","dependencies_parsed_at":"2022-08-25T00:50:20.031Z","dependency_job_id":null,"html_url":"https://github.com/xtompie/aql","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/xtompie/aql","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xtompie%2Faql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xtompie%2Faql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xtompie%2Faql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xtompie%2Faql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xtompie","download_url":"https://codeload.github.com/xtompie/aql/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xtompie%2Faql/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28406808,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T00:40:43.272Z","status":"ssl_error","status_checked_at":"2026-01-14T00:40:42.636Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":[],"created_at":"2026-01-14T00:49:14.132Z","updated_at":"2026-01-14T00:49:14.242Z","avatar_url":"https://github.com/xtompie.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Array Query Language\n\n- [Array Query Language](#array-query-language)\n  - [Requiments](#requiments)\n  - [Installation](#installation)\n  - [Docs](#docs)\n    - [Api](#api)\n      - [Select](#select)\n      - [Prefix](#prefix)\n      - [From](#from)\n      - [Join](#join)\n      - [Group](#group)\n      - [Having](#having)\n      - [Order](#order)\n      - [Limit](#limit)\n      - [Offset](#offset)\n      - [Where](#where)\n        - [String key](#string-key)\n        - [Int key and string value](#int-key-and-string-value)\n        - [Int key and array value](#int-key-and-array-value)\n      - [Insert](#insert)\n    - [Platform](#platform)\n    - [Extending](#extending)\n\nBuilding SQL prepared statment with binds using array\n\n```php\nuse Xtompie\\Aql\\Aql;\nuse Xtompie\\Aql\\MySQLPlatform;\n\n$aql = new Aql(\n    platform: new MySQLPlatform(),\n);\n$result = $aql([\n    'select' =\u003e '*',\n    'from' =\u003e 'order',\n    'where' =\u003e [\n        'status' =\u003e 'active',\n    ],\n    'limit' =\u003e 3,\n]);\n$result-\u003esql(); // 'SELECT * FROM `order` WHERE status = ? LIMIT 3'\n$result-\u003ebinds(); // ['active']\n$result-\u003etoArray(); // ['SELECT * FROM `order` WHERE status = ? LIMIT 3', ['active']]\n```\n\n## Requiments\n\nPHP \u003e= 8.0\n\n## Installation\n\nUsing [composer](https://getcomposer.org/)\n\n```shell\ncomposer require xtompie/aql\n```\n\n## Docs\n\n### Api\n\n#### Select\n\n```php\n$aql(['select' =\u003e 'post_id', 'title' =\u003e 'post_title'])-\u003etoArray();\n// [\"SELECT post_id, post_title as 'title'\", []];\n\n$aql(['select' =\u003e 'post_id, post_title as title'])-\u003etoArray();\n// ['SELECT post_id, post_title as title', []];\n\n$aql(['select' =\u003e '|x' =\u003e '|COUNT(*)'])-\u003etoArray();\n// ['SELECT COUNT(*) as x', []];\n```\n\nThe `|` character can be specified at the beginning of key or value to use the raw sql fragment\n\n#### Prefix\n\n```php\n$aql(['prefix' =\u003e 'SQL_NO_CACHE DISTINCT'])-\u003etoArray();\n// ['SELECT SQL_NO_CACHE DISTINCT', []];\n```\n\n#### From\n\n```php\n$aql(['from' =\u003e 'user'])-\u003etoArray();\n// ['FROM user', []];\n\n$aql(['from' =\u003e ['u' =\u003e 'user']])-\u003etoArray();\n// ['FROM user as u', []];\n\n$aql(['from' =\u003e 'order'])-\u003etoArray();\n// ['FROM `order`', []];\n```\n\nKeywords are quoted.\n\n#### Join\n\n```php\n$aql([\n    'join' =\u003e [\n        'JOIN author ON (author_id = post_id_author)',\n        'LEFT JOIN img ON (author_id_img = img_id)'\n    ]\n])-\u003etoArray();\n// ['JOIN author ON (author_id = post_id_author) LEFT JOIN img ON (author_id_img = img_id)\"]\n```\n\n#### Group\n\n```php\n$aql(['group' =\u003e 'post_id'])-\u003etoArray();\n// ['GROUP post_id', []];\n```\n\n#### Having\n\n```php\n$aql(['having' =\u003e 'post_id \u003e 0'])-\u003etoArray();\n// ['HAVING post_id \u003e 0', []];\n\n$aql(['having' =\u003e ['post_id \u003e' =\u003e '0']])-\u003etoArray();\n// ['HAVING post_id \u003e ?', [0]];\n```\n\nArray of conditions can be set as having.\nIt behaves as where conditions.\nSee [Where](#where).\n\n#### Order\n\n```php\n$aql(['order' =\u003e 'created_at DESC'])-\u003etoArray();\n// ['ORDER BY created_at DESC', []];\n```\n\nOrder is a raw sql fragment.\n\n#### Limit\n\n```php\n$aql(['limit' =\u003e '10'])-\u003etoArray();\n// ['LIMIT ?', [10]];\n```\n\nLimit is casted to int.\n\n#### Offset\n\n```php\n$aql(['offset' =\u003e '20'])-\u003etoArray();\n// ['OFFSET ?', [20]];\n```\n\nOffset is casted to int.\n\n#### Where\n\n##### String key\n\n```php\n$aql([\n    'where' =\u003e [\n        'a' =\u003e 'a',\n        'b' =\u003e ['b1', 'b2', 'b3'],\n        'c BETWEEN' =\u003e [2, 5],\n        'd \u003c\u003e' =\u003e 'd1',\n        'e LIKE' =\u003e '%e1%',\n        'f:gt' =\u003e 9,\n    ]\n])\n    -\u003etoArray()\n;\n// [\n//    'WHERE a = ? AND b IN (?, ?, ?) AND c BETWEEN ? AND ? AND d \u003c\u003e ? AND e LIKE ? AND f \u003e ?',\n//    ['a', 'b1', 'b2', 'b3', 2, 5, 'd1', '%e1%', 9]\n// ];\n```\n\nWhen condition key is a string then expected is column name with optional comparison operator.\nCompartition operator is expected after first space or `:` character.\nAvailable compartition operators are all valid SQL comparition operators and aditional:\n\n`eq` is `=`,\n`gt` is `\u003e`,\n`ge` is `\u003e=`,\n`lt` is `\u003c`,\n`le` is `\u003c=`,\n`not`, `neq` is `!=`,\n`like` is `LIKE`,\n`in` is `IN`,\n`notin` is `NOT IN`,\n`between` is `BETWEEN`,\n`notbetween` is `NOT BETWEEN`,\n\nThe `|` character can be specified at the beginning of key to use the raw sql fragment.\n\nBy default logical operator for all condition is `AND`.\nLogical operator can by change using `:operator` key.\n\n```php\n$aql([\n    'where' =\u003e [\n        'a' =\u003e 'a',\n        'b' =\u003e 'b',\n        ':operator' =\u003e 'OR',\n    ]\n])\n    -\u003etoArray()\n;\n// [\n//    'WHERE a = ? OR b = ?',\n//    ['a', 'bb']\n// ];\n```\n\n##### Int key and string value\n\n```php\n$aql(['where' =\u003e ['category_id IS NOT NULL']])-\u003etoArray();\n// ['WHERE category_id IS NOT NULL', []];\n```\n\n##### Int key and array value\n\n```php\n$aql([\n    'where' =\u003e [\n        'a' =\u003e 'aa',\n        [\n            'b' =\u003e 'bb',\n            'c' =\u003e 'cc',\n            ':operator' =\u003e 'OR',\n        ]\n    ]\n])-\u003etoArray();\n// ['WHERE a = ? AND (b = ? OR c = ?)', ['aa', 'bb', 'cc]];\n```\n\n#### Insert\n\n```php\n$aql([\n    'insert' =\u003e 'order',\n    'values' =\u003e [\n        'order' =\u003e 1,\n        '|time' =\u003e 'NOW()',\n    ]\n])-\u003etoArray();\n// ['INSERT INTO `order` (`order`, time) VALUES (?, NOW())', [1]];\n```\n\n### Platform\n\nBuild in supported platforms:\n\n- `Xtompie/Aql/MySQLPlatform`,\n- `Xtompie/Aql/PostgreSQLPlatform`.\n- `Xtompie/Aql/SQLitePlatform`.\n\nUsing `PostgreSQL`:\n\n```php\nuse Xtompie/Aql/Aql;\nuse Xtompie/Aql/PostgreSQLPlatform;\n\n(new Aql(platform: new PostgreSQLPlatform()))([\n    'SELECT' =\u003e '*',\n    'FROM' =\u003e 'order'\n])-\u003etoArray();\n// ['SELECT * FROM \"order\"', []];\n```\n\n### Extending\n\nBy decorating\n\n```php\n\u003c?php\n\nnamespace App\\Shared\\Database;\n\nuse Xtompie\\Aql\\Aql as BaseAql;\nuse Xtompie\\Aql\\Result;\n\ninterface Paging\n{\n    public function limit(): int;\n    public function offset(): int;\n}\n\nclass Aql\n{\n    public function __construct(\n        protected BaseAql $aql,\n    ) {}\n\n    public function __invoke(array $aql): Result\n    {\n        if (isset($aql['paging'])) {\n            $paging = $aql['paging'];\n            if (!$paging instanceof Paging) {\n                throw new \\Exception();\n            }\n            $aql['offset'] =\u003e $paging-\u003eoffset();\n            $aql['limit'] =\u003e $paging-\u003elimit();\n            unset($aql['paging']);\n        }\n        return ($this-\u003eaql)($aql);\n    }\n}\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxtompie%2Faql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxtompie%2Faql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxtompie%2Faql/lists"}