سؤال

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

هل كانت مفيدة؟

المحلول 2

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.

نصائح أخرى

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', '.*');

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).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top