31

如何从字符串而不是视图文件编译刀片模板,如下面的代码:

<?php
$string = '<h2>{{ $name }}</h2>';
echo Blade::compile($string, array('name' => 'John Doe')); 
?>

http://paste.laravel.com/ujL

4

7 回答 7

21

我通过扩展 BladeCompiler 找到了解决方案。

<?php namespace Laravel\Enhanced;

use Illuminate\View\Compilers\BladeCompiler as LaravelBladeCompiler;

class BladeCompiler extends LaravelBladeCompiler {

    /**
     * Compile blade template with passing arguments.
     *
     * @param string $value HTML-code including blade
     * @param array $args Array of values used in blade
     * @return string
     */
    public function compileWiths($value, array $args = array())
    {
        $generated = parent::compileString($value);

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

        // We'll include the view contents for parsing within a catcher
        // so we can avoid any WSOD errors. If an exception occurs we
        // will throw it out to the exception handler.
        try
        {
            eval('?>'.$generated);
        }

        // If we caught an exception, we'll silently flush the output
        // buffer so that no partially rendered views get thrown out
        // to the client and confuse the user with junk.
        catch (\Exception $e)
        {
            ob_get_clean(); throw $e;
        }

        $content = ob_get_clean();

        return $content;
    }

}
于 2013-06-07T10:48:38.687 回答
17

对上述脚本的小修改。您可以在任何类中使用此函数,而无需扩展 BladeCompiler 类。

public function bladeCompile($value, array $args = array())
{
    $generated = \Blade::compileString($value);

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

    // We'll include the view contents for parsing within a catcher
    // so we can avoid any WSOD errors. If an exception occurs we
    // will throw it out to the exception handler.
    try
    {
        eval('?>'.$generated);
    }

    // If we caught an exception, we'll silently flush the output
    // buffer so that no partially rendered views get thrown out
    // to the client and confuse the user with junk.
    catch (\Exception $e)
    {
        ob_get_clean(); throw $e;
    }

    $content = ob_get_clean();

    return $content;
}
于 2015-11-23T13:25:45.633 回答
5

我没有以这种方式使用刀片,但我认为编译方法只接受一个视图作为参数。

也许您正在寻找:

Blade::compileString()
于 2013-06-03T12:09:02.077 回答
5

我只是偶然发现了同样的要求!对我来说,我必须获取存储在数据库中的刀片模板并渲染它以发送电子邮件通知。

我在 laravel 5.8 中通过某种 Extending 做到了这一点\Illuminate\View\View。所以,基本上我创建了下面的类并将他命名为 StringBlade(我找不到更好的名字 atm :/)

<?php

namespace App\Central\Libraries\Blade;

use Illuminate\Filesystem\Filesystem;

class StringBlade implements StringBladeContract
{
    /**
     * @var Filesystem
    */
    protected $file;

    /**
     * @var \Illuminate\View\View|\Illuminate\Contracts\View\Factory
    */
    protected $viewer;

    /**
     * StringBlade constructor.
     *
     * @param Filesystem $file
     */
    public function __construct(Filesystem $file)
    {
        $this->file = $file;
        $this->viewer = view();
    }

    /**
     * Get Blade File path.
     *
     * @param $bladeString
     * @return bool|string
     */
    protected function getBlade($bladeString)
    {
        $bladePath = $this->generateBladePath();

        $content = \Blade::compileString($bladeString);

        return $this->file->put($bladePath, $content)
            ? $bladePath
            : false;
    }

    /**
     * Get the rendered HTML.
     *
     * @param $bladeString
     * @param array $data
     * @return bool|string
     */
    public function render($bladeString, $data = [])
    {
        // Put the php version of blade String to *.php temp file & returns the temp file path
        $bladePath = $this->getBlade($bladeString);

        if (!$bladePath) {
            return false;
        }

        // Render the php temp file & return the HTML content
        $content = $this->viewer->file($bladePath, $data)->render();

        // Delete the php temp file.
        $this->file->delete($bladePath);

        return $content;
    }

    /**
     * Generate a blade file path.
     *
     * @return string
     */
    protected function generateBladePath()
    {
        $cachePath = rtrim(config('cache.stores.file.path'), '/');
        $tempFileName = sha1('string-blade' . microtime());
        $directory = "{$cachePath}/string-blades";

        if (!is_dir($directory)) {
            mkdir($directory, 0777);
        }

        return "{$directory}/{$tempFileName}.php";
    }
}

正如您已经从上面看到的那样,以下是遵循的步骤:

  1. 首先使用 . 将刀片字符串转换为 php 等效项\Blade::compileString($bladeString)
  2. 现在我们必须将它存储到一个物理文件中。对于此存储,使用框架缓存目录 -storage/framework/cache/data/string-blades/
  3. 现在我们可以请求\Illuminate\View\Factory本地方法“file()”来编译和渲染这个文件。
  4. 立即删除临时文件(在我的情况下,我不需要保留 php 等效文件,对你来说可能也一样)

最后,我在作曲家自动加载的文件中创建了一个外观,以便于使用,如下所示:

<?php

if (! function_exists('string_blade')) {

    /**
     * Get StringBlade Instance or returns the HTML after rendering the blade string with the given data.
     *
     * @param string $html
     * @param array $data
     * @return StringBladeContract|bool|string
     */
    function string_blade(string $html, $data = [])
    {
        return !empty($html)
            ? app(StringBladeContract::class)->render($html, $data)
            : app(StringBladeContract::class);
    }
}

现在我可以从下面的任何地方调用它:

<?php

$html = string_blade('<span>My Name is {{ $name }}</span>', ['name' => 'Nikhil']);

// Outputs HTML
// <span>My Name is Nikhil</span>

希望这可以帮助某人,或者至少可以激发某人以更好的方式重写。

干杯!

于 2019-02-28T17:23:40.657 回答
4

这是一个老问题。但我找到了一个使工作更容易的包。

Laravel Blade String Compiler从字符串值渲染刀片模板。查看有关如何安装软件包的文档。

这是一个例子:

$template = '<h1>{{ $name }}</h1>';  // string blade template

return view (['template' => $template], ['name' => 'John Doe']);

注意:该软件包现已更新以支持 Laravel 6。

于 2016-09-19T20:38:21.727 回答
3

我知道它很老的线程,但今天的要求也是一样的。

以下是我在 Laravel 5.7 上解决此问题的方法(但这将适用于任何高于版本 5 的 laravel 版本),我使用从该线程和其他几个线程中获得的知识来使其正常工作(将保留所有线程的链接最后,如果这也有助于投票)

我将此添加到我的 helper.php 中(我使用此技术将帮助程序添加到我的项目中,但您也可以直接使用此函数)

if (! function_exists('inline_view')) {
    /**
     * Get the evaluated view contents for the given blade string.
     *
     * @param  string  $view
     * @param  array   $data
     * @param  array   $mergeData
     * @return \Illuminate\View\View|\Illuminate\Contracts\View\Factory
     */
    function inline_view($view = null, $data = [], $mergeData = [])
    {
        /* Create a file with name as hash of the passed string */
        $filename = hash('sha1', $view);

        /* Putting it in storage/framework/views so that these files get cleared on `php artisan view:clear*/
        $file_location = storage_path('framework/views/');
        $filepath = storage_path('framework/views/'.$filename.'.blade.php');

        /* Create file only if it doesn't exist */
        if (!file_exists($filepath)) {
            file_put_contents($filepath, $view);
        }
        
        /* Add storage/framework/views as a location from where view files can be picked, used in make function below */
        view()->addLocation($file_location);

        /* call the usual view helper to render the blade file created above */
        return view($filename, $data, $mergeData);
    }
} 

用法和 laravel 的 helper 完全一样view(),只是现在第一个参数是刀片字符串

            $view_string = '@if(strlen($name_html)>6)
                                <strong>{{ $name_html }}</strong>
                            @else 
                                {{$name_html}} 
                            @endif';
            return inline_view($view_string)->with('name_html', $user->name);
            return inline_view($view_string, ['name_html' => $user->name]);

参考:

  1. https://stackoverflow.com/a/31435824/4249775
  2. https://stackoverflow.com/a/33594452/4249775
于 2020-08-29T09:06:55.143 回答
1

对于仍然对此感兴趣的任何人,他们已将其添加到 Laravel 9

use Illuminate\Support\Facades\Blade;
 
return Blade::render('Hello, {{ $name }}', ['name' => 'Julian Bashir']);

https://laravel.com/docs/9.x/blade#rendering-inline-blade-templates

于 2022-02-21T05:20:30.470 回答