laravel 有没有办法从字符串编译刀片模板?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16891398/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there any way to compile a blade template from a string?
提问by Tee Plus
How can I compile a blade template from a string rather than a view file, like the code below:
如何从字符串而不是视图文件编译刀片模板,如下面的代码:
<?php
$string = '<h2>{{ $name }}</h2>';
echo Blade::compile($string, array('name' => 'John Doe'));
?>
回答by Tee Plus
I found the solution by extending BladeCompiler.
我通过扩展 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;
}
}
回答by George John
Small modification to the above script. You can use this function inside any class without extending the BladeCompiler class.
对上述脚本的小修改。您可以在任何类中使用此函数,而无需扩展 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;
}
回答by Hexodus
I'm not using blade this way but I thought that the compile method accepts only a view as argument.
我没有以这种方式使用刀片,但我认为 compile 方法只接受一个视图作为参数。
Maybe you're looking for:
也许您正在寻找:
Blade::compileString()
回答by nikhil_
I just stumbled upon the same requirement! For me, i had to fetch a blade template stored in DB & render it to send email notifications.
我只是偶然发现了同样的要求!对我来说,我必须获取存储在 DB 中的刀片模板并渲染它以发送电子邮件通知。
I did this in laravel 5.8 by kind-of Extending \Illuminate\View\View
. So, basically i created the below class & named him StringBlade (I couldn't find a better name atm :/)
我在 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";
}
}
As you can already see from the above, below are the steps followed:
正如您已经从上面看到的,下面是遵循的步骤:
- First converted the blade string to the php equivalent using
\Blade::compileString($bladeString)
. - Now we have to store it to a physicalfile. For this storage, the frameworks cache directory is used -
storage/framework/cache/data/string-blades/
- Now we can ask
\Illuminate\View\Factory
native method 'file()' to compile & render this file. - Delete the temp file immediately (In my case i didn't need to keep the php equivalent file, Probably same for you too)
- 首先使用 将刀片字符串转换为 php 等效项
\Blade::compileString($bladeString)
。 - 现在我们必须将它存储到一个物理文件中。对于此存储,使用框架缓存目录 -
storage/framework/cache/data/string-blades/
- 现在我们可以要求
\Illuminate\View\Factory
本地方法'file()'来编译和渲染这个文件。 - 立即删除临时文件(在我的情况下,我不需要保留 php 等效文件,对你来说可能也一样)
And Finally i created a facadein a composer auto-loaded file for easy usage like below:
最后,我在 Composer 自动加载的文件中创建了一个外观,以便于使用,如下所示:
<?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);
}
}
Now i can call it from anywhere like below:
现在我可以从任何地方调用它,如下所示:
<?php
$html = string_blade('<span>My Name is {{ $name }}</span>', ['name' => 'Nikhil']);
// Outputs HTML
// <span>My Name is Nikhil</span>
Hope this helps someone or at-least maybe inspires someone to re-write in a better way.
希望这对某人有所帮助,或者至少可以激发某人以更好的方式重写。
Cheers!
干杯!
回答by Raghavendra N
It's a old question. But I found a package which makes the job easier.
这是一个老问题。但是我找到了一个可以使工作更轻松的软件包。
Laravel Blade String Compilerrenders the blade templates from the string value. Check the documentation on how to install the package.
Laravel Blade String Compiler根据字符串值渲染刀片模板。查看有关如何安装软件包的文档。
Here is an example:
下面是一个例子:
$template = '<h1>{{ $name }}</h1>'; // string blade template
return view (['template' => $template], ['name' => 'John Doe']);
Note: The package is now updated to support till Laravel 6.
注意:该包现已更新以支持 Laravel 6。