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

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

《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
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

6年前 评论
讨论数量: 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

6年前 评论

不明白什么意思

6年前 评论

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

6年前 评论

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

6年前 评论

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

6年前 评论

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

6年前 评论

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

6年前 评论

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

6年前 评论

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

6年前 评论

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

6年前 评论
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

6年前 评论

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

6年前 评论

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

6年前 评论

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

6年前 评论

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

6年前 评论
leo

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

6年前 评论
jcc123

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

6年前 评论

@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年前 评论

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