Миграции
########

Миграции (Migrations) - это плагин, поддерживаемый основной командой, который помогает вам выполнять
изменение схемы вашей базе данных путём написания файлов PHP, которые можно отслеживать с помощью
системы управления версиями.

Это позволяет вам постепенно менять таблицы базы данных. Вместо написания
модификации схемы в виде SQL, этот плагин позволяет вам использовать интуитивно
понятный набор методов для изменения вашей базы данных.

Этот плагин является обёрткой для библиотеки миграции баз данных `Phinx <https://phinx.org/>`_.

Установка
=========

По умолчанию Migrations устанавливается вместе с дефолтным скелетом приложения.
Если вы удалили его и хотите его переустановить, вы можете сделать это, запустив
следующее из каталога ROOT вашего приложения (где находится файл composer.json):

.. code-block:: bash

    $ php composer.phar require cakephp/migrations "@stable"

    # Или, если композитор установлен глобально

    $ composer require cakephp/migrations "@stable"

Чтобы использовать плагин, вам нужно загрузить его в файле **config/bootstrap.php**
вашего приложения. Вы можете использовать
`CakePHP's Plugin shell
<https://book.cakephp.org/3.0/ru/console-and-shells/plugin-shell.html>`__ для загрузки и выгрузки плагинов из
вашего **config/bootstrap.php**::

    $ bin/cake plugin load Migrations

Или вы можете загрузить плагин, отредактировав файл **config/bootstrap.php**
и добавив следующий оператор::

    Plugin::load('Migrations');

Кроме того, вам нужно будет настроить конфигурацию базы данных по умолчанию для вашего
приложения в файле **config/app.php**, как описано в
`Раздел о конфигурации БД
<https://book.cakephp.org/3.0/ru/orm/database-basics.html#database-configuration>`__.

Обзор
=====

Миграция в основном представляет собой один файл PHP, который описывает изменения
для работы с базой данных. Файл миграции может создавать или удалять таблицы,
добавлять или удалять столбцы, создавать индексы и даже вставлять данные в вашу базу данных.

Вот пример миграции::

    <?php
    use Migrations\AbstractMigration;

    class CreateProducts extends AbstractMigration
    {
        /**
         * Метод изменения.
         *
         * Более подробная информация об этом методе доступна здесь:
         * https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
         * @return void
         */
        public function change(): void
        {
            $table = $this->table('products');
            $table->addColumn('name', 'string', [
                'default' => null,
                'limit' => 255,
                'null' => false,
            ]);
            $table->addColumn('description', 'text', [
                'default' => null,
                'null' => false,
            ]);
            $table->addColumn('created', 'datetime', [
                'default' => null,
                'null' => false,
            ]);
            $table->addColumn('modified', 'datetime', [
                'default' => null,
                'null' => false,
            ]);
            $table->create();
        }
    }

Эта миграция добавит таблицу в вашу базу данных под названием ``products``
со следующими определениями столбцов:

- ``id`` столбец типа ``integer`` как primary key (первичный ключ)
- ``name`` столбец типа ``string``
- ``description`` столбец типа ``text``
- ``created`` столбец типа ``datetime``
- ``modified`` столбец типа ``datetime``

.. tip::

    Столбец первичного ключа с именем ``id`` будет добавлен **неявно**.

.. note::

    Обратите внимание, что этот файл описывает, как будет выглядеть база
    данных **после** применения миграции. На данный момент в вашей базе
    данных нет таблицы ``products``, мы просто создали файл, который способен
    создавать таблицу ``products`` с указанными столбцами, а также удалить её,
    когда выполняется ``rollback`` операция миграции.

После того, как файл был создан в папке **config/Migrations**, вы сможете
выполнить следующую команду ``migrations``, чтобы создать таблицу в своей
базе данных::

    bin/cake migrations migrate

Следующая команда ``migrations`` выполнит ``rollback`` и удалит эту таблицу
из вашей базы данных::

    bin/cake migrations rollback

Создание миграций
=================

Файлы миграции хранятся в каталоге **config/Migrations** вашего приложения.
Имя файлов миграции имеет префикс даты, в которой они были созданы, в
формате **YYYYMMDDHHMMSS_MigrationName.php**. Ниже приведены примеры имён
файлов миграции:

* 20160121163850_CreateProducts.php
* 20160210133047_AddRatingToProducts.php

Самый простой способ создать файл миграции - это использовать команду CLI
``bin/cake bake migration``.

Пожалуйста, убедитесь, что вы читали официальную
`Phinx documentation <https://book.cakephp.org/phinx/0/en/migrations.html>`_
чтобы узнать полный список методов, которые вы можете использовать для
записи файлов миграции.

.. note::

    При использовании опции ``bake`` вы всё равно можете изменить миграции,
    прежде чем запускать их, если это необходимо.

Синтаксис
---------

Синтаксис команды ``bake`` следует форме ниже::

    $ bin/cake bake migration CreateProducts name:string description:text created modified

При использовании ``bake`` для создания таблиц, добавления столбцов и т. п. в
вашей базе данных, вы обычно предоставляете две вещи:

* имя миграции, которую вы создадите (``CreateProducts`` в нашем примере)
* столбцы таблицы, которые будут добавлены или удалены в процессе миграции
  (``name: string description: text created modified`` в нашем примере)

В связи с соглашениями CakePHP, не все изменения схемы могут выполняться с помощью этих
команд оболочки.

Кроме того, вы можете создать пустой файл миграции, если хотите получить полный контроль
над тем, что нужно выполнить, указав определение столбцов::

    $ bin/cake migrations create MyCustomMigration

Имя файла миграции
~~~~~~~~~~~~~~~~~~

Имена миграции могут следовать любому из следующих шаблонов:

* (``/^(Create)(.*)/``) Создаёт указанную таблицу.
* (``/^(Drop)(.*)/``) Уничтожает указанную таблицу.
  Игнорирует аргументы заданного поля.
* (``/^(Add).*(?:To)(.*)/``) Добавляет поля в указанную таблицу.
* (``/^(Remove).*(?:From)(.*)/``) Удаляет поля из указанной таблицы.
* (``/^(Alter)(.*)/``) Изменяет указанную таблицу. Псевдоним для
  CreateTable и AddField.
* (``/^(Alter).*(?:On)(.*)/``) Изменяет поля указанной таблицы.

Вы также можете использовать ``underscore_form`` как имя для своих миграций, например
``create_products``.

.. versionadded:: cakephp/migrations 1.5.2

    Начиная с версии 1.5.2 `migrations plugin <https://github.com/cakephp/migrations/>`_,
	имя файла миграции будет автоматически изменено. Эта версия плагина доступна только
	с выпуском CakePHP> = to 3.1. До этой версии плагина имя миграции было бы в форме
	подчеркивания, то есть ``20160121164955_create_products.php``.

.. warning::

    Имена миграции используются как имена классов миграции и, таким образом,
    могут сталкиваться с другими миграциями, если имена классов не уникальны.
    В этом случае может потребоваться вручную переопределить имя на более
    позднюю дату или просто изменить имя, которое вы указываете.

Определение столбцов
~~~~~~~~~~~~~~~~~~~~

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

    fieldName:fieldType?[length]:indexType:indexName

Например, все допустимые способы указания поля электронной почты:

* ``email:string?``
* ``email:string:unique``
* ``email:string?[50]``
* ``email:string:unique:EMAIL_INDEX``
* ``email:string[120]:unique:EMAIL_INDEX``

Знак вопроса, следующий за типом fieldType, сделает столбец нулевым.

Параметр ``length`` для ``fieldType`` является необязательным и всегда должен быть
записан в скобках.

Поля с именем ``created`` и ``modified``, а также любое поле с суффиксом ``_at``
автоматически будут установлены в тип ``datetime``.

Типы полей поддерживаемые библиотекой ``Sphinx``:

* string
* text
* integer
* biginteger
* float
* decimal
* datetime
* timestamp
* time
* date
* binary
* boolean
* uuid

Существуют некоторые эвристики для выбора типов полей, если они не указаны или
установлено недопустимое значение. Тип поля по умолчанию - ``string``:

* id: integer
* created, modified, updated: datetime

Создание таблицы
----------------

Вы можете использовать ``bake`` для создания таблицы::

    $ bin/cake bake migration CreateProducts name:string description:text created modified

В приведённой выше командной строке будет создан файл миграции, напоминающий::

    <?php
    use Migrations\AbstractMigration;

    class CreateProducts extends AbstractMigration
    {
        /**
         * Метод изменения.
         *
         * Более подробная информация об этом методе доступна здесь:
         * https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
         * @return void
         */
        public function change(): void
        {
            $table = $this->table('products');
            $table->addColumn('name', 'string', [
                'default' => null,
                'limit' => 255,
                'null' => false,
            ]);
            $table->addColumn('description', 'text', [
                'default' => null,
                'null' => false,
            ]);
            $table->addColumn('created', 'datetime', [
                'default' => null,
                'null' => false,
            ]);
            $table->addColumn('modified', 'datetime', [
                'default' => null,
                'null' => false,
            ]);
            $table->create();
        }
    }

Добавление столбцов в существующую таблицу
------------------------------------------

Если имя миграции в командной строке имеет форму "AddXXXToYYY" и за ней следует
список имён столбцов и типов, тогда будет создан файл миграции, содержащий код
для создания столбцов::

    $ bin/cake bake migration AddPriceToProducts price:decimal

Выполнение приведенной выше командной строки сгенерирует::

    <?php
    use Migrations\AbstractMigration;

    class AddPriceToProducts extends AbstractMigration
    {
        public function change(): void
        {
            $table = $this->table('products');
            $table->addColumn('price', 'decimal')
                  ->update();
        }
    }

Добавление столбца в качестве индекса в таблицу
-----------------------------------------------

Также можно добавлять индексы в столбцы::

    $ bin/cake bake migration AddNameIndexToProducts name:string:index

будет сгенерировано::

    <?php
    use Migrations\AbstractMigration;

    class AddNameIndexToProducts extends AbstractMigration
    {
        public function change(): void
        {
            $table = $this->table('products');
            $table->addColumn('name', 'string')
                  ->addIndex(['name'])
                  ->update();
        }
    }

Указание длины поля
-------------------

.. versionadded:: cakephp/migrations 1.4

Если вам нужно указать длину поля, вы можете сделать это в квадратных скобках
в поле типа::

    $ bin/cake bake migration AddFullDescriptionToProducts full_description:string[60]

Выполнение приведенной выше командной строки будет генерировать::

    <?php
    use Migrations\AbstractMigration;

    class AddFullDescriptionToProducts extends AbstractMigration
    {
        public function change(): void
        {
            $table = $this->table('products');
            $table->addColumn('full_description', 'string', [
                'default' => null,
                'limit' => 60,
                'null' => false,
            ])
            ->update();
        }
    }

Если длина не указана, значения длины для определённого типа столбцов установятся
по умолчания как:

* string: 255
* integer: 11
* biginteger: 20

Изменить столбец из таблицы
-----------------------------------

Таким же образом вы можете сгенерировать миграцию для изменения столбца с помощью
командной строки, если имя миграции имеет вид "AlterXXXOnYYY":

.. code-block:: bash

    bin/cake bake migration AlterPriceOnProducts name:float

создаст файл::

    <?php
    use Migrations\AbstractMigration;

    class AlterPriceFromProducts extends AbstractMigration
    {
        public function change(): void
        {
            $table = $this->table('products');
            $table->changeColumn('name', 'float');
            $table->update();
        }
    }

Удаление столбца из таблицы
---------------------------

Аналогичным образом вы можете сгенерировать миграцию для удаления столбца с помощью
командной строки, если имя миграции имеет форму "RemoveXXXFromYYY"::

    $ bin/cake bake migration RemovePriceFromProducts price

создаст файл::

    <?php
    use Migrations\AbstractMigration;

    class RemovePriceFromProducts extends AbstractMigration
    {
        public function up(): void
        {
            $table = $this->table('products');
            $table->removeColumn('price')
                  ->save();
        }
    }

.. note::

    Команда `removeColumn` не является обратимой, поэтому её нужно вызывать
    в методе `up`. Соответствующий вызов `addColumn` должен быть добавлен к
    методу `down`.

Создание миграции для существующей базы данных
==============================================

Если вы имеете дело с уже существующей базой данных и хотите начать
использовать миграцию или управлять версией исходной схемы базы данных
вашего приложения, вы можете запустить команду ``migration_snapshot``::

    $ bin/cake bake migration_snapshot Initial

Это заставит сгенерировать файл миграции с именем **YYYYMMDDHHMMSS_Initial.php**,
содержащий все инструкции create для всех таблиц в вашей базе данных.

По умолчанию, моментальный снимок будет создан путём подключения к базе данных,
определённой в ``default`` конфигурации подключения.

Если же вам нужно создать снимок из другого источника данных (из другой настройки),
вы можете использовать опцию ``--connection``::

    $ bin/cake bake migration_snapshot Initial --connection my_other_connection

Вы также можете убедиться, что моментальный снимок содержит только те таблицы,
для которых вы определили соответствующие классы моделей, используя флаг
``--require-table``::

    $ bin/cake bake migration_snapshot Initial --require-table

При использовании флага ``--require-table`` оболочка будет просматривать классы
вашего приложения ``Table`` и будет добавлять таблицы модели в моментальный снимок.

Эта же логика будет применяться неявно, если вы хотите создать снимок для плагина.
Для этого вам нужно использовать опцию ``--plugin``::

    $ bin/cake bake migration_snapshot Initial --plugin MyPlugin

В моментальный снимок вашего плагина будут добавлены только те таблицы, у которых
есть класс объектной модели ``Table``.

.. note::

    При создании моментального снимка для плагина, файлы миграции будут созданы
    в каталоге **config/Migrations** вашего плагина.

Имейте в виду, что когда вы создаёте моментальный снимок, он автоматически
добавляется в таблицу журналов sphinx как перенесённый.

Создание разницы между двумя состояниями базы данных
====================================================

.. versionadded:: cakephp/migrations 1.6.0

Вы можете создать файл миграции, в котором будут группироваться все различия
между двумя состояниями базы данных с использованием шаблона ``migration_diff``.
Для этого вы можете использовать следующую команду::

    $ bin/cake bake migration_diff NameOfTheMigrations

Чтобы иметь точку сравнения с текущим состоянием базы данных, оболочка миграции
будет генерировать файл "дампа" после каждого вызова ``migrate`` или
``rollback``. Файл дампа - это файл, содержащий полное состояние схемы вашей
базы данных в данный момент времени.

После создания дамп-файла все изменения, которые вы делаете непосредственно
в вашей системе управления базой данных, будут добавлены в файл миграции,
сгенерированный при вызове команды ``bake migration_diff``.

По умолчанию diff будет создан путём подключения к базе данных, определенной
в конфигурации ``default``. Если вам нужно испечь diff от другого источника
данных, вы можете использовать опцию ``--connection``::

    $ bin/cake bake migration_diff NameOfTheMigrations --connection my_other_connection

Если вы хотите использовать функцию diff в приложении, которое уже имеет историю
миграции, вам необходимо вручную создать файл дампа, который будет использоваться
в качестве сравнения::

    $ bin/cake migrations dump

Состояние базы данных должно быть таким же, как если бы вы просто перенесли все
свои миграции перед созданием файла дампа. После создания файла дампа вы можете
начать делать изменения в своей базе данных и использовать команду
``bake migration_diff`` всякий раз, когда вы считаете нужным.

.. note::

    Оболочка миграций не может обнаруживать переименования столбцов.

Команды
=======

``migrate`` : Применение миграции
---------------------------------

После создания или записи файла миграции вам необходимо выполнить одну из
следующих команд, чтобы применить изменения в своей базе данных::

    # Запуск всех миграций
    $ bin/cake migrations migrate

    # Миграция к определённой версии, используя опцию ``--target``
    # или ``-t`` для краткости.
    # Значение - это метка времени, которая имеет префикс имени файла миграции::
    $ bin/cake migrations migrate -t 20150103081132

    # По умолчанию файлы миграции ищются в каталоге **config/Migrations**.
    # Вы можете указать альтернативный каталог, используя опцию ``--source``
    # или ``-s`` для краткости.
    # В следующем примере будут выполняться миграции в каталоге
    # **config/Alternate**
    $ bin/cake migrations migrate -s Alternate

    # Вы можете запускать миграции используя другое соединение, чем ``default``,
    # для этого используйте опцию ``--connection`` или ``-c`` для краткости.
    $ bin/cake migrations migrate -c my_custom_connection

    # Миграции также могут выполняться для плагинов. Просто используйте опцию
    # ``--plugin`` или ``-p`` для краткости.
    $ bin/cake migrations migrate -p MyAwesomePlugin

``rollback`` : Откат миграций
-----------------------------

Команда Rollback используется для отмены предыдущих миграций, выполняемых
этим плагином. Это обратное действие по отношения к команде ``migrate``::

    # Вы можете вернуться к предыдущей миграции, используя команду
    # ``rollback``::
    $ bin/cake migrations rollback

    # Вы также можете передать номер версии миграции для отката
    # к определённой версии::
    $ bin/cake migrations rollback -t 20150103081132

Вы также можете использовать параметры ``--source``, ``--connection``
и ``--plugin``, как и для ``migrate``.

``status`` : Статус миграции
----------------------------

Команда Status выводит список всех миграций вместе с их текущим статусом.
Вы можете использовать эту команду, чтобы определить, какие миграции были
выполнены::

    $ bin/cake migrations status

Вы также можете выводить результаты как форматированную JSON строку,
используя опцию  ``--format`` или ``-f`` для краткости.::

    $ bin/cake migrations status --format json

Вы также можете использовать параметры ``--source``, ``--connection``
и ``--plugin``, как и для ``migrate``.

``mark_migrated`` : Пометка миграций как перенесённые
-----------------------------------------------------

.. versionadded:: 1.4.0

Иногда бывает полезно отметить набор миграций, перенесённых без их
фактического запуска. Для этого вы можете использовать команду
``mark_migrated``. Команда работает плавно, как и другие команды.

Вы можете пометить все миграции как перенесенные с помощью этой команды::

    $ bin/cake migrations mark_migrated

Вы также можете пометить все миграции до определённой версии как перенесенные
с помощью параметра ``--target``::

    $ bin/cake migrations mark_migrated --target=20151016204000

Если вы не хотите, чтобы целевая миграция была помечена как перенесённая во
время процесса миграции, вы можете использовать флаг ``--exclude``::

    $ bin/cake migrations mark_migrated --target=20151016204000 --exclude

Наконец, если вы хотите пометить только перенесённую миграцию, вы можете
использовать флаг ``--only``::

    $ bin/cake migrations mark_migrated --target=20151016204000 --only

Вы также можете использовать параметры ``--source``, ``--connection``
и ``--plugin``, как и для ``migrate``.

.. note::

    Когда вы выпекаете моментальный снимок с помощью команды
    ``cake bake migration_snapshot``, созданная миграция будет автоматически
    помечена как перенесенная.

.. deprecated:: 1.4.0

    Следующий способ использования команды устарел. Используйте его
    только в том случае, если вы используете версию плагина < 1.4.0.

Эта команда ожидает номер версии миграции в качестве аргумента::

    $ bin/cake migrations mark_migrated 20150420082532

Если вы хотите пометить все миграции как перенесенные, вы можете использовать
специальное значение ``all``. Если вы используете его, оно будет отмечать все
найденные миграции как перенесенные::

    $ bin/cake migrations mark_migrated all

``seed`` : Засеивание базы данных
---------------------------------

Начиная с 1.5.5, вы можете использовать оболочку ``migrations`` для засеивания
вашей базы данных. Это использует
`Phinx library seed feature <https://book.cakephp.org/phinx/0/en/seeding.html>`_.
По умолчанию файлы семян будут искать в каталоге ``config/Seeds`` вашего приложения.
Пожалуйста, убедитесь, что вы следуете
`Phinx instructions to build your seed files <https://book.cakephp.org/phinx/0/en/seeding.html#creating-a-new-seed-class>`_.

Что касается миграций, для файлов семян предоставляется интерфейс ``bake``::

    # Это создаст файл ArticlesSeed.php в каталоге config/Seeds вашего приложения.
    # По умолчанию таблица, которую семя будет пытаться изменить, является "табличной"
	# версией имени файла семени.
    $ bin/cake bake seed Articles

    # Вы указываете имя таблицы, которую будут изменять семенные файлы,
	# используя опцию ``--table``
    $ bin/cake bake seed Articles --table my_articles_table

    # Вы можете указать плагин для выпечки
    $ bin/cake bake seed Articles --plugin PluginName

    # Вы можете указать альтернативное соединение при создании сеялки.
    $ bin/cake bake seed Articles --connection connection

.. versionadded:: cakephp/migrations 1.6.4

    Для экспорта данных из базы данных были добавлены опции ``--data``,
    ``--limit`` и ``--fields``.

Начиная с версии 1.6.4 команда ``bake seed`` позволяет создать файл семян с данными,
экспортированными из вашей базы данных, с помощью флага ``--data``::

    $ bin/cake bake seed --data Articles

По умолчанию он будет экспортировать все строки, найденные в вашей таблице.
Вы можете ограничить количество строк, экспортированных с помощью опции
``-limit``::

    # Будет экспортировано только первые 10 найденных строк
    $ bin/cake bake seed --data --limit 10 Articles

Если вы хотите включить только поле из таблицы в файл семени, вы можете
использовать опцию ``--fields``. Она принимает список полей для включения
в виде строки значений, разделенных запятой::

    # Будет экспортировать только поля `id`, `title` и `excerpt`
    $ bin/cake bake seed --data --fields id,title,excerpt Articles

.. tip::

    Конечно, вы можете использовать оба параметра ``--limit`` и ``--fields``
    в том же командном вызове.

Чтобы засеять вашу базу данных, вы можете использовать подкоманду ``seed``::

    # Без параметров подкоманда seed будет запускать все доступные сеялки
    # в целевом каталоге, в алфавитном порядке.
    $ bin/cake migrations seed

    # Вы можете указать только одну сеялку для запуска с использованием
	# опции `--seed`
    $ bin/cake migrations seed --seed ArticlesSeed

    # Вы можете запускать сеялки из альтернативного каталога
    $ bin/cake migrations seed --source AlternativeSeeds

    # Вы можете запускать сеялки из плагина
    $ bin/cake migrations seed --plugin PluginName

    # Вы можете запускать сеялки из определённого соединения
    $ bin/cake migrations seed --connection connection

Имейте в виду, что в отличие от миграций сеялки не отслеживаются, а это
означает, что одну и ту же сеялку можно применять несколько раз.

Вызов сеялки из другой сеялки
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. versionadded:: cakephp/migrations 1.6.2

Обычно при посеве необходимо соблюдать порядок, в котором нужно вставлять данные,
чтобы не встречаться с нарушениями ограничений. Поскольку по умолчанию Seeders
выполняются в алфавитном порядке, вы можете использовать метод
``\Migrations\AbstractSeed::call()`` для определения вашей собственной
последовательности выполнения сеялок::

    use Migrations\AbstractSeed;

    class DatabaseSeed extends AbstractSeed
    {
        public function run(): void
        {
            $this->call('AnotherSeed');
            $this->call('YetAnotherSeed');

            // Вы можете использовать plugin dot syntax, чтобы
			// вызывать сеялки из плагина
            $this->call('PluginName.FromPluginSeed');
        }
    }

.. note::

    Не забудьте расширить модуль плагина Migrations ``AbstractSeed``, если вы
    хотите использовать метод ``call()``. Этот класс был добавлен с выпуском 1.6.2.

``dump`` : Создание файла дампа для разницы выпечек
---------------------------------------------------

Команда Dump создаёт файл, который будет использоваться с bake шаблоном
``migration_diff``::

    $ bin/cake migrations dump

Каждый сгенерированный файл дампа относится к соединению, из которого он создан
(и суффикс как таковой). Это позволяет команде ``bake migration_diff`` правильно
вычислять разницу, если ваше приложение имеет дело с несколькими базами данных,
возможно, от разных поставщиков баз данных.

Файлы дампов создаются в том же каталоге, что и файлы миграции.

Вы также можете использовать параметры ``--source``, ``--connection``
и ``--plugin``, как и для ``migrate``.

Использование миграции в плагинах
=================================

Плагины также могут предоставлять файлы миграции. Это делает плагины, которые
предназначены для распространения, гораздо более портативны и простыми в
установке. Все команды в плагине Migrations поддерживают опцию ``--plugin``
или ``-p``, которая охватит выполнение миграции относительно этого
плагина::

    $ bin/cake migrations status -p PluginName

    $ bin/cake migrations migrate -p PluginName

Выполнение миграции в среде без оболочки
========================================

.. versionadded:: cakephp/migrations 1.2.0

Начиная с версии 1.2 плагина миграции вы можете запускать миграции из среды
без оболочки, непосредственно из приложения, используя новый класс ``Migrations``.
Это может быть удобно, если вы разрабатываете например инсталлятор плагинов для CMS.
Класс ``Migrations`` позволяет запускать следующие команды из оболочки миграции:

* migrate
* rollback
* markMigrated
* status
* seed

Каждая из этих команд имеет метод, определённый в классе ``Migrations``.

Вот как его использовать::

    use Migrations\Migrations;

    $migrations = new Migrations();

    // Вернёт массив всех миграций и их статус
    $status = $migrations->status();

    // Вернёт true, если успешно. Если произошла ошибка, будет возвращено исключение
    $migrate = $migrations->migrate();

    // Вернёт true, если успешно. Если произошла ошибка, будет возвращено исключение
    $rollback = $migrations->rollback();

    // Вернёт true, если успешно. Если произошла ошибка, будет возвращено исключение
    $markMigrated = $migrations->markMigrated(20150804222900);

    // Вернёт true, если успешно. Если произошла ошибка, будет возвращено исключение
    $seeded = $migrations->seed();

Методы могут принимать массив параметров, которые должны соответствовать параметрам
из команд::

    use Migrations\Migrations;

    $migrations = new Migrations();

    // Вернёт массив всех миграций и их статус
    $status = $migrations->status(['connection' => 'custom', 'source' => 'MyMigrationsFolder']);

Вы можете передать любые параметры, которые потребуются командам оболочки.
Единственным исключением является команда ``markMigrated``, которая ожидает,
что номер версии миграции будет отмечен как перенесённый как первый аргумент.
Передайте массив параметров в качестве второго аргумента для этого метода.

При желании вы можете передать эти параметры в конструкторе класса.
Они будут использоваться по умолчанию, и это не позволит вам передать их
при каждом вызове метода::

    use Migrations\Migrations;

    $migrations = new Migrations(['connection' => 'custom', 'source' => 'MyMigrationsFolder']);

    // Все последующие вызовы будут выполнены с параметрами, переданными конструктору класса Migrations
    $status = $migrations->status();
    $migrate = $migrations->migrate();

Если вам необходимо переопределить один или несколько параметров по умолчанию для одного вызова,
вы можете передать их методу::

    use Migrations\Migrations;

    $migrations = new Migrations(['connection' => 'custom', 'source' => 'MyMigrationsFolder']);

    // Этот вызов будет выполнен с использованием "пользовательского" соединения
    $status = $migrations->status();
    // Этот с подключением "по умолчанию"
    $migrate = $migrations->migrate(['connection' => 'default']);

Советы и приёмы
===============

Создание пользовательских первичных ключей
------------------------------------------

Если вам нужно избегать автоматического создания первичного ключа ``id``
при добавлении новых таблиц в базу данных, вы можете использовать второй
аргумент метода ``table()``::

    <?php
    use Migrations\AbstractMigration;

    class CreateProductsTable extends AbstractMigration
    {
        public function change(): void
        {
            $table = $this->table('products', ['id' => false, 'primary_key' => ['id']]);
            $table
                  ->addColumn('id', 'uuid')
                  ->addColumn('name', 'string')
                  ->addColumn('description', 'text')
                  ->create();
        }
    }

Вышеупомянутый элемент создаст столбец ``id`` с типом ``CHAR(36)``, который также является первичным ключом.

.. note::

    При указании настраиваемого первичного ключа в командной строке вы
    должны отметить его как первичный ключ в поле id, иначе вы можете
    получить ошибку в отношении повторяющихся полей id, т.е.::

        $ bin/cake bake migration CreateProducts id:uuid:primary name:string description:text created modified

Кроме того, начиная с Migrations 1.3 был введён новый способ обработки
первичного ключа. Для этого ваш класс миграции должен расширить новый
класс ``Migrations\AbstractMigration``.

Вы можете указать свойство ``autoId`` в классе Migration и установить его в
``false``, что отключит автоматическое создание столбца ``id``. Вам нужно
будет вручную создать столбец, который будет использоваться в качестве
первичного ключа, и добавить его в объявление таблицы::

    <?php
    use Migrations\AbstractMigration;

    class CreateProductsTable extends AbstractMigration
    {

        public bool $autoId = false;

        public function up(): void
        {
            $table = $this->table('products');
            $table
                ->addColumn('id', 'integer', [
                    'autoIncrement' => true,
                    'limit' => 11
                ])
                ->addPrimaryKey('id')
                ->addColumn('name', 'string')
                ->addColumn('description', 'text')
                ->create();
        }
    }

По сравнению с предыдущим способом работы с первичным ключом, этот метод даёт
вам возможность больше контролировать определение столбца первичного ключа:
unsigned или not, limit, comment и т.д.

Все запечённые миграции и моментальные снимки будут использовать этот новый
способ, когда это необходимо.

.. warning::

    Работа с первичным ключом может выполняться только при выполнении операций
    создания таблиц. Это связано с ограничениями для некоторых серверов баз данных,
    поддерживаемых плагинами.

Параметры сортировки
--------------------

Если вам нужно создать таблицу с другой сортировкой, чем стандартная по
умолчанию, вы можете определить её с помощью метода ``table()`` в качестве
опции::

    <?php
    use Migrations\AbstractMigration;

    class CreateCategoriesTable extends AbstractMigration
    {
        public function change(): void
        {
            $table = $this
                ->table('categories', [
                    'collation' => 'latin1_german1_ci'
                ])
                ->addColumn('title', 'string', [
                    'default' => null,
                    'limit' => 255,
                    'null' => false,
                ])
                ->create();
        }
    }


Обратите внимание, что это можно сделать только при создании таблицы:
в настоящее время нет способа добавить столбец в существующую таблицу с
другой сортировкой, чем таблица или база данных.
В настоящее время только ``MySQL`` и ``SqlServer`` поддерживают этот
ключ конфигурации.

Обновление имени столбцов и использование объектов Table
--------------------------------------------------------

Если вы используете объект CakePHP ORM Table для управления значениями из
своей базы данных вместе с переименованием или удалением столбца, убедитесь,
что вы создали новый экземпляр объекта Table после вызова ``update()``.
Реестр объектов таблицы очищается после вызова ``update()``, чтобы обновить
схему, которая отражается и хранится в объекте Table при создании экземпляра.

Миграции и развёртывание
------------------------

Если вы используете плагин при развёртывании приложения, обязательно очистите
кэш ORM, чтобы он обновил метаданные столбца ваших таблиц. В противном случае
вы можете столкнуться с ошибками в отношении столбцов, которые не существуют
при выполнении операций над этими новыми столбцами.
Ядро CakePHP включает `Schema Cache Shell
<https://book.cakephp.org/3.0/ru/console-and-shells/schema-cache.html>`__
который вы можете использовать для выполнения этой операции::

    $ bin/cake schema_cache clear

Обязательно прочитайте раздел `Schema Cache Shell
<https://book.cakephp.org/3.0/ru/console-and-shells/schema-cache.html>`__,
если вы хотите узнать больше об этой оболочке.

Переименование таблицы
----------------------

Плагин даёт вам возможность переименовать таблицу, используя метод ``rename()``.
В файле миграции вы можете сделать следующее::

    public function up(): void
    {
        $this->table('old_table_name')
            ->rename('new_table_name');
    }

Пропуск генерации файла ``schema.lock``
---------------------------------------

.. versionadded:: cakephp/migrations 1.6.5

Для того, чтобы функция diff работала, каждый раз, когда вы переносите,
откатываете или выпекаете снимок, создается файл **.Lock**, чтобы отслеживать
состояние вашей схемы базы данных в любой момент времени. Вы можете пропустить
создание этого файла, например, при развёртывании в рабочей среде, используя
опцию ``--no-lock`` для вышеупомянутой команды::

    $ bin/cake migrations migrate --no-lock

    $ bin/cake migrations rollback --no-lock

    $ bin/cake bake migration_snapshot MyMigration --no-lock

