Is there any way to compile a blade template from a string?

前端 未结 6 1596
滥情空心
滥情空心 2020-11-27 07:32

How can I compile a blade template from a string rather than a view file, like the code below:

{{ $name }}\';
echo          


        
6条回答
  •  鱼传尺愫
    2020-11-27 07:57

    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.

    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 :/)

    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:

    1. First converted the blade string to the php equivalent using \Blade::compileString($bladeString).
    2. Now we have to store it to a physical file. For this storage, the frameworks cache directory is used - storage/framework/cache/data/string-blades/
    3. Now we can ask \Illuminate\View\Factory native method 'file()' to compile & render this file.
    4. Delete the temp file immediately (In my case i didn't need to keep the php equivalent file, Probably same for you too)

    And Finally i created a facade in a composer auto-loaded file for easy usage like below:

    render($html, $data)
                : app(StringBladeContract::class);
        }
    }

    Now i can call it from anywhere like below:

    My Name is {{ $name }}', ['name' => 'Nikhil']);
    
    // Outputs HTML
    // My Name is Nikhil

    Hope this helps someone or at-least maybe inspires someone to re-write in a better way.

    Cheers!

提交回复
热议问题