Динамически добавлять столбцы в существующую таблицу на лету в CakePHP 3
Я хочу добавить столбец в существующую таблицу в CakePHP 3.
Мой ContactsTable.php
код файла:
<?php
namespace App\Model\Table;
use Cake\ORM\Table;
use Migrations\AbstractMigration;
class ContactsTable extends Table
{
public function initialize(array $config)
{
$this->addBehavior('Timestamp');
$table = $this->table('contacts');
$table->addColumn('price', 'decimal')->update();
}
}
Я пробовал, как описано в документации CakePHP 3, но я получил эту ошибку:
Вызов функции-члена addColumn() для не-объекта
Как добавить столбцы "на лету" через контроллер?
Ответы
Ответ 1
код:
<?php
namespace App\Controller;
use Cake\Core\Configure;
use Cake\Network\Exception\NotFoundException;
use Cake\View\Exception\MissingTemplateException;
use Cake\ORM\TableRegistry;
use Cake\Database\Schema\Table;
use Cake\Datasource\ConnectionManager;
use \Migrations\AbstractMigration as AbstractMigration;
use \Phinx\Db\Adapter\MysqlAdapter as MysqlAdapter;
class PagesController extends AppController
{
public function display()
{
$connectionArray = ConnectionManager::get('default')->config();
$connectionArray['pass'] = $connectionArray['password'];
$connectionArray['user'] = $connectionArray['username'];
$connectionArray['name'] = $connectionArray['database'];
$migrationObject = new AbstractMigration(mt_rand());
$migrationObject->setAdapter(new MysqlAdapter($connectionArray));
$tree = $migrationObject->table('tests');
$tree->addColumn('something', 'text')
->update();
}
}
После нескольких часов Hacking, наконец, нашел способ сделать это на лету.
Протестировано по умолчанию cakephp 3 (последнее - на сегодняшний день - 2 июня '16)
Если вы используете другой адаптер базы данных, измените его на этот адаптатор из MysqlAdapter.
Примечание для пользователей:
-
Это уродливый взлом, и его следует использовать ТОЛЬКО, если вы не работаете в организация, в которой для каждой фиксации миграции требуется одноранговая ссылка.
-
mt_rand() НЕ ДОЛЖЕН использоваться в качестве взлома номера версии.
-
нет канонического способа делать это через контроллеры. Обновление в источнике данных ДОЛЖНО всегда быть изменено посредством миграции - с использованием надлежащей структуры.
-
Обратитесь к Запуск миграции в среде без оболочки и попытайтесь создать журналы миграции в /config/migrations
, что было бы больше правил, на лету, и у вас также будут журналы для просмотра сверстниками.
Ответ 2
Если вы хотите добавить новый столбец в таблицу продуктов, например, "цена", а цена - "десятичная", вы должны пойти в свой проект и записать это в консоли:
bin/cake bake migration AddPriceToProducts price:decimal
Вы можете увидеть новый файл, например. Config/Перемещения/20160501190410_AddPriceToProducts.php
<?php
use Migrations\AbstractMigration;
class AddPriceToProducts extends AbstractMigration
{
/**
* Change Method.
*
* More information on this method is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-change-method
* @return void
*/
public function change()
{
$table = $this->table('products');
$table->addColumn('price', 'decimal', [
'default' => null,
...
'null' => true,
]);
$table->update();
}
}
а затем просто запустите миграцию, чтобы добавить этот столбец в базу данных, напишите это в консоли:
bin/cake migrations migrate
Ответ 3
Плагин миграции также поддерживает Выполнение миграции в среде без оболочки.
С момента выпуска версии 1.2
плагина миграции вы можете запускать миграции из среды без оболочки, непосредственно из приложения, с помощью нового класса Migrations. Это может быть удобно, если вы разрабатываете инсталлятор плагинов для CMS, например. Класс Migrations позволяет запускать следующие команды из оболочки миграции: migrate
, rollback
, markMigrated
, status
и seed
.
Каждая из этих команд имеет метод, определенный в классе Migrations.
Вы можете подготовить какой-то пользовательский обработчик, который будет принимать данные столбца с пользовательской стороны и выполнить миграцию. В этом случае это может быть некоторая форма с входами name
и type
. Миграция будет применена к БД после формы с данными, которые будут отправлены.
Вот как это использовать:
use Migrations\Migrations;
$migrations = new Migrations();
// Will return an array of all migrations and their status
$status = $migrations->status();
// Will return true if success. If an error occurred, an exception will be thrown
$migrate = $migrations->migrate();
// Will return true if success. If an error occurred, an exception will be thrown
$rollback = $migrations->rollback();
// Will return true if success. If an error occurred, an exception will be thrown
$markMigrated = $migrations->markMigrated(20150804222900);
// Will return true if success. If an error occurred, an exception will be thrown
$seeded = $migrations->seed();