繁体   English   中英

Yii2以编程方式迁移命令

[英]Yii2 Migrate Command Programmatically

我想使用code而不是控制台窗口up / down migrate数据库。 我已经研究了framework 我尝试了以下代码:

$runner = new yii\console\Application([
                                          'id'       => 'auto-migrate',
                                          'basePath' => dirname(__DIR__)
                                      ]);        

    $runner->runAction('migrate');
    ob_start();
    return htmlentities(ob_get_clean(), null, Yii::$app->charset);

它给出了Internal Server Error 而且甚至不将文件迁移到数据库。 但是,如果目录不存在,它将创建目录。 它的行为方式应该是这样,但是如果迁移文件存在于同一目录中,则会显示Internal Server Error

我可能会通过php function exec来做到这一点,但是如果您真的想通过创建新的应用程序实例来做到这一点,那么您应该能够做到这一点。

案例1-并非很好

//Define, if you want to capture output
defined('STDIN') or define('STDIN', fopen('php://input', 'r'));
defined('STDOUT') or define('STDOUT', fopen('php://output', 'w'));
//Create new console app, if you do not run it from root namespace you should use '\yii\console\Application'
$runner = new \yii\console\Application([
    'id'       => 'auto-migrate',
    'controllerNamespace' => 'console\controllers', //for migrate command it should not matter but for other cases you must specify otherwise applocation cannot find your controllers
    'basePath' => dirname(__DIR__ . '/../../console/config'), //This must point to your console config directory, when i run this in frontend sitecontroller i must add '/../../console/config',
    'components' => [
                'db' => [//If you want to call migrate you probably need some database component
                    'class' => 'yii\db\Connection',
                    'dsn' => 'mysql:host=localhost;dbname=mydb',
                    'username' => 'root',
                    'password' => '',
                    'charset' => 'utf8',
                ],
            ],
]);        
ob_start();
try
{
    $runner->runAction('migrate/up');
}
catch(\Exception $ex)
{
    echo $ex->getMessage();
}
return htmlentities(ob_get_clean(), null, Yii::$app->charset);

结果在我的情况下:

Yii Migration Tool (based on Yii v2.0.1) No new migration found. Your system is up-to-date.

情况二

    ob_start();
    try
    {
        $output = Array();
        exec(__DIR__ . '/../../yii migrate/up', $output);
        echo implode("\n", $output);
    }
    catch(\Exception $ex)
    {
        echo $ex->getMessage();
    }
    return htmlentities(ob_get_clean(), null, Yii::$app->charset);

结果在我的情况下:

Yii Migration Tool (based on Yii v2.0.1) No new migration found. Your system is up-to-date.
\Yii::$app->runAction('migrate', ['migrationPath' => '@yii/rbac/migrations/']);

您可以通过加载控制台配置来创建控制台应用程序以运行迁移:

public function actionMigrate()
{
    // Keep current application
    $oldApp = \Yii::$app;
    // Load Console Application config
    $config = require \Yii::getAlias('@app'). '/config/console.php';
    new \yii\console\Application($config);
    $result = \Yii::$app->runAction('migrate', ['migrationPath' => '@app/migrations/', 'interactive' => false]);
    // Revert application
    \Yii::$app = $oldApp;
    return;
}

上面的示例代码用于yii2-app-basic模板,您可以更改yii2-app-advanced模板的路径。

对于这种情况,我使用此解决方案。 我仅实现migrate/up案例。 要执行任何其他migrate命令,必须配置runAction()的参数。

use yii\console\controllers\MigrateController;

/*Suppose that config is an array with the following structure
[
    'class' => 'yii\db\Connection',
    'dsn' => "$dsn",
    'username' => "$username",
    'password' => "$password",
    'charset' => 'utf8',
]
*/
public function migrateUp($config){
    $migrate = new MigrateController('migrate', \Yii::$app);
    /*The name of the table for keeping applied migration information*/
    $migrate->migrationTable = 'migration';
    /*At least one of `migrationPath` or `migrationNamespaces` should be specified.
    For this example I use `migrationNamespaces` to find a specific set of migrations I want to execute.*/
    $migrate->migrationNamespaces = [
        'app\modules\v1\migrations'
    ];
    $migrate->migrationPath = null;
    /*The DB connection object to use when applying migrations*/
    $migrate->db = $config;
    /*Run migrations without asking questions*/
    $migrate->interactive = false;
    /*The individual commands ran within the migration will not be output to the console*/
    $migrate->compact = true;
    /*php://temp is a read-write stream that allow temporary data to be stored in a file-like wrapper */
    define('STDOUT', $fp= fopen('php://temp', 'r+'));
    /*run migrate/up */
    $status = $migrate->runAction('up');
    /*Rewind the position of the file pointer*/
    rewind($fp);
    $migrationOutput = stream_get_contents($fp);
    if (isset($status)){
        ob_get_clean();
        return ['Errors when executing migrations', $migrationOutput];
    }
    return ['Everything ok', $migrationOutput];
}

在Web应用程序中使用Yii2的“高级模板-控制台”应用程序进行共享托管我已通过一些调整成功应用了上述代码。

单域multi / web及其子文件夹,例如。 公司1 /网络

multi/web/index.php
         /.htaccess
         /assets
         /common/config/main.php
         /common/config/bootstrap.php
         /config/main-local.php has 
                /only db and urlManager baseUrl=''
         /console/config/main.php
         /frontend/config/main.php
         /images
         /company1/web/assets
         /company1/web/images
         /company1/web/.htaccess
         /company1/web/index.php
         /company1/config/main-local.php

         /company2/web/assets
         /company2/web/images
         /company2/web/.htaccess
         /company2/web/index.php
         /company2/config/main-local.php 

         /company3/web/assets
         /company3/web/images
         /company3/web/.htaccess
         /company3/web/index.php
         /company3/config/main-local.php         
         /vendor

每个公司配置main-local仅包含db和UrlManager组件。 UrlManager的baseUrl,例如 '/公司3 /网络/'

multi / web index.php配置如下:

<?php

defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');
defined('YII_CONSOLE') or define('YII_CONSOLE', false);

//vendors from composer.json
require (__DIR__ . '/vendor/autoload.php');

//yii framework
require(__DIR__  . '/vendor/yiisoft/yii2/Yii.php');

//common frontend bower and installer aliases
require(__DIR__ . '/common/config/bootstrap.php');

//empty
require(__DIR__ . '/frontend/config/bootstrap.php');

$config = yii\helpers\ArrayHelper::merge(
    //vendor path, twilio, paypal
    require(__DIR__ . '/common/config/main.php'),

    //db=installer , urlmanager swiftmailer
    require(__DIR__ . '/common/config/main-local.php'),

    //etc... db and UrlManager Removed into above
    require(__DIR__ . '/frontend/config/main.php'),

    //cookie validation key
    require(__DIR__ . '/frontend/config/main-local.php')
);
(new yii\web\Application($config))->run();
?>

每个公司的子文件夹的index.php配置如下:

<?php

defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');
defined('YII_CONSOLE') or define('YII_CONSOLE', false);

require(dirname(dirname(__DIR__)) . '/vendor/autoload.php');
require(dirname(dirname(__DIR__))  . '/vendor/yiisoft/yii2/Yii.php');
//aliases eg. common frontend bower
require(dirname(dirname(__DIR__)) . '/common/config/bootstrap.php');
$config = yii\helpers\ArrayHelper::merge(

    //vendor path components ...rbac
    require(dirname(dirname(__DIR__)) . '/common/config/main.php'),

    //customer's  database and urlmanager and swiftmailer taken out of frontend/config/main.php
    require(dirname(__DIR__) . '/config/main-local.php'),

    //excluding components db and urlmanager included in above
    require(dirname(dirname(__DIR__)) . '/frontend/config/main.php'),

    //cookie validation key
    require(dirname(dirname(__DIR__)) . '/frontend/config/main-local.php')
);
//
(new yii\web\Application($config))->run();
``````
I have created an action in my Site controller to perform the console migration within the actionMigrateto_company_database.


<?php

public function actionMigrateto_company_database()
    {
        ob_start();
        defined('STDIN') or define('STDIN', fopen('php://input', 'r'));
        defined('STDOUT') or define('STDOUT', fopen('php://output', 'w'));
        defined('STDERR') or define('STDERR', fopen('php://stderr', 'w'));
        $oldApp = \Yii::$app;
        // Load Console Application config
        $config = yii\helpers\ArrayHelper::merge(
        //migration namespaces and 
        //namespaces included in individual
        //migration files
        require \Yii::getAlias('@console'). '/config/main.php',    
        //vendor path components ...rbac
        require \Yii::getAlias('@common').'/config/main.php',
        //database
        require (dirname(dirname(__DIR__)) .dirname(Yii::$app->urlManager->baseUrl). '/config/main-local.php'));    
        $runner = new \yii\console\Application($config);
        $runner->runAction('migrate',['db','interactive' => 0]);
        fclose(\STDOUT);
        fclose(\STDIN);
        fclose(\STDERR);
        \Yii::$app = $oldApp;
        return ob_get_clean();
      }
?>

Adjust the frontend\views\layouts\main.php with 

if (Yii::$app->UrlManager->baseUrl === '') and 
 if (Yii::$app->UrlManager->baseUrl <> '') statements.

.htaccess files are all as follows: 
`````
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php
`````

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM