{"id":16294736,"url":"https://github.com/finesse/minidb","last_synced_at":"2025-06-10T19:33:51.343Z","repository":{"id":62504816,"uuid":"109339653","full_name":"Finesse/MiniDB","owner":"Finesse","description":"Light database abstraction with a query builder","archived":false,"fork":false,"pushed_at":"2020-02-01T05:51:00.000Z","size":67,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-17T14:22:17.538Z","etag":null,"topics":["database","library","mysql","pdo","query-builder","sql","sqlite"],"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/Finesse.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-11-03T01:56:56.000Z","updated_at":"2022-02-22T06:14:36.000Z","dependencies_parsed_at":"2022-11-02T12:16:38.401Z","dependency_job_id":null,"html_url":"https://github.com/Finesse/MiniDB","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Finesse%2FMiniDB","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Finesse%2FMiniDB/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Finesse%2FMiniDB/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Finesse%2FMiniDB/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Finesse","download_url":"https://codeload.github.com/Finesse/MiniDB/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244551974,"owners_count":20470965,"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":["database","library","mysql","pdo","query-builder","sql","sqlite"],"created_at":"2024-10-10T20:16:19.088Z","updated_at":"2025-03-20T04:30:41.223Z","avatar_url":"https://github.com/Finesse.png","language":"PHP","readme":"# MiniDB\n\n[![Latest Stable Version](https://poser.pugx.org/finesse/mini-db/v/stable)](https://packagist.org/packages/finesse/mini-db)\n[![Total Downloads](https://poser.pugx.org/finesse/mini-db/downloads)](https://packagist.org/packages/finesse/mini-db)\n![PHP from Packagist](https://img.shields.io/packagist/php-v/finesse/mini-db.svg)\n[![Test Status](https://github.com/finesse/MiniDB/workflows/Test/badge.svg)](https://github.com/Finesse/MiniDB/actions?workflow=Test)\n[![Maintainability](https://api.codeclimate.com/v1/badges/f06baf6e8d688b28cd12/maintainability)](https://codeclimate.com/github/Finesse/MiniDB/maintainability)\n[![Test Coverage](https://api.codeclimate.com/v1/badges/f06baf6e8d688b28cd12/test_coverage)](https://codeclimate.com/github/Finesse/MiniDB/test_coverage)\n\nLightweight database abstraction in which rows are simple arrays. It has both a query builder for convenient fluent \nsyntax and an interface for performing pure SQL queries.\n\n```php\n$database = Database::create([\n    'driver'   =\u003e 'mysql',\n    'dsn'      =\u003e 'mysql:host=localhost;dbname=my_database',\n    'username' =\u003e 'root',\n    'password' =\u003e 'qwerty',\n    'prefix'   =\u003e 'test_'\n]);\n\n$database-\u003estatement('\n    CREATE TABLE '.$database-\u003eaddTablePrefix('users').' (\n        id INT(11) NOT NULL AUTO_INCREMENT,\n        email VARCHAR(50) NOT NULL, \n        account INT(11) NOT NULL DEFAULT 0\n    )\n');\n\n$database-\u003etable('users')-\u003einsert([\n    ['name' =\u003e 'Jack', 'account' =\u003e 1200],\n    ['name' =\u003e 'Bob', 'account' =\u003e 500],\n    ['name' =\u003e 'Richard', 'account' =\u003e 800]\n]);\n\n$database-\u003etable('users')-\u003ewhere('account', '\u003e', 600)-\u003eget(); // Jack and Richard\n```\n\nKey features:\n\n* Light with a small number of light dependencies.\n* Extensible. Examples will come soon.\n* The [query builder](https://github.com/Finesse/QueryScribe) and the \n  [database connector](https://github.com/Finesse/MicroDB) can be used separately.\n* Supports table prefixes.\n* No static facades. Explicit delivery using dependency injection. \n* Exceptions on errors.\n\nSupported DBMSs:\n\n* MySQL\n* SQLite\n* Maybe any other, didn't test it\n\nIf you need a new database system support please implement it [there](https://github.com/Finesse/MicroDB) and \n[there](https://github.com/Finesse/QueryScribe) using pull requests.\n\n\n## Installation\n\nYou need [Composer](https://getcomposer.org) to use this library. Run in a console:\n                                                                  \n```bash\ncomposer require finesse/mini-db\n```\n\n\n## Reference\n\n### Getting started\n\nYou need to make a `Database` instance once:\n\n```php\nuse Finesse\\MiniDB\\Database;\n\n$database = Database::create([\n    'driver'   =\u003e 'mysql',                     // DBMS type: 'mysql', 'sqlite' or anything else for other (optional) \n    'dsn'      =\u003e 'mysql:host=host;dbname=db', // PDO data source name (DSN)\n    'username' =\u003e 'root',                      // Database username (optional)\n    'password' =\u003e 'qwerty',                    // Database password (optional)\n    'options'  =\u003e [],                          // PDO options (optional)\n    'prefix'   =\u003e ''                           // Tables prefix (optional)\n]);\n```\n\nSee more about the PDO options at the [PDO constructor reference](http://php.net/manual/en/pdo.construct.php).\n\nAlternatively you can create all the dependencies manually:\n\n```php\nuse Finesse\\MicroDB\\Connection;\nuse Finesse\\MiniDB\\Database;\nuse Finesse\\QueryScribe\\Grammars\\MySQLGrammar;\nuse Finesse\\QueryScribe\\PostProcessors\\TablePrefixer;\n\n$connection = Connection::create('mysql:host=host;dbname=db', 'username', 'password');\n$grammar = new MySQLGrammar();\n$tablePrefixer = new TablePrefixer('demo_');\n\n$database = new Database($connection, $grammar, $tablePrefixer);\n```\n\n### Raw SQL queries\n\n```php\n$database-\u003einsertGetId('INSERT INTO users (name, email) VALUES (?, ?), (?, ?)', ['Ann', 'ann@gmail.com', 'Bob', 'bob@rambler.com']); // 19 (the last inserted row id)\n\n$database-\u003eselect('SELECT * FROM users WHERE name = ? OR email = ?', ['Jack', 'jack@example.com']);\n/*\n    [\n        ['id' =\u003e 4, 'name' =\u003e 'Jack', 'email' =\u003e 'demon@mail.com', 'account' =\u003e 1230],\n        ['id' =\u003e 17, 'name' =\u003e 'Bill', 'email' =\u003e 'jack@example.com', 'account' =\u003e -100]\n    ]\n */\n \n$database-\u003eimport('path/to/file.sql');\n```\n\nThe cell values are returned as they are returned by the underlying database connection. They are not casted \nautomatically because casting can cause a data loss.\n\nTable prefix is not applied in raw queries. Use `$database-\u003eaddTablePrefix()` to apply it.\n\n```php\n$database-\u003eselect('SELECT * FROM '.$database-\u003eaddTablePrefix('users').' ORDER BY id');\n```\n\nBe careful, the `statements` and the `import` methods don't throw an exception if the second or a next statement of the \nquery has an error. This is [a PDO bug](https://stackoverflow.com/a/28867491/1118709).\n\nYou can find more information and examples of raw queries [there](https://github.com/Finesse/MicroDB#reference).\n\n### Query builder\n\nBasic examples are presented here. You can find more cool examples \n[there](https://queryscribe.readthedocs.io/en/stable/building-queries/).\n\nValues given to the query builder are treated safely to prevent SQL injections so you don't need to escape them.\n\n#### Select\n\nMany rows:\n\n```php\n$database\n    -\u003etable('users')\n    -\u003ewhere('status', 'active')\n    -\u003eorderBy('name')\n    -\u003eoffset(40)\n    -\u003elimit(10)\n    -\u003eget();\n    \n/*\n    [\n        ['id' =\u003e 17, 'name' =\u003e 'Bill', 'email' =\u003e 'jack@example.com', 'status' =\u003e 'active'],\n        ['id' =\u003e 4, 'name' =\u003e 'Jack', 'email' =\u003e 'demon@mail.com', 'status' =\u003e 'active']\n    ]\n */\n```\n\nOne row:\n\n```php\n$database\n    -\u003etable('users')\n    -\u003ewhere('status', 'active')\n    -\u003eorderBy('name')\n    -\u003efirst();\n    \n/*\n    ['id' =\u003e 17, 'name' =\u003e 'Bill', 'email' =\u003e 'jack@example.com', 'status' =\u003e 'active'] or null\n */\n```\n\n##### Pagination\n\nWe suggest [Pagerfanta](https://github.com/whiteoctober/Pagerfanta) to make a pagination easily.\n\nFirst install Pagerfanta using [composer](https://getcomposer.org) by running in a console:\n\n```bash\ncomposer require pagerfanta/pagerfanta\n```\n\nThen make a query from which the rows should be taken:\n\n```php\n$query = $database\n    -\u003etable('posts')\n    -\u003ewhere('category', 'archive')\n    -\u003eorderBy('date', 'desc');\n    // Don't call -\u003eget() here\n```\n\nAnd use Pagerfanta:\n\n```php\nuse Finesse\\MiniDB\\ThirdParty\\PagerfantaAdapter;\nuse Pagerfanta\\Pagerfanta;\n\n$paginator = new Pagerfanta(new PagerfantaAdapter($query));\n$paginator-\u003esetMaxPerPage(10); // The number of rows on a page\n$paginator-\u003esetCurrentPage(3); // The current page number\n\n$currentPageRows = $paginator-\u003egetCurrentPageResults(); // The rows for the current page\n$pagesCount = $paginator-\u003egetNbPages();                 // Total pages count\n$haveToPaginate = $paginator-\u003ehaveToPaginate();         // Whether the number of results is higher than the max per page\n```\n\nYou can find more reference and examples for Pagerfanta [there](https://github.com/whiteoctober/Pagerfanta#usage).\n\n##### Chunking rows\n\nIf you need to process a large amount of rows you can use chunking. In this approach portions of rows are fetched from \nthe database instead of fetching all the rows at once.\n\n```php\n$database\n    -\u003etable('users')\n    -\u003eorderBy('id')\n    -\u003echunk(100, function ($users) {\n        foreach ($users as $user) {\n            // Process a row here\n        }\n    });\n```\n\n#### Aggregates\n\n```php\n$database\n    -\u003etable('products')\n    -\u003ewhere('price', '\u003e', 1000)\n    -\u003ecount(); // 31\n```\n\nOther aggregate methods: `avg(column)`, `sum(column)`, `min(column)` and `max(column)`.\n\n#### Insert\n\nMany rows:\n\n```php\n$database-\u003etable('debts')-\u003einsert([\n    ['name' =\u003e 'Sparrow', 'amount' =\u003e 13000, 'message' =\u003e 'Sneaky guy'],\n    ['name' =\u003e 'Barbos', 'amount' =\u003e 4999, 'message' =\u003e null],\n    ['name' =\u003e 'Pillower', 'message' =\u003e 'Call tomorrow']\n]); // 3 (number of inserted rows)\n```\n\nThe string array keys are the columns names.\n\nOne row:\n\n```php\n$database-\u003etable('debts')-\u003einsertGetId([\n    'name' =\u003e 'Bigbigger',\n    'amount' =\u003e -3500,\n    'message' =\u003e 'I owe him'\n]); // 4 (id of the inserted row)\n```\n\nFrom a select query:\n\n```php\n$database-\u003etable('debts')-\u003einsertFromSelect(['name', 'amount', 'message'], function ($query) {\n    $query\n        -\u003efrom('users')\n        -\u003eaddSelect(['name', $query-\u003eraw('- account'), 'description'])\n        -\u003ewhere('status', 'debtor');\n}); // 6 (number of inserted rows)\n```\n\n#### Update\n\n```php\n$database\n    -\u003etable('posts')\n    -\u003ewhere('date', '\u003c', '2017-01-01')\n    -\u003eupdate([\n        'status' =\u003e 'obsolete',\n        'category' =\u003e null\n    ]); // 5 (number of updated rows)\n```\n\nThe array keys are the columns names.\n\n#### Delete\n\n```php\n$database\n    -\u003etable('messages')\n    -\u003ewhere('sender_id', 1456)\n    -\u003eorWhere('status', 'stink')\n    -\u003edelete(); // 5 (number of deleted rows)\n```\n\n#### Helpers\n\nEscape LIKE special wildcard characters:\n\n```php\n$searchString = '%iamhacker%';\n\n$query-\u003ewhere('name', 'like', $query-\u003eescapeLikeWildcards($searchString).'_'); // \"name\" LIKE \\%iamhacker\\%_\n```\n\nWrap a table or a column name in quotes:\n\n```php\n$query-\u003ewhereRaw('MIN('.$query-\u003equoteIdentifier('data\"base').'.'.$query-\u003equoteIdentifier('ta\"ble').') \u003e 10');\n// or\n$query-\u003ewhereRaw('MIN('.$query-\u003equoteCompositeIdentifier('data\"base.ta\"ble').') \u003e 10'); // MIN(\"data\"\"base\".\"ta\"\"ble\") \u003e 10\n```\n\nThe above methods are also available in a `Database` object.\n\nMake all the column names in the query have explicit table name or alias:\n\n```php\n$database\n    -\u003etable('users', 'u')\n    -\u003eaddSelect('name')\n    -\u003ewhere('status', 'verified')\n    -\u003eorWhere('u.type', 'admin')\n    -\u003eaddTablesToColumnNames();\n\n// SELECT \"name\" FROM \"users\" AS \"u\" WHERE \"status\" = ? OR \"u\".\"type\" = ?\n```\n\n\n## Versions compatibility\n\nThe project follows the [Semantic Versioning](http://semver.org).\n\n\n## License\n\nMIT. See [the LICENSE](LICENSE) file for details.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffinesse%2Fminidb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffinesse%2Fminidb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffinesse%2Fminidb/lists"}