Laravel 从字符串加载模板时,Blade 指令未执行

Laravel Blade Directives not executing when template loaded from string

编辑:下面的代码片段,其中 view 将数组 ['template' => 'my template'] 作为第一个参数是 wpb/string-blade-compiler 的一个特征正在覆盖本机 laravel 功能。

我在 AppServiceProvider::boot 中注册了一个指令:

public function boot()
{
    Blade::directive('hello', function($expression) {
        return "<?php echo 'Hello world'; ?>";
    });
}

当我使用基于文件的模板保存为 resources/views/something.blade.php 并在我的 Controller::action 中使用 return view('something', $data) 时,它工作得很好。

但是当我尝试时:

try {
  return view(['template' => $template], $data)->render();
} catch(\ErrorException $ex) {
  preg_match('/Undefined variable: (.+?)\s/', $ex->getMessage(), $matches);
  if ($matches) {
    return sprintf('Template: variable {{ $%s }} is invalid', $matches[1]);
  }
  return sprintf('%s: %s', $attribute, $ex->getMessage());
}

并尝试使用字符串中的模板,指令未加载。没有错误,什么都没有。

有没有对laravel有深入了解的人知道这两种情况的区别?我原以为他们会产生相同的结果,但事实并非如此。我正在努力理解 laravel 架构来解开这个问题。谢谢。

composer.json:

"require": {
    "php": ">=5.5.9",
    "laravel/framework": "5.2.*",
    "laravelcollective/html": "^5.2",
    "maatwebsite/excel": "^2.1",
    "sofa/eloquence": "^5.2",
    "wpb/string-blade-compiler": "^3.2",
    "doctrine/dbal": "^2.5",
    "davejamesmiller/laravel-breadcrumbs": "^3.0"
}

PHP 5.6

所以,我在自己的服务器上做了一些测试,想出了一个解决方案:

我在单一路线中的​​压缩代码:

Route::get('/test', function () {

    $template = Blade::compileString('@hello(derek) !');

    ob_start();

    try {

        eval('?>' . $template);

    } catch (\Exception $e) {

        ob_get_clean(); throw $e;

    }

    $content = ob_get_clean();

    return $content;

});

还有指令,如果你想看的话:

public function boot()
    {
        //
        Blade::directive('hello', function($d) {

            return "<?php echo \"Hello {$d}\"; ?>";
        });
    }

几乎没有关于这方面的文档,因此调试可能很麻烦,但我知道如果您想将更多变量传递给字符串,它看起来像这样:

Route::get('/test2', function () {

    $args = ['name' => 'derek'];

    $template = Blade::compileString('@hello($name) !');

    ob_start() and extract($args, EXTR_SKIP);

    try {

        eval('?>' . $template);

    } catch (\Exception $e) {

        ob_get_clean(); throw $e;

    }

    $content = ob_get_clean();

    return $content;

});

最后,您可以在控制器中放置一个简单的函数:

// way to call:

$this->strView('@hello($name)', ['name' => 'Tom Riddle']);

public function strView($view, $args) {
    $template = Blade::compileString($view);

    ob_start() and extract($args, EXTR_SKIP);

    try {

        eval('?>' . $template);

    } catch (\Exception $e) {

        ob_get_clean(); throw $e;

    }

    $content = ob_get_clean();

    return $content;
}

如果您有任何问题,请告诉我!