如何从字符串而不是视图文件编译刀片模板,如下面的代码:
<?php
$string = '<h2>{{ $name }}</h2>';
echo Blade::compile($string, array('name' => 'John Doe'));
?>
答案 0 :(得分:16)
我通过扩展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;
}
}
答案 1 :(得分:4)
我没有以这种方式使用刀片,但我认为compile方法只接受视图作为参数。
也许你正在寻找:
Blade::compileString()
答案 2 :(得分:2)
我偶然发现了相同的要求!对我来说,我必须获取存储在数据库中的刀片模板并渲染它以发送电子邮件通知。
我在laravel 5.8中通过扩展\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";
}
}
从上面已经可以看到,下面是执行的步骤:
\Blade::compileString($bladeString)
将刀片字符串转换为等价的php。 storage/framework/cache/data/string-blades/
\Illuminate\View\Factory
本机方法'file()'编译并呈现此文件。最后,我在作曲家自动加载的文件中创建了一个 facade ,以方便使用,如下所示:
<?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>
希望这可以帮助某人或至少可以激发某人以更好的方式进行重写。
干杯!
答案 3 :(得分:2)
我知道它的线程很老,但是今天的要求也一样。
以下是我在Laravel 5.7上解决此问题的方式(但此方法适用于大于版本5的任何laravel版本),我使用了从该线程和其他几个线程获得的知识来进行此工作(将保留指向最后的所有线程(如果这也有助于投票)
我将此添加到了helper.php中(我曾使用this technique将helper添加到我的项目中,但是您也可以直接使用此功能)
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的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]);
参考:
答案 4 :(得分:1)
这是一个老问题。但我找到了一个让工作更容易的包。
Laravel Blade String Compiler从字符串值中呈现刀片模板。查看有关如何安装软件包的文档。
以下是一个例子:
$template = '<h1>{{ $name }}</h1>'; // string blade template
return view (['template' => $template], ['name' => 'John Doe']);
注意:此软件包与Laravel 5.7不兼容