Yii2 以编程方式迁移命令
Yii2 Migrate Command Programmatically
我想 migrate
up
/down
数据库使用 code
而不是控制台 window。我调查了 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 函数 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];
}
使用 Yii2 的高级模板的共享主机 - Web 应用程序中的控制台应用程序
我已经通过一些调整成功地应用了上面的代码。
带有子文件夹的单域 multi/web,例如。 company1/web
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 例如。 '/company3/web/'
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
`````
我想 migrate
up
/down
数据库使用 code
而不是控制台 window。我调查了 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 函数 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];
}
使用 Yii2 的高级模板的共享主机 - Web 应用程序中的控制台应用程序 我已经通过一些调整成功地应用了上面的代码。
带有子文件夹的单域 multi/web,例如。 company1/web
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 例如。 '/company3/web/'
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
`````