8

Using the Blade service container I want to take a string with markers in it and compile it down so it can be added to the blade template, and further interpolated.

So I have an email string (abridge for brevity) on the server retrieved from the database of:

<p>Welcome {{ $first_name }},</p>

And I want it to interpolated to

<p>Welcome Joe,</p> 

So I can send it to a Blade template as $content and have it render all the content and markup since Blade doesn't interpolate twice and right now our templates are client made and stored in the database.

Blade::compileString(value) produces <p>Welcome <?php echo e($first_name); ?>,</p>, but I can't figure out how to get $first_name to resolve to Joe in the string using the Blade API, and it doesn't do it within the Blade template later. It just displays it in the email as a string with PHP delimiters like:

<p>Welcome <?php echo e($first_name); ?>,</p>

Any suggestions?

1 Answer 1

15

This should do it:

// CustomBladeCompiler.php

use Symfony\Component\Debug\Exception\FatalThrowableError;

class CustomBladeCompiler
{   
    public static function render($string, $data)
    {
        $php = Blade::compileString($string);

        $obLevel = ob_get_level();
        ob_start();
        extract($data, EXTR_SKIP);

        try {
            eval('?' . '>' . $php);
        } catch (Exception $e) {
            while (ob_get_level() > $obLevel) ob_end_clean();
            throw $e;
        } catch (Throwable $e) {
            while (ob_get_level() > $obLevel) ob_end_clean();
            throw new FatalThrowableError($e);
        }

        return ob_get_clean();
    }
}

Usage:

$first_name = 'Joe';
$dbString = '<p>Welcome {{ $first_name }},</p>';

return CustomBladeCompiler::render($dbString, ['first_name' => $first_name]);

Thanks to @tobia on the Laracasts forums.

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

7 Comments

I used a temporary blade template instead of buffer, but this way is much better)
if I use a @foreach the $php value contains this: $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $app): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ;.... (where $__env is not accessable) any idea.
@SimonFakir $path = resource_path('views/' . $id . '.blade.php'); file_put_contents($path,$needCompileString);
@PaulBasenko say much better but temporary blades good choice if need all blade functionalitiy, foreach not working go rewriting code:(. $output = view("temp." . $id , $yourData)->render(); Enjoy.
How can I use this with Mailables ?
|

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.