从Web应用程序运行控制台时,Yii2标头发送了两次

时间:2018-04-03 20:36:09

标签: php google-app-engine yii2

您好我正在尝试将Yii2应用部署到Google App Engine Standard(非Flex)。

标准环境不允许后台任务或popen()或甚至写入php://stdout。此外,GAE Cron作为排队任务似乎使用 http 与其他服务进行通信。因此,我试图找出一种方法来通过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}

关于为什么标题会针对特定响应发送两次或者如何避免它的任何想法?

1 个答案:

答案 0 :(得分:2)

尝试使用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();
}

自2.0.14以来Yii不允许在控制器中回显,您需要返回响应。 GitHub上有几个类似的问题。