【问题标题】:in Laravel how to change the view content at runtime each time before compilation在 Laravel 中如何在每次编译前在运行时更改视图内容
【发布时间】:2017-01-27 19:06:06
【问题描述】:

在 Laravel 5 中,我需要在编译前通过添加以下字符串在运行时修改视图内容:“@extends(foo)”

注意:更改视图文件内容不是一种选择

所以该过程将类似于(每次调用视图)

  1. 获取视图内容
  2. 通过附加“@extends(foo)”关键字来编辑视图内容
  3. 编译(渲染)视图

我尝试过使用 viewcomposer 和中间件,但没有成功

这是我的作曲家服务提供商:

namespace App\Providers;

use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;

class ComposerServiceProvider extends ServiceProvider
{
    public function boot()
    {

        View::composer('pages/*', function ($view) {

             // i want to do the following:
             // 1- find all view under directory resources/views/pages
             // 2- then add the following blade command "@extends(foo)" at the beginning of the view before compile

        });

    }


    public function register()
    {
        //
    }
}

这是我的视图中间件尝试(在中间件中我能够在编译后修改视图内容:()

<?php
namespace App\Http\Middleware;
use Closure;
class ViewMiddleware
{
    public function handle($request, Closure $next)
    {
        $response =  $next($request);
        if (!method_exists($response,'content')) {
            return $response;
        }

        $content  = "@extends('layouts.app')".$response->content();
        $response->setContent($content);
        return $response;
    }
}

谢谢

更新: 我需要完成的是根据其父目录使用布局扩展视图

例如我的视图目录有以下结构

我需要视图“controlpanel.blade.php”具有布局“layout/admin.blade.php”,因为它的父文件夹称为“admin”

-view
  |--pages
    |--admin
      |--controlpanel.blade.php
  |--layouts
     |--admin.blade.php 

【问题讨论】:

  • 你要做什么,为什么需要这个?
  • 为什么不将它们包含在您的视图中?
  • 对于大型项目,您必须考虑转向“约定优于配置”。就我而言,所有视图都有布局,所以为什么不自动化呢。如果有人没有提到“约定优于配置”,这里是维基百科的定义:约定优于配置(也称为按约定编码)是软件框架使用的一种软件设计范式,它试图减少开发人员的决策数量需要使用框架来制作,而不必失去灵活性。希望这能澄清一下,谢谢
  • 你总是想附加@extends(foo) 还是想把它放在视图中的特定位置?
  • @RaghavendraN 现在我的目标是扩展“resources/view/pages”目录下的所有视图,谢谢

标签: php laravel laravel-5 blade


【解决方案1】:

我建议使用 laravel 刀片堆栈。参考:https://laravel.com/docs/5.3/blade#stacks

Blade 允许您推送到命名堆栈,这些堆栈可以在另一个视图或布局中的其他位置呈现。

所以不要扩展“foo”,只需使用堆栈推送“foo”视图。

以下是一些链接和讨论供您参考:

What is the difference between Section and Stack in Blade?

https://laracasts.com/discuss/channels/general-discussion/blade-push-and-stack-are-they-here-to-stay

http://laraveltnt.com/blade-stack-push/

https://laracasts.com/discuss/channels/laravel/blade-stacks-pushing-into-an-included-view

【讨论】:

    【解决方案2】:

    这不是一件容易的事。你需要替换 Laravel 的刀片编译器类。它应该从当前视图路径而不是 @extends 指令中获取主布局。

    配置/app.php: 移除原来的服务商

    Illuminate\View\ViewServiceProvider::class
    

    添加你的

    App\Providers\BetterViewServiceProvider::class
    

    在你的服务提供者 app/BetterViewServiceProvider.php 中唯一重要的是调用 \App\BetterBladeCompiler 而不是原来的 Illuminate\View\Compilers\BladeCompiler,其余的方法是从父级复制的。

    <?php namespace App\Providers;
    
    
    use Illuminate\View\Engines\CompilerEngine;
    use Illuminate\View\ViewServiceProvider;
    
    class BetterViewServiceProvider extends ViewServiceProvider
    {
        /**
         * Register the Blade engine implementation.
         *
         * @param  \Illuminate\View\Engines\EngineResolver  $resolver
         * @return void
         */
        public function registerBladeEngine($resolver)
        {
            $app = $this->app;
    
            // The Compiler engine requires an instance of the CompilerInterface, which in
            // this case will be the Blade compiler, so we'll first create the compiler
            // instance to pass into the engine so it can compile the views properly.
            $app->singleton('blade.compiler', function ($app) {
                $cache = $app['config']['view.compiled'];
    
                return new \App\BetterBladeCompiler($app['files'], $cache);
            });
    
            $resolver->register('blade', function () use ($app) {
                return new CompilerEngine($app['blade.compiler']);
            });
        }
    }
    

    现在在 app\BetterBladeCompiler.php 中覆盖 compileExtends 方法并改变它的行为方式,即读取当前路径并将视图文件之前的最后一个目录插入到将由其他 Laravel 文件解释的表达式。

    <?php namespace App;
    
    use Illuminate\View\Compilers\BladeCompiler;
    use Illuminate\View\Compilers\CompilerInterface;
    
    class BetterBladeCompiler extends BladeCompiler implements CompilerInterface
    {
        /**
         * Compile the extends statements into valid PHP.
         *
         * @param  string  $expression
         * @return string
         */
        protected function compileExtends($expression)
        {
            // when you want to apply this behaviour only to views from specified directory "views/pages/"
            // just call a parent method
            if(!strstr($this->path, '/pages/')) {
                return parent::compileExtends($expression);
            }
    
            // explode path to view
            $parts = explode('/', $this->path);
    
            // take directory and place to expression
            $expression = '\'layouts.' . $parts[sizeof($parts)-2] . '\'';
    
            $data = "<?php echo \$__env->make($expression, array_except(get_defined_vars(), array('__data', '__path')))->render(); ?>";
    
            $this->footer[] = $data;
    
            return '';
        }
    
    }
    

    来自 Laravel 5.2 的代码。测试过,但不是太多。希望对你有帮助。

    【讨论】:

      【解决方案3】:

      如果您想“动态”扩展视图,这里有一种方法:

      $view = 'foo';  // view to be extended
      $template = view('home')->nest('variable_name', $view, ['data' => $data]);
      
      return $template->render();
      

      在你看来:

      @if (isset($variable_name))
          {!! $variable_name !!}
      @endif
      

      这在 Laravel 5.2 中对我有用。

      我仍然认为组织视图并让它们扩展相应的布局而不是动态传递更容易。

      编辑:

      Here 是另一种方式。但是没有签入最新版本的 Laravel。

      在你看来:

      @extends($view)

      在控制器中:

      $view = 'foo';
      return view('someview', compact('view'));
      

      【讨论】:

      • 谢谢,您的解决方案在其他情况下可能会有所帮助;但是,在我的情况下,我将无法使用您的解决方案,因为它需要配置,我需要完全避免任何配置,谢谢跨度>
      • 我没明白你说的配置是什么意思。您可以将 if 块放置在视图中的任何位置,并且只有在传递变量时才能扩展视图
      猜你喜欢
      • 1970-01-01
      • 2021-07-16
      • 2018-11-19
      • 2020-10-28
      • 1970-01-01
      • 2022-11-30
      • 2012-07-11
      • 1970-01-01
      • 2015-06-29
      相关资源
      最近更新 更多