Класс обертки Mysqli by Koenig (Допилить)

18.39K
.

Не хочется смешивать в объектный интерфейс лямбды.

.
L!MP

Delphinum, понятно.
Ну х.з, может одному мне кажется не очевидным тот код что ты привёл.

.
(\/)____o_O____(\/)

L!MP, у тебя понятно, даже догадываюсь реализацию

.

Вчера темка эта снова попалась на глаза и я решил таки написать построитель SQL запросов (одним классом, т.е сам построитель и компилятор объеденены (без драйверов для SQL диалектоов, квотирование идентификаторов заточено под MySQL, но можно легко изменить в методе quote())).

М.б товарищу Koenig`у пригодиццо, когда он решит "Допилить" свой класс.

Вот ссылка на пастебин с кодом для просмотра онлайн: http://pastebin.com/jmCdi2pZ
Для детального ковыряния, креплю архив с классом.

А вот примеры работы (под каждым запросом, построенным при помощи билдера, идет комментарий с SQL который будит сгенерирован).

/* изменение данных */

echo (new Query('users'))->insert(['col' => 'value']);
//=> INSERT INTO `users` (`col`) VALUES (?)
echo (new Query('users'))->where('col', '=', 50)->update(['col' => 'value']);
//=> UPDATE `users` SET `col` = ? WHERE `col` = ?
echo (new Query('users'))->where('col', '=', 50)->delete();
//=> DELETE FROM `users` WHERE `col` = ?

/* инкремент/декремент */

echo (new Query('users'))->where('col', '=', 50)->increment('col');
//=> UPDATE `users` SET `col` = col + 1 WHERE `col` = ?
echo (new Query('users'))->where('col', '=', 50)->decrement('col');
//=> UPDATE `users` SET `col` = col - 1 WHERE `col` = ?

/* получение агрегатного состояния */

echo (new Query('users'))->count();
//=> SELECT COUNT(*) AS `aggregation` FROM `users`
echo (new Query('users'))->count('col');
//=> SELECT COUNT(`col`) AS `aggregation` FROM `users`
echo (new Query('users'))->min('col');
//=> SELECT MIN(`col`) AS `aggregation` FROM `users`
echo (new Query('users'))->max('col');
//=> SELECT MAX(`col`) AS `aggregation` FROM `users`
echo (new Query('users'))->sum('col');
//=> SELECT SUM(`col`) AS `aggregation` FROM `users`
echo (new Query('users'))->avg('col');
//=> SELECT AVG(`col`) AS `aggregation` FROM `users`

/* выборка всех данных */

echo (new Query('users'))->select();
//=> SELECT * FROM `users`
echo (new Query('users'))->select(['col', ['col', 'b']]);
//=> SELECT `col`, `col` AS `b` FROM `users`

/* с сортировкой */
echo (new Query('users'))->order('col')->select();
//=> SELECT * FROM `users` ORDER BY `col` ASC

/* с лимитом */
echo (new Query('users'))->limit(10)->select();
//=> SELECT * FROM `users` LIMIT 10

/* с условием */
echo (new Query('users'))->where('col', '=', 30)->where('col', '=', 50)->select();
//=> SELECT * FROM `users` WHERE `col` = ? AND `col` = ?

/* с группой условий */
echo (new Query('users'))
    ->where('col', '=', 20)
    ->where(function($query) {
        $query->where('col', '=', 30)
            ->orWhere('col', '=', 50);
    })->select();
//=> SELECT * FROM `users` WHERE `col` = ? AND (`col` = ? OR `col` = ?)

/* с простым объединением */

echo (new Query('users'))->join('table', 'table.user_id', '=', 'users.id')->select();
//=> SELECT * FROM `users` INNER JOIN `table` ON (`table`.`user_id` = `users`.`id`) 
/* со сложным обьединением */
echo (new Query('users'))
    ->join('table', function($query) {
        $query->on('table.user_id', '=', 'users.id')
            ->orOn('table.user_id', '=', 'users.id');
    })
    ->select();
//=> SELECT * FROM `users` INNER JOIN `table` ON (`table`.`user_id` = `users`.`id` OR `table`.`user_id` = `users`.`id`)
Прикрепленные файлы:
.

Кому интересно, задачка.
Реализовать в классе построителя следующие методы:

whereIsNull
whereIsNotNull
whereIn
whereNotIn
whereBetween
whereNotBetween

и их алиасы для с логикой OR.
Всё что для этого нужно, там уже реализовано

.
(\/)____o_O____(\/)

L!MP, сп, гляну, пока детально смотрел, не понял 20, 30, 50

.
L!MP

Koenig, ты про такое:

->where('col', '=', 30)


ну как же: где поле "col" равно 30
Третий аргумент - это значение.
--
Все значения проброшеные в билдер собираются в свойстве $bindings в порядке их добавления.
.
(\/)____o_O____(\/)

L!MP, уже догнал, не выспался Гг
второй класс проверяет что это строка?

.
L!MP

Koenig, второй класс - это выражение, т.е когда компилятор видит его, то он не применяет для этого идентификатора/значения никаких преобразований.

Пример:

echo (new Query('users'))->insert(['time' => 'NOW()']);
//=> INSERT INTO `users` (`time`) VALUES (?)
echo (new Query('users'))->insert(['time' => new Expression('NOW()')]);
//=> INSERT INTO `users` (`time`) VALUES (NOW())
.
ramzes
набросок (+/-)

/**
 * Class SqlBuilder
 * @package microapp
 */
class SqlBuilder {

    /**
     * @var array
     */
    private $query = array();
    private $compilate = '';

    public function __construct(){
        return $this;
    }

    public function select($query){
        $this->query['select'] = is_array($query) ? implode(', ', array_map(array(get_class($this), 'article'), $query)) : $this->article($query);
        return $this;
    }

    public function insert($query){
        $this->query['insert'] = false;
        return $this;
    }

    public function update(){
        $this->query['update'] = false;
        return $this;
    }

    public function delete(){
        $this->query['delete'] = false;
        return $this;
    }

    public function from($table){
        $this->query['from'] = $this->article($table);
        return $this;
    }

    public function left($table){
        $this->query['left'] = $this->article($table);
        return $this;
    }

    public function right($table){
        $this->query['right'] = $this->article($table);
        return $this;
    }

    public function on($query){
        $this->query['on'] = $query;
        return $this;
    }

    public function where($where){
        if(preg_match('#([^=<>\!]+)#', $where, $row)){
            $this->query['where'] = str_replace($row[1], $this->article($row[1]), $where);
        }else{
            $this->query['where'] = $where;
        }
        return $this;
    }

    public function order($field, $type = 'ASC'){
        $this->query['order'] = $this->article($field);
        $this->query['sort'] = strtoupper($type)=='ASC' ? 'ASC' : 'DESC';
        return $this;
    }

    public function limit($start, $len = false){
        $this->query['limit'] = $start;
        if($len!=false){
            $this->query['limit_len'] = $len;
        }
        return $this;
    }

    public function set(array $value){
        $this->query['set'] = $value;
        return $this;
    }



    public function run(){
        foreach ($this->query as $q => $v) {
            switch ($q) {
                case 'limit':
                    $this->compilate.= 'LIMIT';
                    break;
                case 'limit_len':
                    $this->compilate.= ' ,';
                    break;
                case 'order':
                    $this->compilate.= 'ORDER BY';
                    break;
                case 'sort':
                    $this->compilate.= '';
                    break;
                case 'right':
                    $this->compilate.= 'RIGHT JOIN';
                    break;
                case 'left':
                    $this->compilate.= 'LEFT JOIN';
                    break;
                case 'insert':
                    $this->compilate.= 'INSERT INTO';
                    break;
                default:
                    $this->compilate.= strtoupper($q);
                    break;
            }

            if (is_array($v)) {
                $this->compilate.= ' ' . implode(', ', $v);
            }else if($q=='on'){
                $split = explode('=', $v);
                $this->compilate.=' '.$this->query['from'].'.'.$this->article($split[0]).' = '.(isset($this->query['left']) ? $this->query['left'] : $this->query['right']).'.'.$this->article($split[1]).' ';
            }else{
                $this->compilate.= ($v != false) ? ' ' . $v . ' ' : '';
            }
        }
    }

    public function exec(){
        $this->run();
        return microapp::sql()->query($this->compilate);
    }

    public function view(){
        $this->run();
        return $this->compilate;
    }

    private function article($row){
        return preg_replace('|([a-z\d_\-]+)|is', '`\1`', str_replace('`', '', trim($row) ) );
    }

}


типа того:
$q = microapp::sql()->select(
        array(
            'forum_thread.*',
            'users.login',
            'users.ontime',
            'users.name'
        )
    )
        ->from('forum_thread')
        ->left('users')
        ->on('last_post_author = id')
        ->where('forum_thread.parent_id = 4')
        ->order('forum_thread.thread_fixed', 'DESC')
        ->order('forum_thread.last_time', 'DESC')
        ->limit(20)
        ->exec();
/* SELECT `forum_thread`.*, `users`.`login`, `users`.`ontime`, `users`.`name`
FROM `forum_thread` LEFT JOIN `users`
ON `forum_thread`.`last_post_author` = `users`.`id`
WHERE `forum_thread`.`parent_id`= 4 ORDER BY `forum_thread`.`last_time`  DESC
LIMIT 20  */
Всего: 362