{"id":21215339,"url":"https://github.com/zlikavac32/query-builder","last_synced_at":"2026-04-30T02:35:58.481Z","repository":{"id":57091522,"uuid":"242281127","full_name":"zlikavac32/query-builder","owner":"zlikavac32","description":"The SQL query builder library that never builds an SQL query from scratch, but rather modifies an existing query.","archived":false,"fork":false,"pushed_at":"2020-04-18T00:17:03.000Z","size":38,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-21T16:30:39.913Z","etag":null,"topics":["query-builder","sql"],"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/zlikavac32.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-02-22T04:46:59.000Z","updated_at":"2020-04-18T00:16:52.000Z","dependencies_parsed_at":"2022-08-22T18:20:56.669Z","dependency_job_id":null,"html_url":"https://github.com/zlikavac32/query-builder","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zlikavac32%2Fquery-builder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zlikavac32%2Fquery-builder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zlikavac32%2Fquery-builder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zlikavac32%2Fquery-builder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zlikavac32","download_url":"https://codeload.github.com/zlikavac32/query-builder/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243664550,"owners_count":20327494,"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":["query-builder","sql"],"created_at":"2024-11-20T21:37:09.958Z","updated_at":"2026-04-30T02:35:53.458Z","avatar_url":"https://github.com/zlikavac32.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Query Builder\n\n[![Build Status](https://travis-ci.org/zlikavac32/query-builder.svg?branch=master)](https://travis-ci.org/zlikavac32/query-builder) [![Latest Stable Version](https://poser.pugx.org/zlikavac32/query-builder/v/stable)](https://packagist.org/packages/zlikavac32/query-builder) [![License](https://poser.pugx.org/zlikavac32/query-builder/license)](https://packagist.org/packages/zlikavac32/query-builder)\n\nThe SQL query builder library that does not build an SQL query from scratch, but rather modifies an existing query. \n\n## Table of contents\n\n1. [Introduction](#introduction)\n1. [How it works](#how-it-works)\n1. [Installation](#installation)\n1. [Configuration](#configuration)\n    1. [Preloading](#preloading)\n1. [Usage](#usage)\n    1. [Subquery inlining](#subquery-inlining)\n1. [Limitations](#limitations)\n\n## Introduction\n\nHow to achieve harmony between the PHP and the database has been a subject to many blog posts. While some propose and use various ORM-s like Doctrine and Eloquent, other stick to raw SQL queries. ORM-s come with some sort of a query builder that is something very useful. For example, when providing filtering to an admin page, it's useful to programmatically modify the query to reflect requested filters.\n\nIf we think about a query itself, there are really rare occasions (I myself did not encounter one such) where we need to build a query from scratch. We usually have a base query that does something and then we extend it. In the filtering example above, we could have `SELECT t.id, t.name FROM tickets t WHERE t.date \u003e= '2020-01-01` as a base query for this years tickets and then a filter for `state` that modifies initial query into `SELECT t.id, t.name FROM tickets t WHERE t.date \u003e '2020-01-01' AND t.state = 'SOLD'`.\n\nThat is the main premise behind this query builder. To reuse existing queries instead of manually constructing a full query through the query builder.\n\n## How it works?\n\nEvery `SELECT` statement is decomposed into sections like `columns` or `where` and then that statement can be modified through the exposed query builder API. To make that possible, the query builder parses statements and tracks all of the parameter placeholders and parameter values themselves and when a certain section is modified, parameters are merged/removed as well.\n\nThat means that parameters must be known at the time when that section is being added to the query builder, whether it's the initial query or just some new section. That being said, this query builder is not intended for reusable prepared statements (**yet!**).\n\nThe parser used is a [small SQL parser](https://github.com/zlikavac32/sql-query-parser) written in C and exposed through the FFI (more parser implementations may come in the future).\n\n## Installation\n\nThe recommended installation is through Composer.\n\n```shell script\ncomposer require zlikavac32/query-builder\n```\n## Configuration\n\nTo use the query builder, create a query builder environment.\n\n```php\nuse Zlikavac32\\QueryBuilder\\FFISqlParser;\nuse Zlikavac32\\QueryBuilder\\NonPreloadedFFIGateway;\nuse Zlikavac32\\QueryBuilder\\ParserBackedQueryEnvironment;\n\n$parser = NonPreloadedFFIGateway::createDefault();\n$parser = new FFISqlParser($parser);\n$queryBuilder = new ParserBackedQueryEnvironment($parser);\n```\n\n### Preloading\n\nInstead of importing the FFI definition when needed, the FFI definition can be preloaded. There is no pretty or automatic way to do it. In your preload script you should add\n\n```php\nFFI::load('{{path}}');\n```\n\nwhere `{{path}}` represents a path to the `tsqlp.h` header file in this repository, for example `__DIR__ . '/vendor/zlikavac32/query-builder/tsqlp.h`. Other (perhaps necessary) option is to use `ffi.preload` with the path to the `tsqlp.h`. For more info consult the [FFI configuration](https://www.php.net/manual/en/ffi.configuration.php).\n\nOther change is that you can no longer use the `\\Zlikavac32\\QueryBuilder\\NonPreloadedFFIGateway` class and you should use the `\\Zlikavac32\\QueryBuilder\\PreloadedFFIGateway` class.\n\n## Usage\n\nUse the constructed environment to create a query builder from an `SQL` string or a `\\Zlikavac32\\QueryBuilder\\Query` instance.\n\n```php\n$qb = $queryBuilder-\u003equeryBuilderFromString(\n    'SELECT * FROM user WHERE active = ?', \n    1\n);\n\n$qb-\u003eandWhere('registered_at \u003e ?', '2020-01-01');\n\n$query = $qb-\u003ebuild();\n\nvar_dump($query-\u003esql(), $query-\u003eparameters());\n// SELECT * FROM user WHERE (active = ?) AND (registered_at \u003e ?)\n// [1, '2020-01-01']\n```\n\nCheck `\\Zlikavac32\\QueryBuilder\\QueryBuilder` for more info regarding available query builder methods.\n\n### Subquery inlining\n\nSince this library parses queries, it can inject subqueries into the parameter placeholders.\n\n```php\nuse Zlikavac32\\QueryBuilder\\Query;\n\n$userOfTheLatestTransactionQuery = Query::create(\n    'SELECT user_id FROM transaction ORDER BY created_at DESC LIMIT 1'\n);\n$qb = $queryBuilder-\u003equeryBuilderFromString(\n    'SELECT * FROM user WHERE id = ?', \n    $userOfTheLatestTransactionQuery\n);\n\n$query = $qb-\u003ebuild();\n\nvar_dump($query-\u003esql(), $query-\u003eparameters());\n// SELECT * FROM user WHERE id = (SELECT user_id FROM transaction ORDER BY date DESC LIMIT 1)\n// []\n```\n\n## Limitations\n\nUsed parser could (and probably will) parse certain SQL queries as valid only for them to be rejected from the database. This is by design to keep the parsing simple since that parser is not intended to be used as a linter or whatever. It doesn't even produce an AST and the resulting query will immediately be executed so the logic error will be known. The query builder itself will not produce an invalid query from a valid query. This is not really a limitation, but it's useful to mention.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzlikavac32%2Fquery-builder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzlikavac32%2Fquery-builder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzlikavac32%2Fquery-builder/lists"}