有谁知道如何用字符串来传入 Blade 模板吗,即不是传入模板路径,而是传入字符串?

有谁知道如何用字符串来传入Blade模板吗,即不是传入模板路径,而是传入字符串

《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
leo
最佳答案
<?php
/**
 * Created by PhpStorm.
 * User: leo108
 * Date: 2018/4/22
 * Time: 15:15
 */

namespace App;

use Exception;
use Illuminate\View\Compilers\BladeCompiler;
use Illuminate\View\Engines\PhpEngine;
use Throwable;

class StringCompilerEngine extends PhpEngine
{
    /**
     * @var BladeCompiler
     */
    protected $compiler;

    /**
     * StringCompilerEngine constructor.
     * @param BladeCompiler $compiler
     */
    public function __construct(BladeCompiler $compiler)
    {
        $this->compiler = $compiler;
    }

    public function renderString($__tpl, $__data = [])
    {
        $__compiled = $this->compiler->compileString($__tpl);
        $obLevel    = ob_get_level();
        ob_start();
        extract($__data, EXTR_SKIP);
        try {
            eval('?> '.$__compiled);
        } catch (Exception $e) {
            $this->handleViewException($e, $obLevel);
        } catch (Throwable $e) {
            $this->handleViewException(new FatalThrowableError($e), $obLevel);
        }

        return ltrim(ob_get_clean());
    }
}

file

7年前 评论
讨论数量: 17
leo
<?php
/**
 * Created by PhpStorm.
 * User: leo108
 * Date: 2018/4/22
 * Time: 15:15
 */

namespace App;

use Exception;
use Illuminate\View\Compilers\BladeCompiler;
use Illuminate\View\Engines\PhpEngine;
use Throwable;

class StringCompilerEngine extends PhpEngine
{
    /**
     * @var BladeCompiler
     */
    protected $compiler;

    /**
     * StringCompilerEngine constructor.
     * @param BladeCompiler $compiler
     */
    public function __construct(BladeCompiler $compiler)
    {
        $this->compiler = $compiler;
    }

    public function renderString($__tpl, $__data = [])
    {
        $__compiled = $this->compiler->compileString($__tpl);
        $obLevel    = ob_get_level();
        ob_start();
        extract($__data, EXTR_SKIP);
        try {
            eval('?> '.$__compiled);
        } catch (Exception $e) {
            $this->handleViewException($e, $obLevel);
        } catch (Throwable $e) {
            $this->handleViewException(new FatalThrowableError($e), $obLevel);
        }

        return ltrim(ob_get_clean());
    }
}

file

7年前 评论

不明白什么意思

7年前 评论

@Littlesqx 不是指定模板路径,而是指定模板字符串内容

7年前 评论

你的意思是不通过 blade 模板渲染,直接返回字符串吗?

7年前 评论

@Littlesqx 不是,就是要通过Blade模板渲染,但是不是通过指定模板路径,而是指定模板字符串内容

7年前 评论

@ 为什么要这样做?一个模板/页面内容这么多,不分层,不会觉得很臃肿吗?

7年前 评论

@Littlesqx 部分模板,比如说邮件发送内容

7年前 评论

那也一样呀。也通过路径不是很好吗?渲染后的内容使用 $view->render() 可获取

7年前 评论

邮件模板我想在后台可以轻松编辑呢?

7年前 评论

@ 如果只能通过路径的话,我实现这个功能就不方便了

7年前 评论
leo
<?php
/**
 * Created by PhpStorm.
 * User: leo108
 * Date: 2018/4/22
 * Time: 15:15
 */

namespace App;

use Exception;
use Illuminate\View\Compilers\BladeCompiler;
use Illuminate\View\Engines\PhpEngine;
use Throwable;

class StringCompilerEngine extends PhpEngine
{
    /**
     * @var BladeCompiler
     */
    protected $compiler;

    /**
     * StringCompilerEngine constructor.
     * @param BladeCompiler $compiler
     */
    public function __construct(BladeCompiler $compiler)
    {
        $this->compiler = $compiler;
    }

    public function renderString($__tpl, $__data = [])
    {
        $__compiled = $this->compiler->compileString($__tpl);
        $obLevel    = ob_get_level();
        ob_start();
        extract($__data, EXTR_SKIP);
        try {
            eval('?> '.$__compiled);
        } catch (Exception $e) {
            $this->handleViewException($e, $obLevel);
        } catch (Throwable $e) {
            $this->handleViewException(new FatalThrowableError($e), $obLevel);
        }

        return ltrim(ob_get_clean());
    }
}

file

7年前 评论

@leo 你为啥要用app函数来调用类,而不是自己实例化

7年前 评论

@leo 666,,马克,说不定什么时候用的着

7年前 评论

TP5中内置的方法好像是把模板写入到缓存文件中,然后统一从缓存去读取。

7年前 评论

不知道Laravel能不能也用这个办法,这样会快点。现在这样要用Eval

7年前 评论
leo

@ 做人不要太懒,我已经把核心的东西写出来,缓存什么的也就几行代码的事,自己写写没坏处

7年前 评论
jcc123

@leo 返回 ajax 请求html模板数据很方便。

7年前 评论

@leo 试了一下,是可以的,但是如果用到了blade 里的@if @foreach 模板里就会渲染到$__env 运行后,由于$__env 没有定义所以报错了。想问一下这个应该怎么处理。

经过查看源码得知,视图在实例化 Illuminate\View\Factory 类时,已经给变量$__env 传值了.所以问题也就解决了.

Illuminate\View\Factory

    /**
     * Create a new view factory instance.
     *
     * @param  \Illuminate\View\Engines\EngineResolver  $engines
     * @param  \Illuminate\View\ViewFinderInterface  $finder
     * @param  \Illuminate\Contracts\Events\Dispatcher  $events
     * @return void
     */
    public function __construct(EngineResolver $engines, ViewFinderInterface $finder, Dispatcher $events)
    {
        $this->finder = $finder;
        $this->events = $events;
        $this->engines = $engines;
        $this->share('__env', $this);
    }

在你这个类里应该添加上这个实例就可以了

public function renderString($__tpl, $__data = [])
    {
        // view() 可以用其它 只是简要说明一下这个解决的方法
        $__data = array_merge(['__env'=>view()],$__data);
        $__compiled = $this->compiler->compileString($__tpl);
        $obLevel    = ob_get_level();
        ob_start();
        extract($__data, EXTR_SKIP);
        try {
            eval('?> '.$__compiled);
        } catch (Exception $e) {
            $this->handleViewException($e, $obLevel);
        } catch (Throwable $e) {
            $this->handleViewException(new FatalThrowableError($e), $obLevel);
        }
        return ltrim(ob_get_clean());
    }
4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!