您好,我正在尝试将 Yii2 应用程序部署到 Google App Engine Standard(而非 Flex)。
标准环境不允许后台任务或popen()
,甚至不允许写入php://stdout
。此外,GAE Cron 作为队列任务似乎使用 http 与其他服务进行通信。因此,我试图找出一种通过 Web 服务包装我的控制台应用程序的方法,我将限制访问该 Web 服务仅供实习生使用。我的尝试是以下操作:
public function actionMigrateTest()
{
/**
* GAE use
* https://cloud.google.com/appengine/docs/standard/php/googlestorage/
*/
// defined('STDOUT') or define('STDOUT', fopen('gs://stdout0/stdout', 'w'));
// defined('STDERR') or define('STDERR', fopen('gs://stdout0/stderr', 'w'));
/**
* local use
*/
defined('STDIN') or define('STDIN', fopen('php://stdin', 'r'));
defined('STDOUT') or define('STDOUT', fopen('php://stdout', 'w'));
defined('STDERR') or define('STDERR', fopen('php://stderr', 'w'));
$migration = new \yii\console\controllers\MigrateController('migrate', Yii::$app);
$status = $migration->runAction('up', ['migrationPath' => '@app/migrations/', 'interactive' => false]);
fclose(\STDOUT);
fclose(\STDERR);
}
效果很好,并且在取消注释顶行以写入 GAE 存储而不是 php://stdout
后执行脚本。当我发现写入该文件的响应类似于以下内容时,没有问题:
Yii Migration Tool (based on Yii v2.0.15.1)
No new migrations found. Your system is up-to-date.
问题是当控制台任务执行时,响应类似于:
...
...
*** applying m180206_052910_create_variant_value_table
*** applied m180206_052910_create_variant_value_table (time: 0.129s)
15 migrations were applied.
Migrated up successfully.
在该成功的脚本之后,会出现以下错误(在 GAE 中,就像在我的本地环境中一样):
An Error occurred while handling another error:
exception 'yii\web\HeadersAlreadySentException' with message 'Headers already sent in /Users/salem/Sites/kt/shell55/vendor/yiisoft/yii2/db/Migration.php on line 591.' in /Users/salem/Sites/kt/shell55/vendor/yiisoft/yii2/web/Response.php:366
Stack trace:
#0 /Users/salem/Sites/kt/shell55/vendor/yiisoft/yii2/web/Response.php(339): yii\web\Response->sendHeaders()
#1 /Users/salem/Sites/kt/shell55/vendor/yiisoft/yii2/web/ErrorHandler.php(135): yii\web\Response->send()
#2 /Users/salem/Sites/kt/shell55/vendor/yiisoft/yii2/base/ErrorHandler.php(111): yii\web\ErrorHandler->renderException(Object(yii\web\HeadersAlreadySentException))
#3 [internal function]: yii\base\ErrorHandler->handleException(Object(yii\web\HeadersAlreadySentException))
#4 {main}
Previous exception:
exception 'yii\web\HeadersAlreadySentException' with message 'Headers already sent in /Users/salem/Sites/kt/shell55/vendor/yiisoft/yii2/db/Migration.php on line 591.' in /Users/salem/Sites/kt/shell55/vendor/yiisoft/yii2/web/Response.php:366
Stack trace:
#0 /Users/salem/Sites/kt/shell55/vendor/yiisoft/yii2/web/Response.php(339): yii\web\Response->sendHeaders()
#1 /Users/salem/Sites/kt/shell55/vendor/yiisoft/yii2/base/Application.php(392): yii\web\Response->send()
#2 /Users/salem/Sites/kt/shell55/web/index.php(28): yii\base\Application->run()
#3 {main}
知道为什么 header 与特定响应一起发送两次或者如何避免它吗?
最佳答案
尝试使用 ob_start()
和 ob_get_clean()
包装迁移运行,或在此方法末尾放置 exit
以防止进一步处理。
public function actionMigrateTest()
{
ob_start();
defined('STDIN') or define('STDIN', fopen('php://stdin', 'r'));
defined('STDOUT') or define('STDOUT', fopen('php://stdout', 'w'));
defined('STDERR') or define('STDERR', fopen('php://stderr', 'w'));
$migration = new \yii\console\controllers\MigrateController('migrate', Yii::$app);
$status = $migration->runAction('up', ['migrationPath' => '@app/migrations/', 'interactive' => false]);
fclose(\STDOUT);
fclose(\STDERR);
return ob_get_clean();
}
由于 Yii 2.0.14 不允许在 Controller 中回显,因此您需要返回响应。 GitHub上有几个类似的问题.
关于php - 从 Web 应用程序运行控制台时,Yii2 header 发送两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49638762/