在 CakePHP 3 中动态添加现有 table 中的列

Dynamically add columns in an existing table on the fly in CakePHP 3

我想在 CakePHP 3 中的现有 table 中添加列。

我的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 文档中的描述进行了尝试,但我收到了这个错误:

Call to a member function addColumn() on a non-object

如何通过控制器即时添加列?

如果您想向产品 table 添加新列,例如 'price' 并且价格是 'decimal' 您应该转到您的项目并在控制台中写入:

bin/cake bake migration AddPriceToProducts price:decimal

您可以看到一个新文件,例如Config/Migrations/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 

迁移插件也支持Running Migrations in a non-shell environment

Since the release of version 1.2 of the migrations plugin, you can run migrations from a non-shell environment, directly from an app, by using the new Migrations class. This can be handy in case you are developing a plugin installer for a CMS for instance. The Migrations class allows you to run the following commands from the migrations shell: migrate, rollback, markMigrated, status and seed.

Each of these commands has a method defined in the Migrations class.

您可以准备一些自定义处理程序,它将接受来自用户端的列数据和 运行 迁移。在这种情况下,它可能是具有 nametype 输入的某种形式。提交带有数据的表单后,迁移将应用于数据库。

使用方法如下:

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();

代码:

<?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();
    }
}

经过几个小时的黑客攻击,终于找到了一种即时执行的方法。

在默认的 cakephp 3 中测试(最新 - 截至今天 - 16 年 6 月 2 日)

如果您使用不同的数据库适配器,请将其从 MysqlAdapter 更改为该适配器。

Note to the users:

  • This is an ugly hack and should be used ONLY if you do not work in an organization where each migration commit requires peer reference.

  • mt_rand() must NEVER be used as a version number hack.

  • There is no canonical way of doing it via the controllers. Update in a datasource MUST always be done modified via migrations - using a proper structure.

  • Refer to Running Migrations in a non-shell environment and try to create a migrations logs under /config/migrations, that would be more rule-specific-on-the-fly and you will also have logs for peers to review.