gpt4 book ai didi

php - 在Laravel中如何在编译前每次在运行时更改 View 内容

转载 作者:可可西里 更新时间:2023-10-31 22:15:11 25 4
gpt4 key购买 nike

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

注意:更改 View 文件内容不是一个选项

所以这个过程会是这样的(每次调用一个 View )

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

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

这是我的 Composer 服务提供商:

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()
{
//
}
}

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

<?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;
}
}

谢谢

更新:我需要完成的是使用基于父目录的布局扩展 View

例如我的 View 目录有以下结构

我需要 View “controlpanel.blade.php”的布局为“layout/admin.blade.php”,因为它的父文件夹名为“admin”

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

最佳答案

这不是一件容易的事。您需要替换 Laravel 的 blade 编译器类。它应该从当前 View 路径而不是 @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 方法并以这种方式更改它的行为,读取当前路径并将 View 文件之前的最后一个目录插入将由其他 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 的代码。测试但不是太多。希望对您有所帮助。

关于php - 在Laravel中如何在编译前每次在运行时更改 View 内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39584227/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com