[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-8535":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":16,"stars30d":17,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":18,"rankGlobal":10,"rankLanguage":10,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":22,"hasPages":20,"topics":23,"createdAt":10,"pushedAt":10,"updatedAt":24,"readmeContent":25,"aiSummary":26,"trendingCount":16,"starSnapshotCount":16,"syncStatus":27,"lastSyncTime":28,"discoverSource":29},8535,"PHP-MySQLi-Database-Class","ThingEngineer\u002FPHP-MySQLi-Database-Class","ThingEngineer","Wrapper for a PHP MySQL class, which utilizes MySQLi and prepared statements. ","",null,"PHP",3302,1316,262,182,0,1,61.46,"Other",false,"master",true,[],"2026-06-12 04:00:40","MysqliDb -- Simple MySQLi wrapper and object mapper with prepared statements\n\u003Chr>\n\n### Table of Contents\n\n**[Initialization](#initialization)**  \n**[Objects mapping](#objects-mapping)**  \n**[Insert Query](#insert-query)**  \n**[Update Query](#update-query)**  \n**[Select Query](#select-query)**  \n**[Delete Query](#delete-query)**  \n**[Insert Data](#insert-data)**  \n**[Insert XML](#insert-xml)**  \n**[Pagination](#pagination)**  \n**[Running raw SQL queries](#running-raw-sql-queries)**  \n**[Query Keywords](#query-keywords)**  \n**[Where Conditions](#where--having-methods)**  \n**[Order Conditions](#ordering-method)**  \n**[Group Conditions](#grouping-method)**  \n**[Properties Sharing](#properties-sharing)**  \n**[Joining Tables](#join-method)**  \n**[Subqueries](#subqueries)**  \n**[EXISTS \u002F NOT EXISTS condition](#exists--not-exists-condition)**  \n**[Has method](#has-method)**  \n**[Helper Methods](#helper-methods)**  \n**[Transaction Helpers](#transaction-helpers)**  \n**[Error Helpers](#error-helpers)**  \n**[Table Locking](#table-locking)**  \n\n## Support Me\n\nThis software is developed during my free time and I will be glad if somebody will support me.\n\nEveryone's time should be valuable, so please consider donating.\n\n[Donate with paypal](https:\u002F\u002Fwww.paypal.com\u002Fcgi-bin\u002Fwebscr?cmd=_donations&business=a%2ebutenka%40gmail%2ecom&lc=DO&item_name=mysqlidb&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted)\n\n### Installation\nTo utilize this class, first import MysqliDb.php into your project, and require it.\n\n```php\nrequire_once ('MysqliDb.php');\n```\n\n### Installation with composer\nIt is also possible to install library via composer\n```\ncomposer require thingengineer\u002Fmysqli-database-class:dev-master\n```\n\n### Initialization\nSimple initialization with utf8 charset set by default:\n```php\n$db = new MysqliDb ('host', 'username', 'password', 'databaseName');\n```\n\nAdvanced initialization:\n```php\n$db = new MysqliDb (Array (\n                'host' => 'host',\n                'username' => 'username', \n                'password' => 'password',\n                'db'=> 'databaseName',\n                'port' => 3306,\n                'prefix' => 'my_',\n                'charset' => 'utf8'));\n```\ntable prefix, port and database charset params are optional.\nIf no charset should be set charset, set it to null\n\nAlso it is possible to reuse already connected mysqli object:\n```php\n$mysqli = new mysqli ('host', 'username', 'password', 'databaseName');\n$db = new MysqliDb ($mysqli);\n```\n\nIf no table prefix were set during object creation its possible to set it later with a separate call:\n```php\n$db->setPrefix ('my_');\n```\n\nIf connection to mysql will be dropped Mysqlidb will try to automatically reconnect to the database once. \nTo disable this behavoir use\n```php\n$db->autoReconnect = false;\n```\n\nIf you need to get already created mysqliDb object from another class or function use\n```php\n    function init () {\n        \u002F\u002F db staying private here\n        $db = new MysqliDb ('host', 'username', 'password', 'databaseName');\n    }\n    ...\n    function myfunc () {\n        \u002F\u002F obtain db object created in init  ()\n        $db = MysqliDb::getInstance();\n        ...\n    }\n```\n\n### Multiple database connection\nIf you need to connect to multiple databases use following method:\n```php\n$db->addConnection('slave', Array (\n                'host' => 'host',\n                'username' => 'username',\n                'password' => 'password',\n                'db'=> 'databaseName',\n                'port' => 3306,\n                'prefix' => 'my_',\n                'charset' => 'utf8')\n);\n```\nTo select database use connection() method\n```php\n$users = $db->connection('slave')->get('users');\n```\n\n### Objects mapping\ndbObject.php is an object mapping library built on top of mysqliDb to provide model representation functionality.\nSee \u003Ca href='dbObject.md'>dbObject manual for more information\u003C\u002Fa>\n\n### Insert Query\nSimple example\n```php\n$data = Array (\"login\" => \"admin\",\n               \"firstName\" => \"John\",\n               \"lastName\" => 'Doe'\n);\n$id = $db->insert ('users', $data);\nif($id)\n    echo 'user was created. Id=' . $id;\n```\n\nInsert with functions use\n```php\n$data = Array (\n\t'login' => 'admin',\n    'active' => true,\n\t'firstName' => 'John',\n\t'lastName' => 'Doe',\n\t'password' => $db->func('SHA1(?)',Array (\"secretpassword+salt\")),\n\t\u002F\u002F password = SHA1('secretpassword+salt')\n\t'createdAt' => $db->now(),\n\t\u002F\u002F createdAt = NOW()\n\t'expires' => $db->now('+1Y')\n\t\u002F\u002F expires = NOW() + interval 1 year\n\t\u002F\u002F Supported intervals [s]econd, [m]inute, [h]hour, [d]day, [M]onth, [Y]ear\n);\n\n$id = $db->insert ('users', $data);\nif ($id)\n    echo 'user was created. Id=' . $id;\nelse\n    echo 'insert failed: ' . $db->getLastError();\n```\n\nInsert with on duplicate key update\n```php\n$data = Array (\"login\" => \"admin\",\n               \"firstName\" => \"John\",\n               \"lastName\" => 'Doe',\n               \"createdAt\" => $db->now(),\n               \"updatedAt\" => $db->now(),\n);\n$updateColumns = Array (\"updatedAt\");\n$lastInsertId = \"id\";\n$db->onDuplicate($updateColumns, $lastInsertId);\n$id = $db->insert ('users', $data);\n```\n\nInsert multiple datasets at once\n```php\n$data = Array(\n    Array (\"login\" => \"admin\",\n        \"firstName\" => \"John\",\n        \"lastName\" => 'Doe'\n    ),\n    Array (\"login\" => \"other\",\n        \"firstName\" => \"Another\",\n        \"lastName\" => 'User',\n        \"password\" => \"very_cool_hash\"\n    )\n);\n$ids = $db->insertMulti('users', $data);\nif(!$ids) {\n    echo 'insert failed: ' . $db->getLastError();\n} else {\n    echo 'new users inserted with following id\\'s: ' . implode(', ', $ids);\n}\n```\n\nIf all datasets only have the same keys, it can be simplified\n```php\n$data = Array(\n    Array (\"admin\", \"John\", \"Doe\"),\n    Array (\"other\", \"Another\", \"User\")\n);\n$keys = Array(\"login\", \"firstName\", \"lastName\");\n\n$ids = $db->insertMulti('users', $data, $keys);\nif(!$ids) {\n    echo 'insert failed: ' . $db->getLastError();\n} else {\n    echo 'new users inserted with following id\\'s: ' . implode(', ', $ids);\n}\n```\n\n### Replace Query\n\u003Ca href='https:\u002F\u002Fdev.mysql.com\u002Fdoc\u002Frefman\u002F5.0\u002Fen\u002Freplace.html'>Replace()\u003C\u002Fa> method implements same API as insert();\n\n### Update Query\n```php\n$data = Array (\n\t'firstName' => 'Bobby',\n\t'lastName' => 'Tables',\n\t'editCount' => $db->inc(2),\n\t\u002F\u002F editCount = editCount + 2;\n\t'active' => $db->not()\n\t\u002F\u002F active = !active;\n);\n$db->where ('id', 1);\nif ($db->update ('users', $data))\n    echo $db->count . ' records were updated';\nelse\n    echo 'update failed: ' . $db->getLastError();\n```\n\n`update()` also support limit parameter:\n```php\n$db->update ('users', $data, 10);\n\u002F\u002F Gives: UPDATE users SET ... LIMIT 10\n```\n\n### Select Query\nAfter any select\u002Fget function calls amount or returned rows is stored in $count variable\n```php\n$users = $db->get('users'); \u002F\u002Fcontains an Array of all users \n$users = $db->get('users', 10); \u002F\u002Fcontains an Array 10 users\n```\n\nor select with custom columns set. Functions also could be used\n\n```php\n$cols = Array (\"id\", \"name\", \"email\");\n$users = $db->get (\"users\", null, $cols);\nif ($db->count > 0)\n    foreach ($users as $user) { \n        print_r ($user);\n    }\n```\n\nor select just one row\n\n```php\n$db->where (\"id\", 1);\n$user = $db->getOne (\"users\");\necho $user['id'];\n\n$stats = $db->getOne (\"users\", \"sum(id), count(*) as cnt\");\necho \"total \".$stats['cnt']. \"users found\";\n```\n\nor select one column value or function result\n\n```php\n$count = $db->getValue (\"users\", \"count(*)\");\necho \"{$count} users found\";\n```\n\nselect one column value or function result from multiple rows:\n```php\n$logins = $db->getValue (\"users\", \"login\", null);\n\u002F\u002F select login from users\n$logins = $db->getValue (\"users\", \"login\", 5);\n\u002F\u002F select login from users limit 5\nforeach ($logins as $login)\n    echo $login;\n```\n\n### Insert Data\nYou can also load .CSV or .XML data into a specific table.\nTo insert .csv data, use the following syntax:\n```php\n$path_to_file = \"\u002Fhome\u002Fjohn\u002Ffile.csv\";\n$db->loadData(\"users\", $path_to_file);\n```\nThis will load a .csv file called **file.csv** in the folder **\u002Fhome\u002Fjohn\u002F** (john's home directory.)\nYou can also attach an optional array of options.\nValid options are:\n\n```php\nArray(\n\t\"fieldChar\" => ';', \t\u002F\u002F Char which separates the data\n\t\"lineChar\" => '\\r\\n', \t\u002F\u002F Char which separates the lines\n\t\"linesToIgnore\" => 1\t\u002F\u002F Amount of lines to ignore at the beginning of the import\n);\n```\n\nAttach them using\n```php\n$options = Array(\"fieldChar\" => ';', \"lineChar\" => '\\r\\n', \"linesToIgnore\" => 1);\n$db->loadData(\"users\", \"\u002Fhome\u002Fjohn\u002Ffile.csv\", $options);\n\u002F\u002F LOAD DATA ...\n```\n\nYou can specify to **use LOCAL DATA** instead of **DATA**:\n```php\n$options = Array(\"fieldChar\" => ';', \"lineChar\" => '\\r\\n', \"linesToIgnore\" => 1, \"loadDataLocal\" => true);\n$db->loadData(\"users\", \"\u002Fhome\u002Fjohn\u002Ffile.csv\", $options);\n\u002F\u002F LOAD DATA LOCAL ...\n```\n\n### Insert XML\nTo load XML data into a table, you can use the method **loadXML**.\nThe syntax is smillar to the loadData syntax.\n```php\n$path_to_file = \"\u002Fhome\u002Fjohn\u002Ffile.xml\";\n$db->loadXML(\"users\", $path_to_file);\n```\n\nYou can also add optional parameters.\nValid parameters:\n```php\nArray(\n\t\"linesToIgnore\" => 0,\t\t\u002F\u002F Amount of lines \u002F rows to ignore at the beginning of the import\n\t\"rowTag\"\t=> \"\u003Cuser>\"\t\u002F\u002F The tag which marks the beginning of an entry\n)\n```\n\nUsage:\n```php\n$options = Array(\"linesToIgnore\" => 0, \"rowTag\"\t=> \"\u003Cuser>\"):\n$path_to_file = \"\u002Fhome\u002Fjohn\u002Ffile.xml\";\n$db->loadXML(\"users\", $path_to_file, $options);\n```\n\n### Pagination\nUse paginate() instead of get() to fetch paginated result\n```php\n$page = 1;\n\u002F\u002F set page limit to 2 results per page. 20 by default\n$db->pageLimit = 2;\n$products = $db->arraybuilder()->paginate(\"products\", $page);\necho \"showing $page out of \" . $db->totalPages;\n\n```\n\n### Result transformation \u002F map\nInstead of getting an pure array of results its possible to get result in an associative array with a needed key. If only 2 fields to fetch will be set in get(),\nmethod will return result in array($k => $v) and array ($k => array ($v, $v)) in rest of the cases.\n\n```php\n$user = $db->map ('login')->ObjectBuilder()->getOne ('users', 'login, id');\nArray\n(\n    [user1] => 1\n)\n\n$user = $db->map ('login')->ObjectBuilder()->getOne ('users', 'id,login,createdAt');\nArray\n(\n    [user1] => stdClass Object\n        (\n            [id] => 1\n            [login] => user1\n            [createdAt] => 2015-10-22 22:27:53\n        )\n\n)\n```\n\n### Defining a return type\nMysqliDb can return result in 3 different formats: Array of Array, Array of Objects and a Json string. To select a return type use ArrayBuilder(), ObjectBuilder() and JsonBuilder() methods. Note that ArrayBuilder() is a default return type\n```php\n\u002F\u002F Array return type\n$u= $db->getOne(\"users\");\necho $u['login'];\n\u002F\u002F Object return type\n$u = $db->ObjectBuilder()->getOne(\"users\");\necho $u->login;\n\u002F\u002F Json return type\n$json = $db->JsonBuilder()->getOne(\"users\");\n```\n\n### Running raw SQL queries\n```php\n$users = $db->rawQuery('SELECT * from users where id >= ?', Array (10));\nforeach ($users as $user) {\n    print_r ($user);\n}\n```\nTo avoid long if checks there are couple helper functions to work with raw query select results:\n\nGet 1 row of results:\n```php\n$user = $db->rawQueryOne('SELECT * from users where id=?', Array(10));\necho $user['login'];\n\u002F\u002F Object return type\n$user = $db->ObjectBuilder()->rawQueryOne('SELECT * from users where id=?', Array(10));\necho $user->login;\n```\nGet 1 column value as a string:\n```php\n$password = $db->rawQueryValue('SELECT password from users where id=? limit 1', Array(10));\necho \"Password is {$password}\";\nNOTE: for a rawQueryValue() to return string instead of an array 'limit 1' should be added to the end of the query.\n```\nGet 1 column value from multiple rows:\n```php\n$logins = $db->rawQueryValue('SELECT login from users limit 10');\nforeach ($logins as $login)\n    echo $login;\n```\n\nMore advanced examples:\n```php\n$params = Array(1, 'admin');\n$users = $db->rawQuery(\"SELECT id, firstName, lastName FROM users WHERE id = ? AND login = ?\", $params);\nprint_r($users); \u002F\u002F contains Array of returned rows\n\n\u002F\u002F will handle any SQL query\n$params = Array(10, 1, 10, 11, 2, 10);\n$q = \"(\n    SELECT a FROM t1\n        WHERE a = ? AND B = ?\n        ORDER BY a LIMIT ?\n) UNION (\n    SELECT a FROM t2 \n        WHERE a = ? AND B = ?\n        ORDER BY a LIMIT ?\n)\";\n$results = $db->rawQuery ($q, $params);\nprint_r ($results); \u002F\u002F contains Array of returned rows\n```\n\n### Where \u002F Having Methods\n`where()`, `orWhere()`, `having()` and `orHaving()` methods allows you to specify where and having conditions of the query. All conditions supported by where() are supported by having() as well.\n\nWARNING: In order to use column to column comparisons only raw where conditions should be used as column name or functions cannot be passed as a bind variable.\n\nRegular == operator with variables:\n```php\n$db->where ('id', 1);\n$db->where ('login', 'admin');\n$results = $db->get ('users');\n\u002F\u002F Gives: SELECT * FROM users WHERE id=1 AND login='admin';\n\n\u002F\u002F Or you can also use Chain Loaders for above query\n$results = $db->where ('id', 1)\n                ->where ('login', 'admin')\n                ->get('users');\n```\n\n```php\n$db->where ('id', 1);\n$db->having ('login', 'admin');\n$results = $db->get ('users');\n\u002F\u002F Gives: SELECT * FROM users WHERE id=1 HAVING login='admin';\n```\n\n\nRegular == operator with column to column comparison:\n```php\n\u002F\u002F WRONG\n$db->where ('lastLogin', 'createdAt');\n\u002F\u002F CORRECT\n$db->where ('lastLogin = createdAt');\n$results = $db->get ('users');\n\u002F\u002F Gives: SELECT * FROM users WHERE lastLogin = createdAt;\n```\n\n```php\n$db->where ('id', 50, \">=\");\n\u002F\u002F or $db->where ('id', Array ('>=' => 50));\n$results = $db->get ('users');\n\u002F\u002F Gives: SELECT * FROM users WHERE id >= 50;\n```\n\nBETWEEN \u002F NOT BETWEEN:\n```php\n$db->where('id', Array (4, 20), 'BETWEEN');\n\u002F\u002F or $db->where ('id', Array ('BETWEEN' => Array(4, 20)));\n\n$results = $db->get('users');\n\u002F\u002F Gives: SELECT * FROM users WHERE id BETWEEN 4 AND 20\n```\n\nIN \u002F NOT IN:\n```php\n$db->where('id', Array(1, 5, 27, -1, 'd'), 'IN');\n\u002F\u002F or $db->where('id', Array( 'IN' => Array(1, 5, 27, -1, 'd') ) );\n\n$results = $db->get('users');\n\u002F\u002F Gives: SELECT * FROM users WHERE id IN (1, 5, 27, -1, 'd');\n```\n\nOR CASE:\n```php\n$db->where ('firstName', 'John');\n$db->orWhere ('firstName', 'Peter');\n$results = $db->get ('users');\n\u002F\u002F Gives: SELECT * FROM users WHERE firstName='John' OR firstName='peter'\n```\n\nNULL comparison:\n```php\n$db->where (\"lastName\", NULL, 'IS NOT');\n$results = $db->get(\"users\");\n\u002F\u002F Gives: SELECT * FROM users where lastName IS NOT NULL\n```\n\nLIKE comparison:\n```php\n$db->where (\"fullName\", 'John%', 'like');\n$results = $db->get(\"users\");\n\u002F\u002F Gives: SELECT * FROM users where fullName like 'John%'\n```\n\nAlso you can use raw where conditions:\n```php\n$db->where (\"id != companyId\");\n$db->where (\"DATE(createdAt) = DATE(lastLogin)\");\n$results = $db->get(\"users\");\n```\n\nOr raw condition with variables:\n```php\n$db->where (\"(id = ? or id = ?)\", Array(6,2));\n$db->where (\"login\",\"mike\");\n$res = $db->get (\"users\");\n\u002F\u002F Gives: SELECT * FROM users WHERE (id = 6 or id = 2) and login='mike';\n```\n\n\nFind the total number of rows matched. Simple pagination example:\n```php\n$offset = 10;\n$count = 15;\n$users = $db->withTotalCount()->get('users', Array ($offset, $count));\necho \"Showing {$count} from {$db->totalCount}\";\n```\n\n### Query Keywords\nTo add LOW PRIORITY | DELAYED | HIGH PRIORITY | IGNORE and the rest of the mysql keywords to INSERT (), REPLACE (), GET (), UPDATE (), DELETE() method or FOR UPDATE | LOCK IN SHARE MODE into SELECT ():\n```php\n$db->setQueryOption ('LOW_PRIORITY')->insert ($table, $param);\n\u002F\u002F GIVES: INSERT LOW_PRIORITY INTO table ...\n```\n```php\n$db->setQueryOption ('FOR UPDATE')->get ('users');\n\u002F\u002F GIVES: SELECT * FROM USERS FOR UPDATE;\n```\n\nAlso you can use an array of keywords:\n```php\n$db->setQueryOption (Array('LOW_PRIORITY', 'IGNORE'))->insert ($table,$param);\n\u002F\u002F GIVES: INSERT LOW_PRIORITY IGNORE INTO table ...\n```\n\nSame way keywords could be used in SELECT queries as well:\n```php\n$db->setQueryOption ('SQL_NO_CACHE');\n$db->get(\"users\");\n\u002F\u002F GIVES: SELECT SQL_NO_CACHE * FROM USERS;\n```\n\nOptionally you can use method chaining to call where multiple times without referencing your object over and over:\n\n```php\n$results = $db\n\t->where('id', 1)\n\t->where('login', 'admin')\n\t->get('users');\n```\n\n### Delete Query\n```php\n$db->where('id', 1);\nif($db->delete('users')) echo 'successfully deleted';\n```\n\n\n### Ordering method\n```php\n$db->orderBy(\"id\",\"asc\");\n$db->orderBy(\"login\",\"Desc\");\n$db->orderBy(\"RAND ()\");\n$results = $db->get('users');\n\u002F\u002F Gives: SELECT * FROM users ORDER BY id ASC,login DESC, RAND ();\n```\n\nOrder by values example:\n```php\n$db->orderBy('userGroup', 'ASC', array('superuser', 'admin', 'users'));\n$db->get('users');\n\u002F\u002F Gives: SELECT * FROM users ORDER BY FIELD (userGroup, 'superuser', 'admin', 'users') ASC;\n```\n\nIf you are using setPrefix () functionality and need to use table names in orderBy() method make sure that table names are escaped with ``.\n\n```php\n$db->setPrefix (\"t_\");\n$db->orderBy (\"users.id\",\"asc\");\n$results = $db->get ('users');\n\u002F\u002F WRONG: That will give: SELECT * FROM t_users ORDER BY users.id ASC;\n\n$db->setPrefix (\"t_\");\n$db->orderBy (\"`users`.id\", \"asc\");\n$results = $db->get ('users');\n\u002F\u002F CORRECT: That will give: SELECT * FROM t_users ORDER BY t_users.id ASC;\n```\n\n### Grouping method\n```php\n$db->groupBy (\"name\");\n$results = $db->get ('users');\n\u002F\u002F Gives: SELECT * FROM users GROUP BY name;\n```\n\n### JOIN method\nJoin table products with table users with LEFT JOIN by tenantID\n```php\n$db->join(\"users u\", \"p.tenantID=u.tenantID\", \"LEFT\");\n$db->where(\"u.id\", 6);\n$products = $db->get (\"products p\", null, \"u.name, p.productName\");\nprint_r ($products);\n\u002F\u002F Gives: SELECT u.name, p.productName FROM products p LEFT JOIN users u ON p.tenantID=u.tenantID WHERE u.id = 6\n```\n\n### Join Conditions\nAdd AND condition to join statement\n```php\n$db->join(\"users u\", \"p.tenantID=u.tenantID\", \"LEFT\");\n$db->joinWhere(\"users u\", \"u.tenantID\", 5);\n$products = $db->get (\"products p\", null, \"u.name, p.productName\");\nprint_r ($products);\n\u002F\u002F Gives: SELECT  u.name, p.productName FROM products p LEFT JOIN users u ON (p.tenantID=u.tenantID AND u.tenantID = 5)\n```\nAdd OR condition to join statement\n```php\n$db->join(\"users u\", \"p.tenantID=u.tenantID\", \"LEFT\");\n$db->joinOrWhere(\"users u\", \"u.tenantID\", 5);\n$products = $db->get (\"products p\", null, \"u.name, p.productName\");\nprint_r ($products);\n\u002F\u002F Gives: SELECT  u.login, p.productName FROM products p LEFT JOIN users u ON (p.tenantID=u.tenantID OR u.tenantID = 5)\n```\n\n### Properties sharing\nIt is also possible to copy properties\n\n```php\n$db->where (\"agentId\", 10);\n$db->where (\"active\", true);\n\n$customers = $db->copy ();\n$res = $customers->get (\"customers\", Array (10, 10));\n\u002F\u002F SELECT * FROM customers WHERE agentId = 10 AND active = 1 LIMIT 10, 10\n\n$cnt = $db->getValue (\"customers\", \"count(id)\");\necho \"total records found: \" . $cnt;\n\u002F\u002F SELECT count(id) FROM customers WHERE agentId = 10 AND active = 1\n```\n\n### Subqueries\nSubquery init\n\nSubquery init without an alias to use in inserts\u002Fupdates\u002Fwhere Eg. (select * from users)\n```php\n$sq = $db->subQuery();\n$sq->get (\"users\");\n```\n \nA subquery with an alias specified to use in JOINs . Eg. (select * from users) sq\n```php\n$sq = $db->subQuery(\"sq\");\n$sq->get (\"users\");\n```\n\nSubquery in selects:\n```php\n$ids = $db->subQuery ();\n$ids->where (\"qty\", 2, \">\");\n$ids->get (\"products\", null, \"userId\");\n\n$db->where (\"id\", $ids, 'in');\n$res = $db->get (\"users\");\n\u002F\u002F Gives SELECT * FROM users WHERE id IN (SELECT userId FROM products WHERE qty > 2)\n```\n\nSubquery in inserts:\n```php\n$userIdQ = $db->subQuery ();\n$userIdQ->where (\"id\", 6);\n$userIdQ->getOne (\"users\", \"name\"),\n\n$data = Array (\n    \"productName\" => \"test product\",\n    \"userId\" => $userIdQ,\n    \"lastUpdated\" => $db->now()\n);\n$id = $db->insert (\"products\", $data);\n\u002F\u002F Gives INSERT INTO PRODUCTS (productName, userId, lastUpdated) values (\"test product\", (SELECT name FROM users WHERE id = 6), NOW());\n```\n\nSubquery in joins:\n```php\n$usersQ = $db->subQuery (\"u\");\n$usersQ->where (\"active\", 1);\n$usersQ->get (\"users\");\n\n$db->join($usersQ, \"p.userId=u.id\", \"LEFT\");\n$products = $db->get (\"products p\", null, \"u.login, p.productName\");\nprint_r ($products);\n\u002F\u002F SELECT u.login, p.productName FROM products p LEFT JOIN (SELECT * FROM t_users WHERE active = 1) u on p.userId=u.id;\n```\n\n### EXISTS \u002F NOT EXISTS condition\n```php\n$sub = $db->subQuery();\n$sub->where(\"company\", 'testCompany');\n$sub->get (\"users\", null, 'userId');\n$db->where (null, $sub, 'exists');\n$products = $db->get (\"products\");\n\u002F\u002F Gives SELECT * FROM products WHERE EXISTS (SELECT userId FROM users WHERE company='testCompany')\n```\n\n### Has method\nA convenient function that returns TRUE if exists at least an element that satisfy the where condition specified calling the \"where\" method before this one.\n```php\n$db->where(\"user\", $user);\n$db->where(\"password\", md5($password));\nif($db->has(\"users\")) {\n    return \"You are logged\";\n} else {\n    return \"Wrong user\u002Fpassword\";\n}\n``` \n### Helper methods\nDisconnect from the database:\n```php\n    $db->disconnect();\n```\n\nReconnect in case mysql connection died:\n```php\nif (!$db->ping())\n    $db->connect()\n```\n\nGet last executed SQL query:\nPlease note that this method returns the SQL query only for debugging purposes as its execution most likely will fail due to missing quotes around char variables.\n```php\n    $db->get('users');\n    echo \"Last executed query was \". $db->getLastQuery();\n```\n\nCheck if table exists:\n```php\n    if ($db->tableExists ('users'))\n        echo \"hooray\";\n```\n\nmysqli_real_escape_string() wrapper:\n```php\n    $escaped = $db->escape (\"' and 1=1\");\n```\n\n### Transaction helpers\nPlease keep in mind that transactions are working on innoDB tables.\nRollback transaction if insert fails:\n```php\n$db->startTransaction();\n...\nif (!$db->insert ('myTable', $insertData)) {\n    \u002F\u002FError while saving, cancel new record\n    $db->rollback();\n} else {\n    \u002F\u002FOK\n    $db->commit();\n}\n```\n\n\n### Error helpers\nAfter you executed a query you have options to check if there was an error. You can get the MySQL error string or the error code for the last executed query. \n```php\n$db->where('login', 'admin')->update('users', ['firstName' => 'Jack']);\n\nif ($db->getLastErrno() === 0)\n    echo 'Update succesfull';\nelse\n    echo 'Update failed. Error: '. $db->getLastError();\n```\n\n### Query execution time benchmarking\nTo track query execution time setTrace() function should be called.\n```php\n$db->setTrace (true);\n\u002F\u002F As a second parameter it is possible to define prefix of the path which should be striped from filename\n\u002F\u002F $db->setTrace (true, $_SERVER['SERVER_ROOT']);\n$db->get(\"users\");\n$db->get(\"test\");\nprint_r ($db->trace);\n```\n\n```\n    [0] => Array\n        (\n            [0] => SELECT  * FROM t_users ORDER BY `id` ASC\n            [1] => 0.0010669231414795\n            [2] => MysqliDb->get() >>  file \"\u002Favb\u002Fwork\u002FPHP-MySQLi-Database-Class\u002Ftests.php\" line #151\n        )\n\n    [1] => Array\n        (\n            [0] => SELECT  * FROM t_test\n            [1] => 0.00069189071655273\n            [2] => MysqliDb->get() >>  file \"\u002Favb\u002Fwork\u002FPHP-MySQLi-Database-Class\u002Ftests.php\" line #152\n        )\n\n```\n\n### Table Locking\nTo lock tables, you can use the **lock** method together with **setLockMethod**. \nThe following example will lock the table **users** for **write** access.\n```php\n$db->setLockMethod(\"WRITE\")->lock(\"users\");\n```\n\nCalling another **->lock()** will remove the first lock.\nYou can also use\n```php\n$db->unlock();\n```\nto unlock the previous locked tables.\nTo lock multiple tables, you can use an array.\nExample:\n```php\n$db->setLockMethod(\"READ\")->lock(array(\"users\", \"log\"));\n```\nThis will lock the tables **users** and **log** for **READ** access only.\nMake sure you use **unlock()* afterwards or your tables will remain locked!\n\n","该项目提供了一个PHP MySQLi类的封装，利用预处理语句来增强数据库操作的安全性和便捷性。其核心功能包括对象映射、插入、更新、查询、删除等基本SQL操作，并支持分页、事务处理、错误处理及表锁定等高级特性。技术特点上，它通过预处理语句防止SQL注入攻击，同时简化了数据库连接与操作过程。适合于需要快速开发且对安全有一定要求的小到中型Web应用项目中使用，尤其是那些基于LAMP（Linux+Apache+MySQL+PHP）架构的应用场景。",2,"2026-06-11 03:18:29","top_language"]