Topnew DB is a PHP class to use PDO database library easily.
Save Topnew\Db file into somewhere eg:
vendor/topnew/src/Db.php
An example of your applications:
namespace App; use Topnew\Db; class TestApp { public function __construct() { $this->db = Db::make($this->config['db']); ... } public function getUser($uid) { return $this->db->from('users')->where('uid', $uid)->row(); } }
Your database configure should contain something like following:
$config['db'] = [ 'host' => 'localhost', 'user' => 'db-user', 'pass' => 'db-pwd', 'db' => 'my_db', 'eng' => 'mysql', // pgsql, sqlite, mssql, cubrid, etc ... ];
Topnew\Db works for most of the major databases, eg MySQL, PostgreSQL, SQLite, MS-SQL etc via PHP PDO class
As you see the config in above example, the following is a full list of config supported:
$config['db'] = [ 'host' => 'localhost', 'user' => 'db-user', 'pass' => 'db-pwd', 'db' => 'my_db', 'eng' => 'mysql', // pgsql, sqlite, mssql, cubrid, etc 'char' => 'utf8', 'port' => 3306, 'enc' => 0, // if 1 need Topnew\Auth::dec() 'log' => '', // log table for SQL err or slow SQL eg log_err 'slow' => 1000, // SQL slower than this will be logged ];
You can also encryt password in the config file as following:
$config['db'] = [ .... 'pass' => 'aC4r@xd._e.......', 'enc' => 1 ];
Then you need Topnew\Auth plugin to be able to decrypt the password
This method to get all rows from a select SQL. eg select * from users
You can use it in several ways though:
3.1.1 - direct input SQL eg
$rows = $db->all('select * from users');
3.1.2 - direct input SQL with variable to bind
$sql = 'select * from users where name = :name';
$rows = $db->all($sql, ['name' => 'Topnew']);
3.1.3 - use Topnew\Db trained methods
$rows = $db->select(...)->from(...)->where(...)->all();
3.1.4 - this method has an alias = $db->rows()
This method to get all rows in a nested array. Similiar usage as all() by either direct $sql or via trained Db methods
$sales = $this->db->select('yr, mon, sum(amt) amt')->from('sales')->group(1,2)->arr2(); And sample result will be something like following: $sales[2019][10] = 123; $sales[2019][12] = 234; $sales[2020][01] = 345; ...
arr($sql, $param, $level, $all_record)
It supports unlimitted levels of nested array, however it is always less 1 than the total number of cols in each row. eg above example $db->arr10() will be auto changed to ->arr2() as it has only 3 cols in each row.
Same as above example, if you call $db->arr() or $db->arr1() The result will be as following: $sales = [ 2019 => ['mon' => 12, 'amt' => 234], 2020 => ['mon' => 01, 'amt' => 345], ];
It is in one level of array, and it keeps last value if same key found.
If you want to keep all records if same key occurs, use ->arrXall() instead. eg
Same as above example, if you call $db->arrAll() The result will be as following: $sales = [ 2019 => [ ['mon' => 10, 'amt' => 123], ['mon' => 12, 'amt' => 234], ], 2020 => [ ['mon' => 01, 'amt' => 345], ], ];
Aliases or dynamic calls
arr1() == arr(); // default to 1 level of array arr4() == arr($sql, $param, 4); arr4All() == arr($sql, $param, 4, true); arrAll() == arr($sql, $param, 1, true);
Same results:
arr() == enum(); // when there is only 1 col in each row arr() == list() == lists(); // when there are exactly 2 cols in each row
$db->from('users')->count() == SELECT count(*) FROM users;
$db->count('distinct col') == SELECT count(distinct col) ...
$db->select('distinct gender')->from('users')->enum(); Result will be something like: ['Male', 'Female']
And it is exactly same as $db->arr() if there is only one col in SELECT. When there are multiple cols in SELECT, then enum() will only return the first col
No matter how many cols in each row, it will return a col1 => col2 key pair of each row, if there are only 2 cols in each row, it is same as arr()
$db->select('uid, name')->from('users')->list()
list() is alias of lists(), and safe method name for PHP 7.0+
Get one row from SELECT
$user = $db->from('users')->where(...)->row();
By default, it will return only one assoc row, eg above result will be something like:
$user = [ 'uid' => 1, 'name' => 'Topnew', 'gender' => 'Male', ... ];
Same as all(), you can always insert a raw SQL to get a result:
$user = $db->row('SELECT * FROM users WHERE email=:email', ['email'=>'...']);
You can param it to return in other data format:
row() == row('ASSOC') // return assoc row by default row('NUM') // return numeric row eg $user = [1, 'Topnew', 'Male', ...] row('BOTH')// return both assoc and numeric rows $row = $db->row($sql, $binds, 'NUM'); $row = $db->...->row('BOTH');
The following will return multiple rows:
row('ALL ASSOC') == rows() == all() == all('ASSOC') row('ALL NUM') == rows('NUM') == all('NUM') row('ALL BOTH') == rows('BOTH') == all('BOTH')
You can also choose which one as a key, and the following is returning multiple rows:
$users = $this->db->select('name,uid')->from('users')->row('uid'); It will return something like: $users = [ 1 => ['name' => 'Topnew', 'uid' => 1], 2 => ['name' => 'Geo', 'uid' => 2], ];
row($key) == rows($key) == all($key):
$users = $this->db->select('uid,name')->from('users')->rows('uid');
The difference between row($key) and arr() is that:
arr() is nested by first col, $key in row() can be any col
arr() the first col is removed from array, row() key-col also kept in the result
Get the value of first col of first row
$name = $db->select('name')->from('users')->where('uid', 1)->val(); // Topnew OR $name = $db->val('SELECT name FROM users WHERE uid=1')
You might need debug SQL on development, by turning it on before any of other methods:
$this->db->debug(); // turn on all debug $users = $this->db->from('users')->all(); // then all SQL will be shown on screen even there is no error $this->db->debug(-1); // turn off the debug after you turn it on $this->db->debug('err'); // only shown any error SQL
$db->err() == return last PDO error code
$db->err(1) == return last PDO error message
$new_user = ['name' => 'Tom', 'gender' => 'Male', ...]; $uid = $db->insert('users', $new_user); OR $uid = $db->data($new_user)->insert('users');
For PostgreSQL you need indicate which serial to return
$uid = $db->insert('users', $new_user, 'uid');
Also $db->replace($table, $data)
$db->where('uid', 12)->delete('users'); // DELETE FROM users WHERE uid = 12 OR via raw SQL $db->delete('users', 'WHERE uid=:uid', ['uid' => 123]) OR $db->where(...)->data($data)->delete($table)
You need be careful of ->where() here incase all rows be deleted!
$db->where('uid', 12)->update('users', ['name' => 'New name']); // UPDATE users SET name='New name' WHERE uid = 12 OR via raw SQL $db->update($table, $data, $where, $bind) OR $db->where(...)->data($data)->update($table)
You can also try lazy raw SQL
$db->where(...)->update('users', 'hit=hit+1'); Same as $db->where(...)->update('users', ['hit=hit+1', 'updated'=>'now()']);
This is a lazy call of insert() or update() based on $where
$db->where(...)->save($table, $data); OR via raw SQL $db->save($table, $data, $where, $bind)
If $where is found, update, otherwise insert
If you can not find any method matches your need, or you are trying to run a complicated report, you can always run any SQL by this method
$res = $db->run($sql, $bind);
Let's try an example
$rows = $this->db ->select('u.uid, c.name AS category, sum(s.amt) AS ttl') ->from('users AS u') ->join(['c' => 'cats'], 'u.cat_id = c.cat_id') ->leftJoin(['s' => 'sales'], 'u.uid = s.uid') ->where('u.uid', '>', 123) ->where('u.gender', 'Male') ->where('c.cat_root', [123, 456]) ->where('OR', [ ['u.name', 'To"*m'], ['u.manager', 'like', 'Sally'], 's.flag = 1', ]) ->group(1,2) ->having('ttl', 'between', 1000, 3000) ->order('2,3 DESC') ->limit(20) ->all();
Any methods can be in any order, except the last method has to be the get data method eg rows() etc
SELECT u.uid, c.name AS category, sum(s.amt) AS amt FROM users AS u JOIN cats AS c ON u.cat_id = c.cat_id LEFT JOIN sales AS s ON u.uid = s.uid WHERE u.uid > 123 AND u.gender = 'Male' AND c.cat_root IN (123, 456) AND ( u.name = :1 OR u.manager like '%Sally%' OR s.flag = 1 ) GROUP BY 1,2 HAVING ttl BETWEEN 1000 AND 3000 ORDER BY 2,3 DESC LIMIT 20
Please note that:
join / leftJoin / rightJoin / where / having -- accept multple calls;
any other method will use the last call, eg if you have:
$db->select('abc')->...->select('*')
The final SELECT will be *
Any of the chained method can be raw SQL, or params explained as following:
select('any raw SQL text here') ->select(['alias' => 'col_name']) // SELECT col_name AS alias // If no ->select() default to SELECT * ->select['distinct', 'col1', 'alias' => 'col2']) // SELECT DISTINCT col1, col2 AS alias
->from('table_name') ->from('users AS u') ->from(['u' => 'users']) // alias => table_name
->table() is alias of ->from()
->join('users AS u ON u.id = g.user_id') ->join(['u' => 'users'], 'u.id = g.user_id')
->leftJoin($tab, $on) == ->join($tab, $on, 'Left')
->leftJoin('users AS u ON u.id = g.user_id') ->join(['u' => 'users'], 'u.id = g.user_id', 'Left') ->leftJoin('users AS u', 'u.id = g.user_id')
->rightJoin($tab, $on) == ->join($tab, $on, 'Right')
->rightJoin('users AS u ON u.id = g.user_id') ->join(['u' => 'users'], 'u.id = g.user_id', 'Right') ->rightJoin('users AS u', 'u.id = g.user_id')
->group(1,2,3) // GROUP BY 1,2,3 ->group('col1, col2', 'col3') // GROUP BY col1, col2, col3
Please see ->where() for exactly same usage
->order('raw SQL') // ORDER BY raw SQL ->order(['col1', 'col2' => 'desc']) // ORDER BY col1, col2 DESC
->limit(10) // LIMIT 10 ->limit([10, 20]) // LIMIT 10 OFFSET 20 ->limit([10, 'page' => 5]) // LIMIT 10 OFFSET 40 // (5 - 1) * 10 = 40 ->limit(10)->page(5) // same as above
Sometimes you need manually bind key for raw SQL
->where('user_id in (select id from users where name = :name)') ->bindKey('name', 'Topnew')
->bindKey('name', $name) == ->bindKey(':name', $name)
Sometimes you need bind multiple keys, this method loop the array to call bindKey
->where('user_id in (select id from users where name = :name and email = :email)') ->bind(['name' => 'Topnew', 'email' => 'm@a.com'])
This is a get method, to return the raw SQL of the chained method. And the SQL will be reset after this call
$sql = $db->from('users')->where('id', 1)->sql(); // SELECT * FROM users WHERE id = 1
However and binded data not reset after this method call. In case this SQL is re-used for a more complicated sub-SQL while its binded data is to be used togather with its parent SQL
This is a quick call to get the result of a page, with total count of data, used for pagination.
$data = $db->from('users')->limit(10)->pgno(2, $ttl, $max)
If total rows in user table = 120, $ttl will return 120, and $max = 120 / pgsize (10) = 12
And $data will be the sub-set of data of LIMIT 10 OFFSET 10
Without ->limit(10), ->pgno() will default pgsize = 15, as it will make no sense to call this method without a pgsize
By default it will return ASSOC arrays of data, if you need other format of data, you might need call the following instead eg:
$data = $db->select('id', 'name')->from('users')->ttl()->arr(); $ttl = $db->ttl;
->ttl() to let the system to keep $ttl after get method eg arr(), and you can get it back via $db->ttl
Let's talk about the ->where in another wiki, as this wiki is getting too long now.
Topnew CMS Apps
» Topnew CMS Core
» Blog, Support, Ticket
» Page Maker CMS
Independent Apps
» BenSon Bank
» PHP SVG Chart
» SIDU DB Admin GUI
Topnew CMS
» Secure PHP Login
» Wiki & Support
© 2018 TOPNEW CMS