问题
How can I render an string which contains blade syntax?
View::make('directory.file-name')->with('var', $var); // Usual usage
View::render('{{$var}}')->with('var', $var); // Like this for Example
I use wrote an script that produces blade syntax and I want to give it's output directly to blade engine if possible.
Thanks
回答1:
Hope this helps,
https://github.com/TerrePorter/StringBladeCompiler
This is a fork of the next link that removes the db model requirement and replaces it with a array that requires three required keys ('template', 'cache_key', 'updated_at') instead of the full Eloquent model.
https://github.com/Flynsarmy/laravel-db-blade-compiler
This uses a Eloquent model to get the template.
回答2:
I don't recommend to use 'Blade::compileString' as it won't fully render PHP as View does.
This is a working version of my actual Blade string renderer. You may use it for database content or any string you want to render as you would with a .blade.php file. Tested with Laravel 4. Fully commented and explained.
Do not forget to create the 'cache' folder inside views
This function generates the fileview
public function generateViewFile($html, $url, $updated_at)
{
// Get the Laravel Views path
$path = \Config::get('view.paths.0');
// Here we use the date for unique filename - This is the filename for the View
$viewfilename = $url."-".hash('sha1', $updated_at);
// Full path with filename
$fullfilename = $path."/cache/".$viewfilename.".blade.php";
// Write the string into a file
if (!file_exists($fullfilename))
{
file_put_contents($fullfilename, $html);
}
// Return the view filename - This could be directly used in View::make
return $viewfilename;
}
This is the ContentController route renderer
public function getIndex($uri = false)
{
// In my real ContentController I get the page from the DB here
//
// $page = Page::findByUrl($uri);
// $content = $page->content;
// $updated_at = $page->updated_at;
// $url = $page->url;
$content = '<h1>This is the page to render</h1>';
$updated_at = '2015-07-15 02:40:55';
$url = '/blog/new-article';
// Will write the file when needed and return the view filename
$filename = $this->generateViewFile($content, $url, $updated_at);
// Fully render and output the content
return View::make('cache/'.$filename);
}
Handler at the end of the routes.php. Even if this is not required, this is to present a fully testeable solution.
Route::get('{all}', 'ContentController@getIndex')->where('all', '.*');
回答3:
I just made it for Laravel 4.2 as Linux-only version (which uses shm to create temporary files). It should work in another OS but through usual temporary files (a bit slower).
<?php
class FilesDeletionQueue {
protected $files = [];
public function add($filename) {
$this->files[] = $filename;
}
public function flush() {
$result = true;
foreach ($this->files as $filename) {
if (@unlink($filename) === false) {
$result = false;
}
}
return $result;
}
}
class Helpers {
static public function viewFromStr($tplName, $pageContent, array $data) {
global $app;
// Try to create temporary blade template file in shm memory,
// if fails, create as usual temporary file.
$tempname = tempnam('/run/shm/', 'laravel_blade');
if (@file_put_contents($tempname, $pageContent) === false) {
$tempname = tempnam(storage_path(), 'laravel_blade');
if (@file_put_contents($tempname, $pageContent) === false) {
throw new \Exception("Cannot create {$tempname} in " . __METHOD__);
}
}
// Create template from shm memory file.
$resolver = $app['view.engine.resolver'];
$finder = $app['view.finder'];
$env = new \Illuminate\View\Factory($resolver, $finder, $app['events']);
$env->setContainer($app);
$pageView = new \Illuminate\View\View(
$env,
$env->getEngineResolver()->resolve('blade'),
$tplName,
$tempname,
$data
);
$env->callCreator($pageView);
try {
$fdq = App::make('files_deletion_queue');
} catch (\Exception $e) {
App::singleton('files_deletion_queue', function() {
return new FilesDeletionQueue();
});
$fdq = App::make('files_deletion_queue');
App::shutdown(function() {
App::make('files_deletion_queue')->flush();
});
}
// Add tempname to list of files to be deleted when application ends.
$fdq->add($tempname);
return $pageView;
}
}
Then you can use it like this:
$pageView = Helpers::viewFromStr('content', $pageContent, $this->data);
$this->layout->with('content', $pageView)
->with('menus', $this->menus )
->with('page',$this->data);
instead of:
/*
$this->layout->nest('content',"pages.template.{$row->filename}",$this->data)
->with('menus', $this->menus )
->with('page',$this->data);
*
*/
It's really sad that recommended methods cannot load blade files from arbitrary OS pathes and there's no ready out of box support for compiling from RAM (I heard it's much easier for twig).
来源:https://stackoverflow.com/questions/21556981/render-blade-from-string-instead-of-file