{"id":13527830,"url":"https://github.com/voku/simple-mysqli","last_synced_at":"2025-04-01T10:32:51.493Z","repository":{"id":19349836,"uuid":"22589186","full_name":"voku/simple-mysqli","owner":"voku","description":":gem: Simple MySQLi Abstraction Layer + Doctrine/DBAL support","archived":false,"fork":true,"pushed_at":"2024-06-08T23:47:57.000Z","size":1032,"stargazers_count":45,"open_issues_count":2,"forks_count":12,"subscribers_count":10,"default_branch":"master","last_synced_at":"2024-10-29T23:51:26.548Z","etag":null,"topics":["database","database-connector","db","hacktoberfest","mysqli","mysqli-to-pdo","php","sql"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"entomb/OBJ-MySQL","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/voku.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null},"funding":{"github":["voku"],"patreon":"voku","tidelift":"packagist/voku/simple-mysqli","custom":"https://www.paypal.me/moelleken"}},"created_at":"2014-08-04T02:16:56.000Z","updated_at":"2024-10-02T20:31:39.000Z","dependencies_parsed_at":"2023-09-24T10:36:33.055Z","dependency_job_id":null,"html_url":"https://github.com/voku/simple-mysqli","commit_stats":{"total_commits":589,"total_committers":18,"mean_commits":32.72222222222222,"dds":0.7266553480475382,"last_synced_commit":"a4eddfd7d551b10af95e9d3224bd308450c62821"},"previous_names":[],"tags_count":100,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/voku%2Fsimple-mysqli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/voku%2Fsimple-mysqli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/voku%2Fsimple-mysqli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/voku%2Fsimple-mysqli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/voku","download_url":"https://codeload.github.com/voku/simple-mysqli/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246625656,"owners_count":20807797,"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","database-connector","db","hacktoberfest","mysqli","mysqli-to-pdo","php","sql"],"created_at":"2024-08-01T06:02:03.063Z","updated_at":"2025-04-01T10:32:51.466Z","avatar_url":"https://github.com/voku.png","language":"PHP","funding_links":["https://github.com/sponsors/voku","https://patreon.com/voku","https://tidelift.com/funding/github/packagist/voku/simple-mysqli","https://www.paypal.me/moelleken","https://www.patreon.com/voku","https://paypal.me/moelleken","https://www.patreon.com/voku/posts"],"categories":["PHP"],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/voku/simple-mysqli.svg?branch=master)](https://travis-ci.org/voku/simple-mysqli)\n[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fvoku%2Fsimple-mysqli.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fvoku%2Fsimple-mysqli?ref=badge_shield)\n[![Coverage Status](https://coveralls.io/repos/github/voku/simple-mysqli/badge.svg?branch=master)](https://coveralls.io/github/voku/simple-mysqli?branch=master)\n[![Codacy Badge](https://api.codacy.com/project/badge/Grade/797ba3ba657d4e0e86f0bade6923fdec)](https://www.codacy.com/app/voku/simple-mysqli)\n[![Latest Stable Version](https://poser.pugx.org/voku/simple-mysqli/v/stable)](https://packagist.org/packages/voku/simple-mysqli) \n[![Total Downloads](https://poser.pugx.org/voku/simple-mysqli/downloads)](https://packagist.org/packages/voku/simple-mysqli)\n[![License](https://poser.pugx.org/voku/simple-mysqli/license)](https://packagist.org/packages/voku/simple-mysqli)\n[![Donate to this project using Paypal](https://img.shields.io/badge/paypal-donate-yellow.svg)](https://www.paypal.me/moelleken)\n[![Donate to this project using Patreon](https://img.shields.io/badge/patreon-donate-yellow.svg)](https://www.patreon.com/voku)\n\n# :gem: Simple MySQLi Class\n\nThis is a simple MySQL Abstraction Layer compatible with PHP 7+ \u0026 PHP 8.0 that provides a simple \nand _secure_ interaction with your database using mysqli_* functions at \nits core. This is perfect for small scale applications such as cron jobs, \nfacebook canvas campaigns or micro frameworks or sites. \n\nYou can also use the :ring: [\"Simple Active Record\"](https://github.com/voku/simple-active-record)-class, it's based on this db class and add some OOP syntax. But please inform you about \"Active Record\" vs \"Data Mapper\" before you use it.\n\n\n### Get \"Simple MySQLi\"\n\nYou can download it from here, or require it using [composer](https://packagist.org/packages/voku/simple-mysqli).\n```json\n  {\n      \"require\": {\n        \"voku/simple-mysqli\": \"8.*\"\n      }\n  }\n```\n\n### Install via \"composer require\"\n```shell\n  composer require voku/simple-mysqli\n```\n\n* [Starting the driver](#starting-the-driver)\n* [Multiton \u0026\u0026 Singleton](#multiton--singleton)\n* [Doctrine/DBAL as parent driver](#doctrinedbal-as-parent-driver)\n* [Using the \"DB\"-Class](#using-the-db-class)\n  * [Selecting and retrieving data from a table](#selecting-and-retrieving-data-from-a-table)\n  * [Inserting data on a table](#inserting-data-on-a-table)\n  * [Binding parameters on queries](#binding-parameters-on-queries)\n  * [Transactions](#transactions)\n* [Using the \"Result\"-Class](#using-the-result-class)\n  * [Fetching all data](#fetching-all-data) \n  * [Fetching database-table-fields](#fetching-database-table-fields)\n  * [Fetching + Callable](#fetching--callable)\n  * [Fetching + Transpose](#fetching--transpose)\n  * [Fetching + Pairs](#fetching--pairs)\n  * [Fetching + Groups](#fetching--groups)\n  * [Fetching + first](#fetching--first)\n  * [Fetching + last](#fetching--last)\n  * [Fetching + slice](#fetching--slice)\n  * [Fetching + map](#fetching--map)\n  * [Fetching + aliases](#fetching--aliases)\n  * [Fetching + Iterations](#fetching--iterations)\n* [Using the \"Prepare\"-Class](#using-the-prepare-class)\n  * [INSERT-Prepare-Query (example)](#insert-prepare-query-example)\n  * [SELECT-Prepare-Query (example)](#select-prepare-query-example)\n* [Logging and Errors](#logging-and-errors)\n* [Changelog](#changelog)\n\n\n### Starting the driver\n```php\n  use voku\\db\\DB;\n\n  require_once 'composer/autoload.php';\n\n  $db = DB::getInstance('yourDbHost', 'yourDbUser', 'yourDbPassword', 'yourDbName');\n  \n  // example\n  // $db = DB::getInstance('localhost', 'root', '', 'test');\n```\n\n### Multiton \u0026\u0026 Singleton\n\nYou can use ```DB::getInstance()``` without any parameters and you will get your (as \"singleton\") first initialized connection. Or you can change the parameter and you will create an new \"multiton\"-instance which works like an singleton, but you need to use the same parameters again, otherwise (without the same parameter) you will get an new instance. \n\n### Doctrine/DBAL as parent driver\n```php\n  use voku\\db\\DB;\n\n  require_once 'composer/autoload.php';\n  \n  $connectionParams = [\n      'dbname'   =\u003e 'yourDbName',\n      'user'     =\u003e 'yourDbUser',\n      'password' =\u003e 'yourDbPassword',\n      'host'     =\u003e 'yourDbHost',\n      'driver'   =\u003e 'mysqli', // 'pdo_mysql' || 'mysqli'\n      'charset'  =\u003e 'utf8mb4',\n  ];\n  $config = new \\Doctrine\\DBAL\\Configuration();\n  $doctrineConnection = \\Doctrine\\DBAL\\DriverManager::getConnection(\n      $connectionParams,\n      $config\n  );\n  $doctrineConnection-\u003econnect();\n\n  $db = DB::getInstanceDoctrineHelper($doctrineConnection);\n```\n\n## Using the \"DB\"-Class\n\nThere are numerous ways of using this library, here are some examples of the most common methods.\n\n#### Selecting and retrieving data from a table\n\n```php\n  use voku\\db\\DB;\n  \n  $db = DB::getInstance();\n  \n  $result = $db-\u003equery(\"SELECT * FROM users\");\n  $users  = $result-\u003efetchAll();\n```\n\nBut you can also use a method for select-queries:\n\n```php\n  $db-\u003eselect(string $table, array $where); // generate an SELECT query\n```\n\nExample: SELECT\n```php\n  $where = [\n      'page_type ='         =\u003e 'article',\n      'page_type NOT LIKE'  =\u003e '%öäü123',\n      'page_id \u003e='          =\u003e 2,\n  ];\n  $articles = $db-\u003eselect('page', $where);\n  \n  echo 'There are ' . count($articles) . ' article(s):' . PHP_EOL;\n  \n  foreach ($articles as $article) {\n      echo 'Type: ' . $article['page_type'] . PHP_EOL;\n      echo 'ID: ' . $article['page_id'] . PHP_EOL;\n  }\n```\n\nHere is a list of connectors for the \"WHERE\"-array:\n'NOT', 'IS', 'IS NOT', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN', 'LIKE', 'NOT LIKE', '\u003e', '\u003c', '\u003e=', '\u003c=', '\u003c\u003e', '+', '-'\n\nINFO: use an array as $value for \"[NOT] IN\" and \"[NOT] BETWEEN\"\n\nINFO: use + / - in the value not in the key of the $data\n\nExample: UPDATE with \"page_template = page_template + 1\"\n```php\n  $where = [\n      'page_type LIKE'     =\u003e '%foo',\n      'page_type NOT LIKE' =\u003e 'bar',\n  ];\n  $data = [\n      'page_template' =\u003e ['page_template +' =\u003e 1],\n      'page_type'     =\u003e 'lall',\n  ];\n  $resultSelect = $db-\u003eupdate('page', $data, $where);\n```\n\nExample: SELECT with \"NOT IN\"\n```php\n  $where = [\n      'page_type NOT IN' =\u003e [\n          'foo',\n          'bar'\n      ],\n      'page_id \u003e'        =\u003e 2,\n  ];\n  $resultSelect = $db-\u003eselect('page', $where);\n```\n\nExample: SELECT with Cache\n```php\n  $resultSelect = $db-\u003eexecSQL(\"SELECT * FROM users\", true, 3600);\n```\n\nThe result (via $result-\u003efetchAllArray()) is only cached for 3600s when the query was a SELECT statement, otherwise you get the default result from the ```$db-\u003equery()``` function. \n\n#### Inserting data on a table\n\nto manipulate tables you have the most important methods wrapped,\nthey all work the same way: parsing arrays of key/value pairs and forming a safe query\n\nthe methods are:\n```php\n  $db-\u003einsert( string $table, array $data );                // generate an INSERT query\n  $db-\u003ereplace( string $table, array $data );               // generate an REPLACE query\n  $db-\u003eupdate( string $table, array $data, array $where );  // generate an UPDATE query\n  $db-\u003edelete( string $table, array $where );               // generate a DELETE query\n```\n\nAll methods will return the resulting `mysqli_insert_id()` or true/false depending on context.\nThe correct approach if to always check if they executed as success is always returned\n\nExample: DELETE\n```php\n  $deleteArray = ['user_id' =\u003e 9];\n  $ok = $db-\u003edelete('users', $deleteArray);\n  if ($ok) {\n    echo \"user deleted!\";\n  } else {\n    echo \"can't delete user!\";\n  }\n```\n\n**note**: all parameter values are sanitized before execution, you don\\'t have to escape values beforehand.\n\nExample: INSERT\n```php\n  $insertArray = [\n    'name'   =\u003e \"John\",\n    'email'  =\u003e \"johnsmith@email.com\",\n    'group'  =\u003e 1,\n    'active' =\u003e true,\n  ];\n  $newUserId = $db-\u003einsert('users', $insertArray);\n  if ($newUserId) {\n    echo \"new user inserted with the id $new_user_id\";\n  }\n```\n\nExample: REPLACE\n```php\n  $replaceArray = [\n      'name'   =\u003e 'lars',\n      'email'  =\u003e 'lars@moelleken.org',\n      'group'  =\u003e 0\n  ];\n  $tmpId = $db-\u003ereplace('users', $replaceArray);\n```\n\n#### Binding parameters on queries\n\nBinding parameters is a good way of preventing mysql injections as the parameters are sanitized before execution.\n\n```php\n  $sql = \"SELECT * FROM users \n    WHERE id_user = :id_user\n    AND active = :active\n    LIMIT 1\n  \";\n  $result = $db-\u003equery($sql, ['id_user' =\u003e 11, 'active' =\u003e 1]);\n  if ($result) {\n    $user = $result-\u003efetchArray();\n    print_r($user);\n  } else {\n    echo \"user not found\";\n  }\n```\n\n#### Transactions\n\nUse `begin()`, `commit()`, and `rollback()` to manage transactions:\n\n```php\n$db-\u003ebeginTransaction();\n\n$db-\u003equery(\n    'UPDATE `users` SET `foo` = :foo WHERE id = :id',\n    ['foo' =\u003e 100, 'id' =\u003e 1]\n);\n$db-\u003equery(\n    'UPDATE `users_noop` SET `foo` = :foo WHERE id = :id',\n    ['foo' =\u003e 100, 'id' =\u003e 2]\n);\n\n$db-\u003eendTransaction();\n```\n\nAny SQL errors between `begin()` and `commit()` will yield a `RuntimeException`.\n\nYou can also use the `DB-\u003etransact()` method. The following is equivalent\nto the above:\n\n```php\n$db-\u003etransact(function($db) {\n    $db-\u003equery(\n        'UPDATE `users` SET `foo` = :foo WHERE id = :id',\n        ['foo' =\u003e 100, 'id' =\u003e 1]\n    );\n    $db-\u003equery(\n        'UPDATE `users_noop` SET `foo` = :foo WHERE id = :id',\n        ['foo' =\u003e 100, 'id' =\u003e 2]\n    );\n});\n```\n\n### Using the \"Result\"-Class\n\nAfter executing a `SELECT` query you receive a `Result` object that will help you manipulate the resultant data.\nthere are different ways of accessing this data, check the examples bellow:\n\n#### Fetching all data\n\n```php\n  $result = $db-\u003equery(\"SELECT * FROM users\");\n  $allUsers = $result-\u003efetchAll();\n```\nFetching all data works as Result::RESULT_TYPE_* the `fetchAll()` and `fetch()` method will return the default based on the `$_default_result_type` config.\nOther methods are:\n\n```php\n  $row = $result-\u003efetch();        // fetch an single result row as defined by the config (array, object or Arrayy)\n  $row = $result-\u003efetchArray();   // fetch an single result row as array\n  $row = $result-\u003efetchArrayy();  // fetch an single result row as Arrayy object\n  $row = $result-\u003efetchObject();  // fetch an single result row as object\n  $row = $result-\u003efetchYield();   // fetch an single result row as Generator\n  \n  $data = $result-\u003efetchAll();        // fetch all result data as defined by the config (array, object or Arrayy)\n  $data = $result-\u003efetchAllArray();   // fetch all result data as array\n  $data = $result-\u003efetchAllArrayy();  // fetch all result data as Array object\n  $data = $result-\u003efetchAllObject();  // fetch all result data as object\n  $data = $result-\u003efetchAllYield();   // fetch all result data as Generator\n  \n  $data = $result-\u003efetchColumn(string $column, bool $skipNullValues);    // fetch a single column as string\n  $data = $result-\u003efetchAllColumn(string $column, bool $skipNullValues); // fetch a single column as an 1-dimension array\n  \n  $data = $result-\u003efetchArrayPair(string $key, string $value);           // fetch data as a key/value pair array\n```\n\n#### Fetching database-table-fields\n\nReturns rows of field information in a result set:\n\n```php\n$fields = $result-\u003efetchFields();\n```\n\nPass `true` as argument if you want each field information returned as an\nassociative array instead of an object. The default is to return each as an\nobject, exactly like the `mysqli_fetch_fields` function.\n\n#### Fetching + Callable\n\nFetches a row or a single column within a row:\n\n```php\n$data = $result-\u003efetch($row_number, $column);\n```\n\nThis method forms the basis of all fetch_ methods. All forms of fetch_ advances\nthe internal row pointer to the next row. `null` will be returned when there are\nno more rows to be fetched.\n\n#### Fetching + Transpose\n\nReturns all rows at once, transposed as an array of arrays:\n\n```php\n$plan_details = $plans-\u003efetchTranspose();\n```\n\nTransposing a result set of X rows each with Y columns will result in an array\nof Y rows each with X columns.\n\nPass a column name as argument to return each column as an associative array\nwith keys taken from values of the provided column. If not provided, the keys\nwill be numeric starting from zero.\n\ne.g.:\n```php\n$transposedExample = [\n  'title' =\u003e [\n    1 =\u003e 'Title #1',\n    2 =\u003e 'Title #2',\n    3 =\u003e 'Title #3',\n  ],\n);\n```\n\n#### Fetching + Pairs\n\nReturns all rows at once as key-value pairs using the column in the first\nargument as the key:\n\n```php\n$countries = $result-\u003efetchPairs('id');\n```\n\nPass a column name as the second argument to only return a single column as the\nvalue in each pair:\n\n```php\n$countries = $result-\u003efetchPairs('id', 'name');\n\n/*\n[\n  1 =\u003e 'Title #1',\n  2 =\u003e 'Title #2',\n  3 =\u003e 'Title #3',\n]\n*/\n```\n\n#### Fetching + Groups\n\nReturns all rows at once as a grouped array:\n\n```php\n$students_grouped_by_gender = $result-\u003efetchGroups('gender');\n```\n\nPass a column name as the second argument to only return single columns as the\nvalues in each groups:\n\n```php\n$student_names_grouped_by_gender = $result-\u003efetchGroups('gender', 'name');\n```\n\n#### Fetching + first\n\nReturns the first row element from the result:\n\n```php\n$first = $result-\u003efirst();\n```\n\nPass a column name as argument to return a single column from the first row:\n\n```php\n$name = $result-\u003efirst('name');\n```\n\n#### Fetching + last\n\nReturns the last row element from the result:\n\n```php\n$last = $result-\u003elast();\n```\n\nPass a column name as argument to return a single column from the last row:\n\n```php\n$name = $result-\u003elast('name');\n```\n\n#### Fetching + slice\n\nReturns a slice of rows from the result:\n\n```php\n$slice = $result-\u003eslice(1, 10);\n```\n\nThe above will return 10 rows skipping the first one. The first parameter is the\nzero-based offset; the second parameter is the number of elements; the third\nparameter is a boolean value to indicate whether to preserve the keys or not\n(optional and defaults to false). This methods essentially behaves the same as\nPHP's built-in `array_slice()` function.\n\n#### Fetching + map\n\nSets a mapper callback function that's used inside the `Result-\u003efetchCallable()` method:\n\n```php\n$result-\u003emap(function($row) {\n    return (object) $row;\n});\n$object = $result-\u003efetchCallable(0);\n```\n\nThe above example will map one row (0) from the result into a\nobject. Set the mapper callback function to null to disable it.\n\n#### Fetching + aliases\n```php\n  $db-\u003eget()                  // alias for $db-\u003efetch();\n  $db-\u003egetAll()               // alias for $db-\u003efetchAll();\n  $db-\u003egetObject()            // alias for $db-\u003efetchAllObject();\n  $db-\u003egetArray()             // alias for $db-\u003efetchAllArray();\n  $db-\u003egetArrayy()            // alias for $db-\u003efetchAllArrayy();\n  $db-\u003egetYield()             // alias for $db-\u003efetchAllYield();\n  $db-\u003egetColumn($key)        // alias for $db-\u003efetchColumn($key);\n```\n\n#### Fetching + Iterations\nTo iterate a result-set you can use any fetch() method listed above.\n\n```php\n  $result = $db-\u003eselect('users');\n\n  // using while\n  while ($row = $result-\u003efetch()) {\n    echo $row-\u003ename;\n    echo $row-\u003eemail;\n  }\n\n  // using foreach (via \"fetchAllObject()\")\n  foreach($result-\u003efetchAllObject() as $row) {\n    echo $row-\u003ename;\n    echo $row-\u003eemail;\n  }\n  \n  // using foreach (via \"Result\"-object)\n  foreach($result as $row) {\n    echo $row-\u003ename;\n    echo $row-\u003eemail;\n  }\n  \n  // using foreach (via \"Generator\"-object)\n  foreach($result-\u003efetchAllYield() as $row) {\n    echo $row-\u003ename;\n    echo $row-\u003eemail;\n  }\n  \n  // INFO: \"while + fetch()\" and \"fetchAllYield()\" will use less memory that \"foreach + \"fetchAllObject()\", because we will fetch each result entry seperatly\n```\n\n#### Executing Multi Queries\nTo execute multiple queries you can use the ```$db-\u003emulti_query()``` method. You can use multiple queries separated by \"```;```\".\n\nReturn-Types:     \n\u003cul\u003e\n\u003cli\u003e\"Result\"-Array by \"\u003cb\u003eSELECT\u003c/b\u003e\"-queries\u003c/li\u003e\n\u003cli\u003e\"bool\" by only \"\u003cb\u003eINSERT\u003c/b\u003e\"-queries\u003c/li\u003e\n\u003cli\u003e\"bool\" by only (affected_rows) by \"\u003cb\u003eUPDATE / DELETE\u003c/b\u003e\"-queries\u003c/li\u003e\n\u003cli\u003e\"bool\" by only by e.g. \"DROP\"-queries\u003c/li\u003e\n\u003c/ul\u003e\n\ne.g.:\n\n```php\n$sql = \"\n    INSERT INTO foo\n      SET\n        page_template = 'lall1',\n        page_type = 'test1';\n    INSERT INTO lall\n      SET\n        page_template = 'lall2',\n        page_type = 'test2';\n    INSERT INTO bar\n      SET\n        page_template = 'lall3',\n        page_type = 'test3';\n\";\n$result = $this-\u003edb-\u003emulti_query($sql); // true\n\n$sql = \"\n    SELECT * FROM foo;\n    SELECT * FROM lall;\n    SELECT * FROM bar;\n\";\n$result = $this-\u003edb-\u003emulti_query($sql); // Result[]\nforeach ($result as $resultForEach) {\n    $tmpArray = $resultForEach-\u003efetchArray();\n    ...\n}\n```\n\n## Using the \"Prepare\"-Class\n\nPrepare statements have the advantage that they are built together in the MySQL-Server, so the performance is better.\n\nBut the debugging is harder and logging is impossible (via PHP), so we added a wrapper for \"bind_param\" called \"bind_param_debug\". \nWith this wrapper we pre-build the sql-query via php (only for debugging / logging). Now you can e.g. echo the query.\n\nINFO: You can still use \"bind_param\" instead of \"bind_param_debug\", e.g. if you need better performance.\n\n#### INSERT-Prepare-Query (example)\n```php\n  use voku\\db\\DB;\n  \n  $db = DB::getInstance();\n  \n  // ------------- \n  // prepare the queries\n  \n  $query = 'INSERT INTO users\n    SET \n      name = ?, \n      email = ?\n  ';\n  \n  $prepare = $db-\u003eprepare($query);\n  \n  $name = '';\n  $email = '';\n  \n  $prepare-\u003ebind_param_debug('ss', $name, $email);\n  \n  // -------------\n  // execute query no. 1\n  \n  // INFO: \"$template\" and \"$type\" are references, since we use \"bind_param\" or \"bind_param_debug\" \n  $name = 'name_1_中';\n  $email = 'foo@bar.com';\n  \n  $prepare-\u003eexecute();\n  \n  // DEBUG\n  echo $prepare-\u003eget_sql_with_bound_parameters();\n  \n  // -------------\n  // execute query no. 2\n  \n  // INFO: \"$template\" and \"$type\" are references, since we use \"bind_param\" or \"bind_param_debug\"  \n  $name = 'Lars';\n  $email = 'lars@moelleken.org';\n  \n  $prepare-\u003eexecute();\n  \n  // DEBUG\n  echo $prepare-\u003eget_sql_with_bound_parameters();\n```\n\n#### SELECT-Prepare-Query (example)\n```php\n  use voku\\db\\DB;\n  \n  $db = DB::getInstance();\n  \n  // -------------\n  // insert some dummy-data, first\n  \n  $data = [\n      'page_template' =\u003e 'tpl_test_new123123',\n      'page_type'     =\u003e 'ö\\'ä\"ü',\n  ];\n\n  // will return the auto-increment value of the new row\n  $resultInsert[1] = $db-\u003einsert($this-\u003etableName, $data);\n  $resultInsert[2] = $db-\u003einsert($this-\u003etableName, $data);\n\n  // ------------- \n  // prepare the queries\n\n  $sql = 'SELECT * FROM ' . $this-\u003etableName . ' \n    WHERE page_id = ?\n  ';\n\n  $prepare = $this-\u003edb-\u003eprepare($sql);\n  $page_id = 0;\n  $prepare-\u003ebind_param_debug('i', $page_id);\n\n  // ------------- \n  // execute query no. 1\n\n  $page_id = $resultInsert[1];\n  $result = $prepare-\u003eexecute();\n  $data = $result-\u003efetchArray();\n\n  // $data['page_template'] === 'tpl_test_new123123'\n  // $data['page_id'] === $page_id\n\n  // ------------- \n  // execute query no. 2\n\n  $page_id = $resultInsert[2];\n  $result = $prepare-\u003eexecute();\n  $data = $result-\u003efetchArray();\n\n  // $data['page_id'] === $page_id\n  // $data['page_template'] === 'tpl_test_new123123'\n```\n\n### Logging and Errors\n\nYou can hook into the \"DB\"-Class, so you can use your personal \"Logger\"-Class. But you have to cover the methods:\n\n```php\n$this-\u003etrace(string $text, string $name) { ... }\n$this-\u003edebug(string $text, string $name) { ... }\n$this-\u003einfo(string $text, string $name) { ... }\n$this-\u003ewarn(string $text, string $name) { ... } \n$this-\u003eerror(string $text, string $name) { ... }\n$this-\u003efatal(string $text, string $name) { ... }\n```\n\nYou can also disable the logging of every sql-query, with the \"getInstance()\"-parameter \"logger_level\" from \"DB\"-Class.\nIf you set \"logger_level\" to something other than \"TRACE\" or \"DEBUG\", the \"DB\"-Class will log only errors anymore.\n\n```php\nDB::getInstance(\n    getConfig('db', 'hostname'),        // hostname\n    getConfig('db', 'username'),        // username\n    getConfig('db', 'password'),        // password\n    getConfig('db', 'database'),        // database\n    getConfig('db', 'port'),            // port\n    getConfig('db', 'charset'),         // charset\n    true,                               // exit_on_error\n    true,                               // echo_on_error\n    'cms\\Logger',                       // logger_class_name\n    getConfig('logger', 'level'),       // logger_level | 'TRACE', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'FATAL'\n    getConfig('session', 'db')          // session_to_db\n);\n```\n\nShowing the query log: The log comes with the SQL executed, the execution time and the result row count.\n\n```php\n  print_r($db-\u003elog());\n```\n\nTo debug mysql errors, use `$db-\u003eerrors()` to fetch all errors (returns false if there are no errors) or `$db-\u003elastError()` for information about the last error. \n\n```php\n  if ($db-\u003eerrors()) {\n    echo $db-\u003elastError();\n  }\n```\n\nBut the easiest way for debugging is to configure \"DB\"-Class via \"DB::getInstance()\" to show errors and exit on error (see the example above). Now you can see SQL-errors in your browser if you are working on \"localhost\" or you can implement your own \"checkForDev()\" via a simple function, you don't need to extend the \"Debug\"-Class. If you will receive error-messages via e-mail, you can implement your own \"mailToAdmin()\"-function instead of extending the \"Debug\"-Class.\n\n### Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md).\n\n### Support\n\nFor support and donations please visit [Github](https://github.com/voku/simple-mysqli/) | [Issues](https://github.com/voku/simple-mysqli/issues) | [PayPal](https://paypal.me/moelleken) | [Patreon](https://www.patreon.com/voku).\n\nFor status updates and release announcements please visit [Releases](https://github.com/voku/simple-mysqli/releases) | [Twitter](https://twitter.com/suckup_de) | [Patreon](https://www.patreon.com/voku/posts).\n\nFor professional support please contact [me](https://about.me/voku).\n\n### Thanks\n\n- Thanks to [GitHub](https://github.com) (Microsoft) for hosting the code and a good infrastructure including Issues-Managment, etc.\n- Thanks to [IntelliJ](https://www.jetbrains.com) as they make the best IDEs for PHP and they gave me an open source license for PhpStorm!\n- Thanks to [Travis CI](https://travis-ci.com/) for being the most awesome, easiest continous integration tool out there!\n- Thanks to [StyleCI](https://styleci.io/) for the simple but powerfull code style check.\n- Thanks to [PHPStan](https://github.com/phpstan/phpstan) \u0026\u0026 [Psalm](https://github.com/vimeo/psalm) for relly great Static analysis tools and for discover bugs in the code!\n\n### License\n[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fvoku%2Fsimple-mysqli.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fvoku%2Fsimple-mysqli?ref=badge_large)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvoku%2Fsimple-mysqli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvoku%2Fsimple-mysqli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvoku%2Fsimple-mysqli/lists"}