2017 © Pedro Peláez
 

library mysql

Simply mysqli wrapper

image

eb/mysql

Simply mysqli wrapper

  • Saturday, February 17, 2018
  • by EgorBanin
  • Repository
  • 1 Watchers
  • 1 Stars
  • 901 Installations
  • PHP
  • 0 Dependents
  • 0 Suggesters
  • 0 Forks
  • 0 Open issues
  • 5 Versions
  • 0 % Grown

The README.md

Простая библиотека для работы с MySQL

Обёртка mysqli, которая умеет делать простые и асинхронные запросы., (*1)

Установка

composer require eb/mysql, (*2)

Или скачайте архив и извлеките содержимое src/ в директроию с библиотеками. Используйте psr-0-совместимый автозагрузчик., (*3)

Подключение, база данных по умолчанию и кодировка

<?php

$db = Mysql\Client::init([
    'user' => 'username',
    'password' => 'password',
    'defaultDb' => 'Sakila',
    'charset' => 'utf8',
    'lazy' => true,
]);

Если опция 'lazy' установлена в true, то подключение к базе данных создаётся не сразу, а при первом запросе., (*4)

Запрос и получение данных

$result = $db->query('
    select * from `Book`
    where `author` = :author
', [':author' => 'Мартин Фаулер']);

while ($row = $result->row()) {
    echo $row['title'], "\n";
}
$result = $db->query('
    insert into `Book`
    set
        `ISBN` = :ISBN,
        `title` = :title,
        `author` = :author;
', [
    ':ISBN' => '978-5-7502-0064-1',
    ':title' => 'Совершенный код',
    ':author' => 'Стив Макконнелл'
]);

$id = $result->insertedId();
$affectedRows = $result->affectedRows();

Массивы в параметрах

$result = $db->query('
    select * from `Book`
    where `id` in (:ids)
', [':ids' => [1, 4, 10]]);
$values = [
    ['978-5-7502-0064-1', 'Совершенный код', 'Стив Макконнелл'],
    ['978-5-93286-153-0', 'MySQL. Оптимизация производительности', 'Бэрон Шварц, Петр Зайцев, Вадим Ткаченко, Джереми Д. Зооднай, Дерек Дж. Баллинг, Арьен Ленц']
];
$result = $db->query('
    insert into `Book` (`ISBN`, `title`, `author`)
    values :values
', [':values' => $values]);

Транзакции

$db->transaction(function($connection, $commit, $rollback) {
    $from = 1;
    $to = 2;
    $sum = 100;

    $account = $connection->query('
        select *
        from `accounts`
        where `id` = :id
        for update
    ', [':id' => $from])->row();
    if ($account['amount'] < $sum) {
        return $rollback(); // или можно просто бросить исключение
    }

    $connection->query('
        update `accounts`
        set `amount` = `amount` - :sum
        where `id` = :from
    ', [':sum' => $sum, ':from' => $from]);
    $connection->query('
        update `accounts`
        set `amount` = `amount` + :sum
        where `id` = :to
    ', [':sum' => $sum, ':to' => $to]);

    return $commit(); // можно и не вызывать коммит, он будет вызван автоматически
});

Обработка ошибок

В случае возникновения ошибки при подключении или при выполнении запроса будет брошено исключение Mysql\Exception., (*5)

Вспомогательный класс Table

Для сокращения объёма похожего кода запросов можно воспользоваться вспомогательным классом Table., (*6)

$table = $db->table('books');
$book = $table->get(1);
$books = $table->select(['author' => 'Мартин Фаулер']);
$favoriteBook = $table->selectOne(['title' => 'Совершенный код']);
$table->set($favoriteBook['id'], ['ISBN' => '978-5-469-00822-4']);
$table->update(['title' => 'Совершенный код'], ['ISBN' => '978-5-469-00822-4']);
$id = $table->insert([
    'ISBN' => '978-5-459-01720-5',
    'title' => 'Приемы объектно-ориентированного проектирования',
    'author' => 'Эрих Гамма, Ричард Хелм, Ральф Джонсон, Джон Влиссидес'
]);
$table->rm($id);
$table->delete(['ISBN' => '978-5-459-01720-5']);

Методы

get($id)

Выбирает строку по первичному ключу, (*7)

set($id, array $fields)

Обновляет указанные ячейки строки по первичному ключу., (*8)

rm($id)

Удаляет строку по первичному ключу., (*9)

insert(array $row)

Вставляет строку. Возвращает id добавленой записи., (*10)

select([array $query = [][, array $fields = ['*'][, mixed $sort = null[, mixed $limit = null]]]])

Выбирает строки соответствующие запросу., (*11)

selectOne([array $query = [][, array $fields = ['*']]])

Выбирает только одну строку соответствующую запросу., (*12)

update(array $query, array $fields)

Обновляет строки соответствующие запросу., (*13)

delete(array $query)

Удаляет строки соответствующие запросу., (*14)

Операторы поддерживаемые в запросах select, update и delete

$and

['gender' => 'f', 'age' => ['$between' => [18, 25]]] или ['$and' => ['gender' => 'f', 'age' => ['$between' => [18, 25]]]] => …where `gender` = 'f' and `age` between 18 and 25, (*15)

$or

['$or' => ['sheIs' => 'pretty', 'iAm' => 'drunk']] => … where `sheIs` = 'pretty' or `iAm` = 'drunk', (*16)

$eq

['id' => 100] или ['id' => ['$eq' => 100]] => …where `id` = 100, (*17)

$ne

['id' => ['$ne' => 100]] => …where `id` != 100, (*18)

$lt

['id' => ['$lt' => 100]] => …where `id` < 100, (*19)

$lte

['id' => ['$lte' => 100]] => …where `id` <= 100, (*20)

$gt

['id' => ['$gt' => 100]] => …where `id` > 100, (*21)

$gte

['id' => ['$gte' => 100]] => …where `id` >= 100, (*22)

$between

['id' => ['$between' => [100, 200]] => …where `id` between 100 and 200, (*23)

$in

['id' => ['$in' => [1, 2, 3]]] => …where `id` in (1, 2, 3), (*24)

$nin

['id' => ['$nin' => [1, 2, 3]]] => …where `id` not in (1, 2, 3), (*25)

$like

['blood' => ['$like' => '%ice%']] => ...where `blood` like '%ice%', (*26)

Нетривиальные запросы

Несмотря на богатство возможностей Table, в случае нетривиальных запросов следует предпочесть Mysql\Client::query. Сравните:, (*27)

$table = new Mysql\Table($db, 'posts');
$archive = $table->select([
    'active' => true,
    '$or' => [
        'archive' => true,
        'ctime' => ['$lt' => time() - (60 * 60 * 24 * 365)],
    ],
    'id' => ['$nin' => [1, 4, 10]]
], ['id', 'title', 'ctime'], ['ctime' => -1], ['limit' => 10, 'offset' => 20]);

$archive = $db->query('
    select
        `id`,
        `title`,
        from_unixtime(`ctime`) as `cdate`
    from `posts`
    where
        `active` = true
        and (
            `archive` = true
            or `ctime` < :timeLimit
        )
        and `id` not in :exclusions
    order by `ctime` desc
    limit :limit offset :offset
', [
    ':timeLimit' => time() - (60 * 60 * 24 * 365),
    ':exclusions' => [1, 4, 10],
    ':limit' => 10,
    ':offset' => 20,
]);

Хотя первый вариант более компактный, он не такой очевидный как SQL-запрос., (*28)

Асинхронные запросы

$db = Mysqli\Client::pool([
    [
        'user' => 'username',
        'password' => 'password',
        'defaultDB' => 'Sakila',
        'charset' => 'utf8',
        'lazy' => true,
    ],
    [
        'user' => 'username',
        'password' => 'password',
        'defaultDB' => 'Sakila',
        'charset' => 'utf8',
        'lazy' => true,
    ]
]);

Количество подключений в пуле определяет сколько запросов может быть выполнено параллельно. Но даже одно подключение может обеспечить выигрыш во времени выполнения, если перед использованием результатов медленного асинхронного запроса выполняется какой-то медленный код., (*29)

$result = $db->asyncQuery('select sleep(1)');
sleep(1);
var_dump($result->rows()); // завершится быстрее чем за 2 секунды

Тэги подключений

Кроме асинхронных запросов пул позволяет разделить подключения для разных задач на уровне приложения., (*30)

$db = Mysqli\Client::pool([
    [
        'host' => 'master',
        'tags' => ['write'],
        'user' => 'username',
        'password' => 'password',
        'defaultDB' => 'Sakila',
        'charset' => 'utf8',
        'lazy' => true,
    ],
    [
        'host' => 'slave',
        'tags' => ['read'],
        'user' => 'username',
        'password' => 'password',
        'defaultDB' => 'Sakila',
        'charset' => 'utf8',
        'lazy' => true,
    ]
]);
$db->query('insert into `foo` ...', [], ['write']); // уйдёт на master
$db->query('select * from `foo` ...', [], ['read']); // уйдёт на slave

Советы по написанию SQL-запросов

  • Не стесняйтесь переносить строку запроса и использовать отступы для улучшения читаемости;
  • Не пишите запросы капсом, в этом нет смысла;
  • Заключайте в апострофы имена таблиц, столбцов и алиасов;
  • Используйте осмысленные имена алиасов;
  • По возможности используйте одинаковый стиль написания имён переменных php и столбцов в базе.
$hotPosts = $db->query('SELECT t1.*, t2.name as autor_name FROM posts as t1 INNER JOIN authors as t2 ON t1.author_id = t2.id WHERE t1.active = 1 AND t1.views > 10000 ORDER BY t1.views DESC LIMIT 10')->rows();

$hotPosts = $db->query('
    select
        `posts`.*,
        `authors`.`name` as `authorName`
    from `posts`
    inner join `authors` on `authors`.`id` = `posts`.`authorId`
    where
        `posts`.`active` = true
        and `posts`.`views` > 10000
    order by `posts`.`views` desc
    limit 10
')->rows();

Похожие библиотеки

Стандартные mysqli и PDO интерфейсы несколько неуклюжи, поэтому обёртки, подобные этой, пишет каждый второй разработчик. Возможно вас заинтересует что-нибудь из следующего:, (*31)

  • MysqliDb -- обёртка mysqli, GPLv3
  • MeekroDB -- обёртка mysqli, LGPLv3
  • DByte -- компактная реализация обёртки PDO, MIT
  • DbSimple -- довольно известная в рунете библиотека, умеет работать с разными расширениями, LGPL

Тесты

Интеграционные тесты включают general_log и исследуют лог-файл после каждого запроса., (*32)

docker-compose -f tests/docker/docker-compose.yaml up -V --abort-on-container-exit

The Versions

17/02 2018

dev-master

9999999-dev https://github.com/EgorBanin/phpmysql

Simply mysqli wrapper

  Sources   Download

Unlicense

The Requires

  • php >=5.3.0
  • ext-mysqli *

 

The Development Requires

database mysql mysqli db

25/11 2017

1.1.2

1.1.2.0 https://github.com/EgorBanin/phpmysql

Simply mysqli wrapper

  Sources   Download

Unlicense

The Requires

  • php >=5.3.0
  • ext-mysqli *

 

The Development Requires

database mysql mysqli db

23/11 2017

1.1.1

1.1.1.0 https://github.com/EgorBanin/phpmysql

Simply mysqli wrapper

  Sources   Download

Unlicense

The Requires

  • php >=5.3.0
  • ext-mysqli *

 

The Development Requires

database mysql mysqli db

23/11 2017

1.1.0

1.1.0.0 https://github.com/EgorBanin/phpmysql

Simply mysqli wrapper

  Sources   Download

Unlicense

The Requires

  • php >=5.3.0
  • ext-mysqli *

 

The Development Requires

database mysql mysqli db

12/03 2016

1.0.0

1.0.0.0 https://github.com/EgorBanin/phpmysql

Simply mysqli wrapper

  Sources   Download

Unlicense

The Requires

  • php >=5.3.0

 

database mysql mysqli db