Closed hesna closed 9 years ago
defined('STDIN') or define('STDIN', fopen('php://stdin', 'r')); defined('STDOUT') or define('STDOUT', fopen('php://stdout', 'w'));
this is required by console app. not sure if it applies to your situation
Yeah thank you that solved the problem! But I don't get it, why it was working with version 2.0.0 and stopped working with version 2.0.1? and shouldn't this code be part of core framework?
It's currently located in yii
file which is Yii console bootstrap file, so gets executed whenever one uses terminal to run a console application. But there are scenarios that someone wants to create a console app within a web app, in that case those constants would be undefined.
Or is there another way of doing this job that I'm not aware of?
creating a console app in web context can have various side effects, if we want to support this, there may be more things needed to consider.
I suggest that putting the code for creating the STDIN and STDOUT constants into init() of the console app class.
I suggest that putting the code for creating the STDIN and STDOUT constants into init() of the console app class.
If that's the case then how about I make the changes and create a PR?
feel free to send a PR but I'd like to review more places of the console support before I'll merge it.
by the way, for not CLI PHP output MUST BE 'php://output', otherwise it outputs only last line. at least it is for me in FastCGI.
i find another difficulty with migrations. i cannot combine them (in my case yii2 rbac and my schema). Here's similar approach to call migrations from web application. It works but like a card house so far
use yii\web\Controller;
use yii\console\controllers\MigrateController;
use yii\web\Application;
use yii\base\Exception;
class InstallController extends Controller
{.....
public function actionInstall()
{
//app integration
define('STDOUT', fopen('php://output', 'w'));
$cfg_my = [
'migrationTable' => 'yii2_migrations',
'migrationPath' => \Yii::getAlias('@console-app/migrations'),
'interactive' => 0,
'templateFile' => \Yii::getAlias('@console-app/migrations/_template.php'),
'db' => \Yii::$app->db
];
$cfg_rbac = $cfg_my;
$cfg_rbac['migrationPath'] = \Yii::getAlias('@yii/rbac/migrations');
// cannot use \Yii::createObject($cfg). 'id' is not set!
$my = new MigrateController(null, null, $cfg_my);
$rbac = new MigrateController(null, null, $cfg_rbac);
// suppresses echo
$echo = function ($c) {
ob_start();
$c();
return ob_get_clean();
};
$do = ['up','down'];
$do = $do[1];
try {
ob_start();
//1. init migration table. better way?
$echo(function() use (&$rbac) { $rbac->actionHistory(1); });
if ($do == 'up') {// UP ALL
//2. check available migrations
// --yii2 rbac
echo $mgs = $echo(function() use (&$rbac) { $rbac->actionNew(); });
$mgs = explode("\n", $mgs);
if (preg_match('/^Found [\d] new migration[s]{0,1}:$/', $mgs[0])) { //NEW: apply by number
$num = count($mgs) - 1;
$rbac->actionUp($num);
}
// --my schema
echo $mgs = $echo(function() use (&$my) { $my->actionNew(); });
$mgs = explode("\n", $mgs);
if (preg_match('/^Found [\d] new migration[s]{0,1}:$/', $mgs[0])) { //NEW: apply by number
$num = count($mgs) - 1;
$my->actionUp($num);
}
} else { // DOWN ALL
//2. check installed migrations in reverse order
// --my schema
$mgs = $echo(function() use (&$my) { $my->actionHistory(); });
$mgs = explode("\n", $mgs);
if (preg_match('/^Showing the last [\d] applied migration[s]{0,1}:$/', $mgs[0])) { //NEW: apply by number
$my->actionHistory();
$num = count($mgs) - 1; //PROBLEM! cannot realise migration source!
$num = 2; // i have 2 migrations
$my->actionDown($num);
}
// --yii2 rbac
$mgs = $echo(function() use (&$rbac) { $rbac->actionHistory(); });
$mgs = explode("\n", $mgs);
if (preg_match('/^Showing the last [\d] applied migration[s]{0,1}:$/', $mgs[0])) { //NEW: apply by number
$num = count($mgs) - 1;
$num = 1; // delete anything left
$rbac->actionDown('all');
}
}
echo '<br>-----------------------------<br>';
echo $rbac->actionHistory();
} catch (Exception $e) {
echo $e->getCode().':'.$e->getMessage();
}
catch (\Exception $e) {
echo $e->getCode().':'.$e->getMessage();
} finally {
$ob = ob_get_clean();
echo str_replace("\n", "<br/>", $ob);
}
die;
}
This works for me! Would would guys like me to add this as a pull request to the docs? Or should this be part of the Yii2 core framework?
namespace common\components;
use Yii;
use yii\base\Component;
use yii\console\Application;
class General extends Component
{
/**
* Create and return an application instance
* if the console app doesn't exist we create a new instance
* otherwise, it returns the existing instance
*
* @return null|\yii\base\Module|Application
*/
public static function switchToConsoleApp()
{
$config = self::getConsoleConfig();
if (!$consoleApp = Yii::$app->getModule($config['id']))
$consoleApp = new Application($config);
// assuming that switching apps only happens when making console commands through the web app,
// we have to redefine STDOUT to trick the console output into going straight to the web output
define('STDOUT', fopen('php://output', 'w'));
return $consoleApp;
}
public static function runConsoleActionFromWebApp($action, $params = [])
{
$webApp = Yii::$app;
$consoleApp = self::switchToConsoleApp();
$result = ($consoleApp->runAction($action, $params) == \yii\console\Controller::EXIT_CODE_NORMAL);
Yii::$app = $webApp;
return $result;
}
public static function getConsoleConfig()
{
return ArrayHelper::merge(
require(Yii::getAlias('@common/config/main.php')),
require(Yii::getAlias('@common/config/main-local.php')),
require(Yii::getAlias('@console/config/main.php')),
require(Yii::getAlias('@console/config/main-local.php'))
);
}
}
// example usage within any web controller
SiteController extends \yii\web\Controller
{
public function actionRbacLoad() {
General::runConsoleActionFromWebApp('rbac/load');
}
public function actionMigrate() {
General::runConsoleActionFromWebApp('migrate', ['migrationPath' => '@console/migrations/', 'interactive' => false]);
}
}
I'm writing an step by step installer script which in one step it tries to run some database migrations located in a folder. To do this I create a console Yii application and use
runAction()
method to run migrations. here is the code:everything was fine until I upgraded the framework from 2.0.0 to 2.0.2, now these fatal errors occur:
I tested it with Yii 2.0.1 and it didn't work with that either. Yii 2.0.0 is fine though. I'm on MAMP environment with php 5.4.30, but tested it on Ubuntu and same error occurred. Am I missing something or there is an issue hiding somewhere?