Нередко сочетаются изменения структуры базы данных с изменениями данных. Например, вы можете захотеть перенести данные в нескольких столбцах от пользователей во вновь созданную таблицу. Для этого типа сценариев, Phinx обеспечивает доступ к объекту построителя запросов, которые вы можете использовать для выполнения сложного SELECT, UPDATE, INSERTили DELETEзаявления.

Доступ к построителю запросов осуществляется путем вызова getQueryBuilder()функции:

<?php

use Phinx\Migration\AbstractMigration;

class MyNewMigration extends AbstractMigration
{
    /**
     * Migrate Up.
     */
    public function up()
    {
        $builder = $this->getQueryBuilder();
        $statement = $builder->select('*')->from('users')->execute();
        var_dump($statement->fetchAll());
    }
}

Выбор полей

Добавление полей в предложение SELECT:

<?php
$builder->select(['id', 'title', 'body']);

// Results in SELECT id AS pk, title AS aliased_title, body ...
$builder->select(['pk' => 'id', 'aliased_title' => 'title', 'body']);

// Use a closure
$builder->select(function ($builder) {
    return ['id', 'title', 'body'];
});

Where условия

Условия генерации:

// WHERE id = 1
$builder->where(['id' => 1]);

// WHERE id > 1
$builder->where(['id >' => 1]);

Как видите, вы можете использовать любой оператор, поставив его с пробелом после имени поля. Также легко добавить несколько условий:

<?php
$builder->where(['id >' => 1])->andWhere(['title' => 'My Title']);

// Equivalent to
$builder->where(['id >' => 1, 'title' => 'My title']);

// WHERE id > 1 OR title = 'My title'
$builder->where(['OR' => ['id >' => 1, 'title' => 'My title']]);

Для еще более сложных условий вы можете использовать замыкания и объекты выражений:

<?php
// Coditions are tied together with AND by default
$builder
    ->select('*')
    ->from('articles')
    ->where(function ($exp) {
        return $exp
            ->eq('author_id', 2)
            ->eq('published', true)
            ->notEq('spam', true)
            ->gt('view_count', 10);
    });

Что приводит к:

SELECT * FROM articles
WHERE
    author_id = 2
    AND published = 1
    AND spam != 1
    AND view_count > 10

Также возможно комбинирование выражений:

<?php
$builder
    ->select('*')
    ->from('articles')
    ->where(function ($exp) {
        $orConditions = $exp->or_(['author_id' => 2])
            ->eq('author_id', 5);
        return $exp
            ->not($orConditions)
            ->lte('view_count', 10);
    });

Он генерирует:

SELECT *
FROM articles
WHERE
    NOT (author_id = 2 OR author_id = 5)
    AND view_count <= 10

При использовании объектов выражения вы можете использовать следующие методы для создания условий:

  • eq() Создает условие равенства.
  • notEq() Создайте условие неравенства
  • like()Создайте условие с помощью LIKEоператора.
  • notLike()Создайте отрицательное LIKEусловие.
  • in()Создайте условие, используя IN.
  • notIn()Создайте отрицательное условие, используя IN.
  • gt()Создайте >условие.
  • gte()Создайте >=условие.
  • lt()Создайте <условие.
  • lte()Создайте <=условие.
  • isNull()Создайте условие.IS NULL
  • isNotNull()Создайте отрицательное условие.IS NULL

Агрегаты и функции SQL

<?php
// Results in SELECT COUNT(*) count FROM ...
$builder->select(['count' => $builder->func()->count('*')]);

С помощью метода func () можно создать ряд часто используемых функций:

  • sum()Подсчитайте сумму. Аргументы будут рассматриваться как буквальные значения.
  • avg()Рассчитайте среднее значение. Аргументы будут рассматриваться как буквальные значения.
  • min()Вычислите минимум столбца. Аргументы будут рассматриваться как буквальные значения.
  • max()Рассчитайте максимум столбца. Аргументы будут рассматриваться как буквальные значения.
  • count()Посчитайте количество. Аргументы будут рассматриваться как буквальные значения.
  • concat()Соедините два значения вместе. Аргументы обрабатываются как связанные параметры, если не отмечены как буквальные.
  • coalesce()Объединяйте ценности. Аргументы обрабатываются как связанные параметры, если не отмечены как буквальные.
  • dateDiff()Узнайте разницу между двумя датами и временем. Аргументы обрабатываются как связанные параметры, если не отмечены как буквальные.
  • now() В качестве аргумента можно использовать либо «время», либо «дату», позволяющее получить либо текущее время, либо текущую дату.

Предоставляя аргументы для функций SQL, вы можете использовать два типа параметров: буквальные аргументы и связанные параметры. Литеральные параметры позволяют ссылаться на столбцы или другие литералы SQL. Связанные параметры можно использовать для безопасного добавления пользовательских данных в функции SQL. Например:

<?php
// Generates:
// SELECT CONCAT(title, ' NEW') ...;
$concat = $builder->func()->concat([
    'title' => 'literal',
    ' NEW'
]);
$query->select(['title' => $concat]);

Получение результатов по запросу

После того, как вы сделали свой запрос, вы захотите получить из него строки. Есть несколько способов сделать это:

<?php
// Iterate the query
foreach ($builder as $row) {
    echo $row['title'];
}

// Get the statement and fetch all results
$results = $builder->execute()->fetchAll('assoc');

Создание запроса на вставку

Также возможно создание запросов на вставку:

<?php
$builder = $this->getQueryBuilder();
$builder
    ->insert(['first_name', 'last_name'])
    ->into('users')
    ->values(['first_name' => 'Steve', 'last_name' => 'Jobs'])
    ->values(['first_name' => 'Jon', 'last_name' => 'Snow'])
    ->execute()

Для повышения производительности вы можете использовать другой объект построителя в качестве значений для запроса на вставку:

<?php

$namesQuery = $this->getQueryBuilder();
$namesQuery
    ->select(['fname', 'lname'])
    ->from('users')
    ->where(['is_active' => true])

$builder = $this->getQueryBuilder();
$st = $builder
    ->insert(['first_name', 'last_name'])
    ->into('names')
    ->values($namesQuery)
    ->execute()

var_dump($st->lastInsertId('names', 'id'));

Приведенный выше код сгенерирует:

INSERT INTO names (first_name, last_name)
    (SELECT fname, lname FROM USERS where is_active = 1)

Создание запроса на обновление

Создание запросов на обновление аналогично вставке и выбору:

<?php
$builder = $this->getQueryBuilder();
$builder
    ->update('users')
    ->set('fname', 'Snow')
    ->where(['fname' => 'Jon'])
    ->execute()

Создание запроса на удаление

Наконец, удалите запросы:

<?php
$builder = $this->getQueryBuilder();
$builder
    ->delete('users')
    ->where(['accepted_gdpr' => false])
    ->execute()