{"id":43678079,"url":"https://github.com/francerz/php-sql-builder","last_synced_at":"2026-02-05T01:20:06.897Z","repository":{"id":62507062,"uuid":"308986816","full_name":"francerz/php-sql-builder","owner":"francerz","description":"A powerful PHP query building tool designed to streamline database interactions by facilitating optimal performance and object-based query construction. Supports SELECT, INSERT, UPDATE, and DELETE queries, as well as transactions and stored procedures.","archived":false,"fork":false,"pushed_at":"2025-07-02T17:47:35.000Z","size":302,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-20T06:36:50.155Z","etag":null,"topics":["object-relational-mapping","relational-databases"],"latest_commit_sha":null,"homepage":"https://packagist.org/packages/francerz/sql-builder","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/francerz.png","metadata":{"files":{"readme":"README.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-10-31T23:00:59.000Z","updated_at":"2025-10-01T03:47:51.000Z","dependencies_parsed_at":"2024-02-12T02:28:31.884Z","dependency_job_id":"3c84c85c-6831-4014-87ba-91f340c4dc5c","html_url":"https://github.com/francerz/php-sql-builder","commit_stats":{"total_commits":176,"total_committers":1,"mean_commits":176.0,"dds":0.0,"last_synced_commit":"0d05a5d67793db4598b6a175ca1f73a1754ae76b"},"previous_names":[],"tags_count":122,"template":false,"template_full_name":null,"purl":"pkg:github/francerz/php-sql-builder","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/francerz%2Fphp-sql-builder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/francerz%2Fphp-sql-builder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/francerz%2Fphp-sql-builder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/francerz%2Fphp-sql-builder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/francerz","download_url":"https://codeload.github.com/francerz/php-sql-builder/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/francerz%2Fphp-sql-builder/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29105274,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-05T00:52:08.035Z","status":"ssl_error","status_checked_at":"2026-02-05T00:52:07.703Z","response_time":62,"last_error":"SSL_read: 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":["object-relational-mapping","relational-databases"],"created_at":"2026-02-05T01:20:05.967Z","updated_at":"2026-02-05T01:20:06.874Z","avatar_url":"https://github.com/francerz.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"SQL Builder\n=======================================\n\n![Packagist](https://img.shields.io/packagist/v/francerz/sql-builder)\n![License](https://img.shields.io/github/license/francerz/php-sql-builder?color=%230078D0)\n![Packagist Downloads](https://img.shields.io/packagist/dt/francerz/sql-builder?color=%23E0B000)\n![Build Status](https://github.com/francerz/php-sql-builder/workflows/PHP%20Unit%20Tests/badge.svg)\n\nA PHP SQL query builder that prioritizes readability and optimal performance\nwith object based construction.\n\nTable of contents\n---------------------------------------\n- [SQL Builder](#sql-builder)\n  - [Table of contents](#table-of-contents)\n  - [Installation ↑](#installation-)\n  - [Connect to database ↑](#connect-to-database-)\n  - [Basic common usage syntax ↑](#basic-common-usage-syntax-)\n    - [Select query ↑](#select-query-)\n    - [Insert query ↑](#insert-query-)\n    - [Update query ↑](#update-query-)\n    - [Delete query ↑](#delete-query-)\n  - [Build SELECT with WHERE or HAVING clause ↑](#build-select-with-where-or-having-clause-)\n    - [Parentheses syntax](#parentheses-syntax)\n    - [List of operators ↑](#list-of-operators-)\n  - [Building SELECT with JOIN ↑](#building-select-with-join-)\n    - [SUPPORTED JOIN TYPES](#supported-join-types)\n    - [Examples](#examples)\n  - [SELECT nesting ↑](#select-nesting-)\n    - [Nesting a Collection of Result Objects](#nesting-a-collection-of-result-objects)\n    - [Nesting the First or Last Result Object](#nesting-the-first-or-last-result-object)\n  - [Transactions ↑](#transactions-)\n  - [Executing Stored Procedures ↑](#executing-stored-procedures-)\n\nInstallation [↑](#table-of-contents)\n---------------------------------------\n\nThis package can be installed with composer using following command.\n\n```sh\ncomposer require francerz/sql-builder\n```\n\nConnect to database [↑](#table-of-contents)\n---------------------------------------\n\nUsing an URI string\n```php\n$db = DatabaseManager::connect('driver://user:password@host:port/database');\n```\n\nUsing environment variable\n```php\nputenv('DATABASE_SCHOOL_DRIVER', 'driver');\nputenv('DATABASE_SCHOOL_HOST', 'host');\nputenv('DATABASE_SCHOOL_INST', 'instanceName');\nputenv('DATABASE_SCHOOL_PORT', 'port');\nputenv('DATABASE_SCHOOL_USER', 'user');\nputenv('DATABASE_SCHOOL_PSWD', 'password');\nputenv('DATABASE_SCHOOL_NAME', 'database');\n\n// Support to Docker secrets\nputenv('DATABASE_SCHOOL_PSWD_FILE', '/run/secrets/db_school_password');\n\n$db = DatabaseManager::connect('school');\n```\n\nBasic common usage syntax [↑](#table-of-contents)\n---------------------------------------\n```php\nclass Group {\n    public $group_id;\n    public $subject;\n    public $teacher;\n}\n```\n\n### Select query [↑](#table-of-contents)\n```php\n// SELECT group_id, subject, teacher FROM groups\n$query = Query::selectFrom('groups', ['group_id', 'subject', 'teacher']);\n\n$db = DatabaseManager::connect('school');\n$result = $db-\u003eexecuteSelect($query);\n$groups = $result-\u003etoArray(Group::class);\n```\n\n### Insert query [↑](#table-of-contents)\n```php\n$group = new Group();\n$group-\u003esubject = 'Database fundamentals';\n$group-\u003eteacher = 'francerz';\n\n// INSERT INTO groups (subject, teacher) VALUES ('Database fundamentals', 'francerz')\n$query = Query::insertInto('groups', $group, ['subject', 'teacher']);\n\n$db = DatabaseManager::connect('school');\n$result = $db-\u003eexecuteInsert($query);\n$group-\u003egroup_id = $result-\u003egetInsertedId();\n```\n\n### Update query [↑](#table-of-contents)\n```php\n$group = new Group();\n$group-\u003egroup_id = 10;\n$group-\u003esubject = 'Introduction to databases';\n\n// UPDATE groups SET subject = 'Introduction to databases' WHERE group_id = 10\n$query = Query::update('groups', $group, ['group_id'], ['subject']);\n\n$db = DatabaseManager::connect('school');\n$result = $db-\u003eexecuteUpdate($query);\n```\n\n### Delete query [↑](#table-of-contents)\n```php\n// DELETE FROM groups WHERE group_id = 10\n$query = Query::deleteFrom('groups', ['group_id' =\u003e 10]);\n\n$db = DatabaseManager::connect('school');\n$result = $db-\u003eexecuteDelete($query);\n```\n\n---\n\nBuild SELECT with WHERE or HAVING clause [↑](#table-of-contents)\n---------------------------------------\n\nBellow are examples of using `WHERE` clause which aplies to `SELECT`, `UPDATE`\nand `DELETE` queries.\n\n\u003e Selecting all fields from table `groups` when the value of column `group_id` is\n\u003e equal to `10`.\n\n```sql\nSELECT * FROM groups WHERE group_id = 10\n```\n```php\n// Explicit syntax\n$query = Query::selectFrom('groups')-\u003ewhere()-\u003eequals('group_id', 10);\n\n// Implicit syntax\n$query = Query::selectFrom('groups')-\u003ewhere('group_id', 10);\n```\n\n---\n\n\u003e Selecting all fields from table `groups` when value of column `group_id` is\n\u003e equals to `10`, `20` or `30`.\n\n```sql\nSELECT * FROM groups WHERE group_id IN (10, 20, 30)\n```\n```php\n// Explicit syntax\n$query = Query::selectFrom('groups')-\u003ewhere()-\u003ein('group_id', [10, 20, 30]);\n\n// Implicit syntax\n$query = Query::selectFrom('groups')-\u003ewhere('group_id', [10, 20, 30]);\n```\n\n---\n\n\u003e Selecting all fields from table `groups`when value of column `teacher` is\n\u003e `NULL`.\n\n```sql\nSELECT * FROM groups WHERE teacher IS NULL\n```\n```php\n// Explicit syntax\n$query = Query::selectFrom('groups')-\u003ewhere()-\u003enull('teacher');\n\n// Implicit compact syntax\n$query = Query::selectFrom('groups')-\u003ewhere('teacher', 'NULL');\n```\n\n---\n\n\u003e Selecting all fields from table `groups` when value of column `group_id` is\n\u003e less or equals to `10` and value from column `subject` contains the word\n\u003e `\"database\"`.\n\n```sql\nSELECT * FROM groups WHERE group_id \u003c= 10 AND subject LIKE '%database%'\n```\n```php\n// Explicit syntax\n$query = Query::selectFrom('groups');\n$query-\u003ewhere()-\u003elessEquals('group_id', 10)-\u003eandLike('subject', '%database%');\n\n// Implicit compact syntax\n$query = Query::selectFrom('groups');\n$query-\u003ewhere('group_id', '\u003c=', 10)-\u003eandLike('subject', '%database%');\n```\n\n---\n\n### Parentheses syntax\n\nTo incorporate highly specific and intricate conditions, it becomes essential to\noverride the default operator precedence, a task traditionally achieved through\nthe use of parentheses in SQL syntax. Within the SQL Builder, this functionality\nis adeptly handled through the utilization of an anonymous function parameter.\n\nParentheses anonymous function works in the following syntax:\n\n```php\n$query-\u003ewhere(function($subwhere) { });\n$query-\u003ewhere-\u003enot(function($subwhere) { });\n$query-\u003ewhere-\u003eand(function($subwhere) { });\n$query-\u003ewhere-\u003eor(function($subwhere) { });\n$query-\u003ewhere-\u003eandNot(function($subwhere) { });\n$query-\u003ewhere-\u003eorNot(function($subwhere) { });\n```\n\n\u003e Selecting all fields from table `groups` when the value of `group_id` is\n\u003e equals to `10` or is within the range from `20` to `30`.\n\n```sql\nSELECT *\n    FROM groups\n    WHERE subject LIKE '%database%'\n    AND (group_id = 10 OR group_id BETWEEN 20 AND 30)\n```\n\n```php\n$query = Query::selectFrom('groups');\n\n// Using an anonymous function to emulate parenthesis\n$query-\u003ewhere()\n    -\u003elike('subject', '%database%')\n    -\u003eand(function(ConditionList $subwhere) {\n        $subwhere\n            -\u003eequals('group_id', 10)\n            -\u003eorBetween('group_id', 20, 30);\n    });\n```\n\n---\n\n### List of operators [↑](#table-of-contents)\n\nThe library provides a comprehensive array of operators that are largely\nconsistent across various SQL database engines. To enhance readability, it also\nprefixes the `and` and `or` logical operators for clarity.\n\n| SQL Operator  | Regular (AND)                 | AND                              | OR                              |\n| ------------- | ----------------------------- | -------------------------------- | ------------------------------- |\n| `=`           | `equals($op1, $op2)`          | `andEquals($op1, $op2)`          | `orEquals($op1, $op2)`          |\n| `\u003c\u003e` or `!=`  | `notEquals($op1, $op2)`       | `andNotEquals($op1, $op2)`       | `orNotEquals($op1, $op2)`       |\n| `\u003c`           | `lessThan($op1, $op2)`        | `andLessThan($op1, $op2)`        | `orLessthan($op1, $op2)`        |\n| `\u003c=`          | `lessEquals($op1, $op2)`      | `andLessEquals($op1, $op2)`      | `orLessEquals($op1, $op2)`      |\n| `\u003e`           | `greaterThan($op1, $op2)`     | `andGreaterThan($op1, $op2)`     | `orGreaterThan($op1, $op2)`     |\n| `\u003e=`          | `greaterEquals($op1, $op2)`   | `andGreaterEquals($op1, $op2)`   | `orGreaterEquals($op1, $op2)`   |\n| `LIKE`        | `like($op1, $pattern)`        | `andLike($op1, $pattern)`        | `orLike($op1, $pattern)`        |\n| `NOT LIKE`    | `notLike($op1, $pattern)`     | `andNotLike($op1, $pattern)`     | `orNotLike($op1, $pattern)`     |\n| `REGEXP`      | `regexp($op1, $pattern)`      | `andRegexp($op1, $pattern)`      | `orRegexp($op1, $pattern)`      |\n| `NOT REGEXP`  | `notRegexp($op1, $pattern)`   | `andNotRegexp($op1, $pattern)`   | `orNotRegexp($op1, $pattern)`   |\n| `IS NULL`     | `null($op)`                   | `andNull($op)`                   | `orNull($op)`                   |\n| `IS NOT NULL` | `notNull($op)`                | `andNotNull($op)`                | `orNotNull($op)`                |\n| `BETWEEN`     | `between($op, $min, $max)`    | `andBetween($op, $min, $max)`    | `orBetween($op, $min, $max)`    |\n| `NOT BETWEEN` | `notBetween($op, $min, $max)` | `andNotBetween($op, $min, $max)` | `orNotBetween($op, $min, $max)` |\n| `IN`          | `in($op, $array)`             | `andIn($op, $array)`             | `orIn($op, $array)`             |\n| `NOT IN`      | `notIn($op, $array)`          | `andNotIn($op, $array)`          | `orNotIn($op, $array)`          |\n| `IS NOT NULL` | `hasValue($op)`               | `andHasValue($op)`               | `orHasValue($op)`               |\n\n\u003e **About `ConditionList` class**\n\u003e\n\u003e The examples of condition list, functions and operators applies in the same\n\u003e way to `WHERE`, `HAVING` and `ON` clauses.\n\n---\n\nBuilding SELECT with JOIN [↑](#table-of-contents)\n---------------------------------------\n\nOne of the most common operations in relational databases is merging and\ncombining data from multiple tables. The join operations allow to combine the\ndata from multiple tables by using the `INNER JOIN`, `LEFT JOIN`, `RIGHT JOIN`\nand `CROSS JOIN` syntax.\n\n### SUPPORTED JOIN TYPES\n\nQuery Builder supports many types of `JOIN` syntaxes:\n\n```php\n// INNER JOIN\n$query-\u003einnerJoin($table, $columns = []);\n\n// CROSS JOIN\n$query-\u003ecrossJoin($table, $columns = []);\n\n// LEFT JOIN\n$query-\u003eleftJoin($table, $columns = []);\n\n// RIGHT JOIN\n$query-\u003erightJoin($table, $columns = []);\n```\n\n\u003e **SQL Join Syntax Compatibility:**\n\u003e\n\u003e Join Syntax is available to `SELECT`, `UPDATE` and `DELETE` sql syntax,\n\u003e however, not all database engines might support it.\n\n### Examples\n\n```sql\nSELECT * FROM groups INNER JOIN teachers ON groups.teacher_id = teachers.teacher_id\n```\n```php\n$query = Query::selectFrom('groups');\n$query\n    -\u003einnerJoin('teachers')\n    -\u003eon('groups.teacher_id', 'teachers.teacher_id');\n```\n\n---\n\nUsing table aliases to reduce naming length.\n\n```sql\nSELECT * FROM groups AS g INNER JOIN teachers AS t ON g.teacher_id = t.teacher_id\n```\n```php\n// Alias array syntax\n$query = Query::selectFrom(['g' =\u003e 'groups']);\n$query\n    -\u003einnerJoin(['t' =\u003e 'teachers'])\n    -\u003eon('g.teacher_id', 't.teacher_id');\n\n// Alias \"AS\" string syntax\n$query = Query::selectFrom('groups AS g');\n$query\n    -\u003einnerJoin('teachers AS t')\n    -\u003eon('g.teacher_id', 't.teacher_id');\n```\n\n---\n\nMultiple database (same host) select with join.  \n\n```sql\nSELECT * FROM school.groups AS g INNER JOIN hr.employees AS e ON g.teacher_id = e.employee_id\n```\n```php\n$query = Query::selectFrom('school.groups AS g');\n$query\n    -\u003einnerJoin('hr.employees AS e')\n    -\u003eon('g.teacher_id','e.employee_id');\n```\n\n---\n\nSelecting fields from joined tables.\n\n```sql\nSELECT g.group_id, t.given_name, t.family_name\nFROM groups AS g\nINNER JOIN teachers AS t ON g.teacher_id = t.teacher_id\n```\n```php\n$query = Query::selectFrom('groups AS g', ['group_id']);\n$query\n    -\u003einnerJoin('teachers AS t', ['given_name', 'family_name'])\n    -\u003eon('g.teacher_id', 't.teacher_id');\n```\n\n---\n\nRenaming fields from joined tables.\n\n```sql\nSELECT g.group_id, CONCAT(t.given_name, ' ', t.family_name) AS teacher_name\nFROM groups AS g\nINNER JOIN teachers AS t ON g.teacher_id = t.teacher_id\n```\n```php\n$query = Query::selectFrom('groups AS g', ['group_id']);\n$query\n    -\u003einnerJoin('teachers AS t', [\n        'teacher_name' =\u003e \"CONCAT(t.given_name, ' ', t.family_name)\"\n    ])-\u003eon('g.teacher_id', 't.teacher_id');\n```\n\n---\n\nSelecting columns into an external function (cleaner code).\n\n```sql\nSELECT g.group_id, CONCAT(t.given_name, ' ', t.family_name) AS teacher_name\nFROM groups AS g\nINNER JOIN teachers AS t ON g.teacher_id = t.teacher_id\n```\n```php\n$query = Query::selectFrom('groups AS g');\n$query\n    -\u003einnerJoin('teachers AS t')\n    -\u003eon('g.teacher_id', 't.teacher_id');\n$query-\u003ecolumns([\n    'g.group_id',\n    'teacher_name' =\u003e \"CONCAT(t.given_name, ' ', t.family_name)\"\n]);\n```\n\n---\n\nJoin tables and subqueries.\n\n```sql\n-- Gets all groups of active teachers\nSELECT g.group_id, CONCAT(t.given_name, ' ', t.family_name) AS teacher_name\nFROM groups AS g\nINNER JOIN (SELECT * FROM teachers WHERE active = 1) AS t\nON g.teacher_id = t.teacher_id\n```\n```php\n// Creating subquery object\n$subquery = Query::selectFrom('teachers');\n$subquery-\u003ewhere('active', 1);\n\n$query = Query::selectFrom('groups AS g');\n$query\n    -\u003einnerJoin(['t' =\u003e $subquery])\n    -\u003eon('g.teacher_id', 't.teacher_id');\n$query-\u003ecolumns([\n    'g.group_id',\n    'teacher_name' =\u003e \"CONCAT(t.given_name, ' ', t.family_name)\"\n]);\n```\n\nSELECT nesting [↑](#table-of-contents)\n---------------------------------------\n\nIn some cases, simple database table joining isn't sufficient for meeting all\ndata requirements. It's common to need to execute additional filtered queries\nfor each row in the result of a primary query.\n\nHowever, this approach often leads to overly complex code and performance issues\ndue to increased loops and database access roundtrips. To address these\nchallenges, a more efficient and lightweight syntax is available for querying\nnested data.\n\n### Nesting a Collection of Result Objects\n\nThe `nestMany` method is used to nest a collection of result objects within each\nrow of the primary query's result. In the provided example, this is used to\nassociate multiple students with their respective groups. This approach is\nsuitable when you expect multiple related records for each main record.\n\n```php\n// Primary Query for Groups\n$groupsQuery = Query::selectFrom(\n    'groups',\n    ['group_id', 'subject', 'classroom']\n);\n\n// Query for Students\n$studentsQuery = Query::selectFrom(\n    'students',\n    ['student_id', 'group_id', 'first_name', 'last_name']\n);\n\n// Nesting students within each group\n$groupsQuery\n    -\u003enestMany('Students', $studentsQuery, $groupRow, Student::class)\n    -\u003ewhere('students.group_id', $groupRow-\u003egroup_id);\n\n// Connecting to the database and executing the query\n$db = DatabaseManager::connect('school');\n$result = $db-\u003eexecuteSelect($groupsQuery);\n$groups = $result-\u003etoArray(Group::class);\n```\n\n**Result:**\n\n```json\n[\n    {\n        \"group_id\": 1,\n        \"subject\": \"Programing fundamentals\",\n        \"classroom\": \"A113\",\n        \"Students\": [\n            {\n                \"student_id\": 325,\n                \"first_name\": \"Charlie\",\n                \"last_name\": \"Ortega\"\n            },\n            {\n                \"student_id\": 743,\n                \"first_name\": \"Beth\",\n                \"last_name\": \"Wilson\"\n            }\n        ]\n    },\n    {\n        \"group_id\": 2,\n        \"subject\" : \"Object Oriented Programming\",\n        \"classroom\": \"G7-R5\",\n        \"Students\": [\n            {\n                \"student_id\": 536,\n                \"first_name\": \"Dylan\",\n                \"last_name\": \"Morrison\"\n            }\n        ]\n    }\n]\n```\n\n### Nesting the First or Last Result Object\n\nOn the other hand, the `linkFirst` method is employed to link only the first\nresult object from a secondary query with each row of the primary query's\nresult. In the given code snippet, this is used to link the first teacher to\neach group. This method is beneficial when you want to link a single related\nrecord to each main record, prioritizing the first match.\n\nAdditionally, there is the `linkLast` method, which is similar to `linkFirst`\nbut instead links the last result object from a secondary query to each row of\nthe primary query's result. This can be useful in scenarios where you want to\nprioritize the most recent or latest related record for each main record.\n\n```php\n// Primary Query for Groups\n$groupsQuery = Query::selectFrom(\n    'groups',\n    ['group_id', 'teacher_id', 'subject', 'classroom']\n);\n\n// Query for Teachers\n$teachersQuery = Query::selectFrom(\n    'teachers',\n    ['teacher_id', 'first_name', 'last_name']\n);\n\n// Linking the first teacher to each group\n$groupsQuery\n    -\u003elinkFirst('Teacher', $teachersQuery, $groupRow, Teacher::class)\n    -\u003ewhere('teachers.teacher_id', $groupRow-\u003eteacher_id);\n\n// Query for Classes\n$classesQuery = Query::selectFrom(\n    'groups_classes',\n    ['class_id', 'group_id', 'topic', 'date']\n)-\u003eorderBy('date', 'ASC');\n\n// Linking the last class to each group\n$groups\n    -\u003elinkLast('LastClass', $classesQuery, $groupRow, GroupClass::class)\n    -\u003ewhere('groups_classes.group_id', $groupRow-\u003egroup_id);\n\n// Connecting to the database and executing the query\n$db = DatabaseManager::connect('school');\n$result = $db-\u003eexecuteSelect($groupsQuery);\n$groups = $result-\u003etoArray(Group::class);\n```\n\n**Result:**\n\n```json\n[\n    {\n        \"group_id\": 1,\n        \"teacher_id\": 3,\n        \"subject\": \"Programming fundamentals\",\n        \"classroom\": \"A113\",\n        \"Teacher\": {\n            \"teacher_id\": 3,\n            \"first_name\": \"Rosemary\",\n            \"last_name\": \"Smith\"\n        },\n        \"LastClass\": {\n            \"class_id\": 233,\n            \"group_id\": 1,\n            \"topic\": \"Algorithms\",\n            \"date\": \"2024-04-18\"\n        }\n    },\n    {\n        \"group_id\": 2,\n        \"teacher_id\": 75,\n        \"subject\" : \"Object Oriented Programming\",\n        \"classroom\": \"G7-R5\",\n        \"Teacher\": {\n            \"teacher_id\": 75,\n            \"first_name\": \"Steve\",\n            \"last_name\": \"Johnson\"\n        },\n        \"LastClass\": null\n    }\n]\n```\n\nBy choosing the appropriate nesting mode (`nestMany`, `linkFirst`, or\n`linkLast`), you can tailor your queries to efficiently handle nested data based\non your specific data structure and requirements.\n\n\u003e **Legacy old nest syntax**  \n\u003e\n\u003e There is a legacy nest syntax, that stills working underhood.\n\u003e\n\u003e ```php\n\u003e $groupsQuery-\u003enest(['Students' =\u003e $studentsQuery], function (NestedSelect $nest, RowProxy $row) {\n\u003e     $nest-\u003egetSelect()-\u003ewhere('s.group_id', $row-\u003egroup_id);\n\u003e }, NestMode::COLLECTION, Student::class);\n\u003e ```\n\nTransactions [↑](#table-of-contents)\n---------------------------------------\n\nOne of the most important features in databases is to keep data consistency\nacross multiple records that might be stored in multiple tables.\n\n```php\n$db = DatabaseManager::connect('school');\ntry {\n    $db-\u003estartTransaction();\n    \n    // Perform any needed operation inside this block to keep consistency.\n    \n    $db-\u003ecommit();\n} catch (Exception $ex) {\n    $db-\u003erollback();\n}\n```\n\n\nExecuting Stored Procedures [↑](#table-of-contents)\n---------------------------------------\n\n```php\n// Connecting to database 'school'.\n$db = DatabaseManager::connect('school');\n\n// Calls stored procedure with two argments.\n/** @var SelectResult[] */\n$results = $db-\u003ecall('procedure_name', 'arg1', 'arg2');\n\n// Shows how many results obtained from procedure.\necho count($results) . ' results.' . PHP_EOL;\n\n// Iterating procedure result sets.\nforeach ($results as $i =\u003e $selectResult) {\n    echo \"Fetched \" . $selectResult-\u003egetNumRows() . PHP_EOL;\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrancerz%2Fphp-sql-builder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffrancerz%2Fphp-sql-builder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrancerz%2Fphp-sql-builder/lists"}