每一个你不满意的现在,都有一个你不努力的曾经。

怎么在 Laravel 中移除核心服务-视图


怎么在 Laravel 中移除核心服务-视图

1)下载一个全新的Laravel项目

composer create-project laravel/laravel=8.* laravel-demo

然后我们直接使用内置的服务运行

cd laravel-demo && php artisan serve Starting Laravel development server: http://127.0.0.1:8000

2) 因为我们要移除视图, 所以把首页的路由routes/web.php的代码修改为

    Route::get('/', function () {
        return [
            'code' => 200,
            'msg' => 'msg'
        ];
    });

3) 然后我们开始注释config/app.php中的视图提供者 Illuminate\View\ViewServiceProvider::class 再次访问首页,可以看到已经出现错误 Target class [view.engine.resolver] does not exist. 这个错误其实是 facade/ignition 这个服务提供者导致的 facade/ignition 是一个漂亮的错误页面, 它依赖视图服务, 并且是自动注册的,所以我们要做的就是不要注册它.

4) 把一下内容增加到composer.json

"extra": {
    "laravel": {
        "dont-discover": [
            "facade/ignition"
        ]
    }
},

然后运行 composer dump-auto

5)再次访问首页路由还是有错误 不过这次错误没那么好看, 因为用的是以前Laravel默认的错误页面,并且错误消息不足,我们查看一下错误日志文件storage/logs/laravel.log

\\laravel-demo\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(167): Illuminate\\Session\\Middleware\\StartSession->handle(Object(Illuminate\\Http\\Request), Object(Closure))

从日志中看到Session的启动导致的错误,不过在想这两个并没有什么关系,后面排查了一会,终于找到问题所在

<?php namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{

    ...(省略)

    protected $middlewareGroups = [
        'web' => [
            ...(省略)
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            ...(省略)
        ],

        ...(省略)
    ];

    ...(省略)
}
<?php namespace Illuminate\View\Middleware;

use Closure;
use Illuminate\Contracts\View\Factory as ViewFactory;
use Illuminate\Support\ViewErrorBag;

class ShareErrorsFromSession
{
    ...(省略)

    public function handle($request, Closure $next)
    {
        ...(省略)

        $this->view->share(
            'errors', $request->session()->get('errors') ?: new ViewErrorBag
        );

        ...(省略)

        return $next($request);
    }
}

其实是这个web中间组里的ShareErrorsFromSession, 从Session中获取错误, 然后共享到视图里, 这里就会依赖视图服务, 我们注释掉这个中间件

如果Laravel版本低的话, Illuminate\Pagination\PaginationServiceProvider::class Illuminate\Notifications\NotificationServiceProvider::class 这两个服务提供者也是依赖视图服务的,不过新版本的已经修改为延迟加载可不注释

不过这里还没完整,还有错误的处理,比如我们访问 http://127.0.0.1:8000/test 这个路由我们并没有写

会出现 Target class [view] does not exist.

当然就会出现这个错误, 因为默认的错误处理, Laravel会去找storage/views/errors/404.blade.php的视图文件(根据状态码找对应的文件)

我们开始自定义错误, 找到文件app\Exceptions\Handler.php自定义处理错误

use Illuminate\Http\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

    public function render($request, Throwable $e)
    {
        $code = 500;
        if ($e instanceof NotFoundHttpException) {
            $code = 404;
        }

        return (new Response([
            'code' => $code,
            'msg' => $e->getMessage()
        ]))->withHeaders(['Content-Type' => 'application/json']);;
    }

#原文档

Card image cap

每一个你不满意的现在,都有一个你不努力的曾经。