3

EDIT: The code snippet below, where view takes an array ['template' => 'my template'] as the first argument is a feature of wpb/string-blade-compiler which is overriding the native laravel functionality.

I have a directive registered in AppServiceProvider::boot:

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

It works perfectly when I use file based templates saved as resources/views/something.blade.php and used return view('something', $data) in my Controller::action.

However when I try:

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());
}

And try and use templates from a string, the directive isn't loaded. No errors, no nothing.

Does anyone with an intimate knowledge of laravel know the difference with these two contexts? I would have thought they'd yield the same result but do not. I'm struggling to understand the laravel architecture to unravel this one. Thanks.

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

5
  • Have you tried using View::make() instead? Commented Oct 3, 2016 at 19:44
  • @Derek, yup. Both yield same results = working view, less my directive. Commented Oct 3, 2016 at 19:46
  • What version of laravel are you using? Commented Oct 3, 2016 at 19:47
  • 1
    @Derek, added snippet from composer.json above. Commented Oct 3, 2016 at 19:50
  • Alright, I did some testing and I believe I may have the answer you want, posting answer.. Commented Oct 3, 2016 at 20:56

1 Answer 1

2

So, I did a little testing on my own server and came up with a solution:

My condensed code in a singe route:

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;

});

And the directive, if you care to see it:

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

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

There is like little to no documentation on this, so debugging could be a hassle, but I do know if you would like to pass in more variables to the string, it would look like this:

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;

});

Finally, a simple function you can place in your controller:

// 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;
}

Let me know if you have any questions!

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your answer. I realise "wpb/string-blade-compiler" was overriding the default laravel behaviour that doesn't support strings. I need to edit the question to clarify this. Laravel doesn't support blade templates as strings. Natively it compiles vanilla php to a cache file and includes it. Your solution, using eval, is an alternative to writing files. Both use output buffering.
@Simon - with my solution, it returns the finished HTML - is this not what you were looking for?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.