重写 Laravel Router 类,路由能够打印,访问却提示 404

继承框架Router类,并重写apiResource方法

namespace App\Overload\Routing;
use Illuminate\Routing\Router as CoreRouter;
class Router extends CoreRouter
{
    public function apiResource($name, $controller, array $options = [])
    {
        $only = ['ls', 'detail', 'add', 'edit', 'delete','editBatch','deleteBatch'];

        if (isset($options['except'])) {
            $only = array_diff($only, (array) $options['except']);
        }

        return $this->resource($name, $controller, array_merge([
            'only' => $only,
        ], $options));
    }

重载 ResourceRegistrar类,并重写addResourceXXX的相关方法

namespace App\Overload\Routing;
use Illuminate\Routing\ResourceRegistrar as CoreResourceRegistrar;
class ResourceRegistrar extends CoreResourceRegistrar
{
    protected $resourceDefaults = ['ls', 'addPage', 'add', 'detail', 'editPage', 'edit', 'delete', 'editBatch', 'deleteBatch'];

    protected static $verbs = [
        'create' => 'addPage',
        'edit' => 'editPage'
    ];

    protected function addResourceLs($name, $base, $controller, $options)
    {
        $uri = $this->getResourceUri($name);

        $action = $this->getResourceAction($name, $controller, 'ls', $options);

        return $this->router->get($uri, $action);
    }

    protected function addResourceAddPage($name, $base, $controller, $options)
    {
        $uri = $this->getResourceUri($name).'/'.static::$verbs['create'];

        $action = $this->getResourceAction($name, $controller, 'editPage', $options);

        return $this->router->get($uri, $action);
    }

    //以下代码省略
}

替换系统的Router和ResourceRegistrar

  • AppServiceProvider中替换原来的router和ResourceRegistrar

    class AppServiceProvider extends ServiceProvider
    {
      /**
       * Register any application services.
       *
       * @return void
       */
      public function register()
      {
          $this->app->singleton('router',function($app){
              return new \App\Overload\Routing\Router($app['events'],$app);
          });
      }
    
      /**
       * Bootstrap any application services. 
       * @return void
       */
       public function boot()
       {
           $this->app->bind(\Illuminate\Routing\ResourceRegistrar::class, function (){
              return new \App\Overload\Routing\ResourceRegistrar($this->app['router']);
          });
        }
    }
  • HttpKernel中取代原来的Router

    namespace App\Http;
    use Illuminate\Foundation\Http\Kernel as HttpKernel;
    use Illuminate\Contracts\Foundation\Application;
    use App\Overload\Routing\Router;
    class Kernel extends HttpKernel
    {
      /**
       * Create a new HTTP kernel instance.
       *
       * @param  \Illuminate\Contracts\Foundation\Application  $app
       * @param  \App\Overload\Routing\Router  $router
       * @return void
       */
      public function __construct(Application $app, Router $router)
      {
          parent::__construct($app,$router);
      }
    
      //代码略。。。
    }

目前取代系统的Router完毕,并且在系统中能够正常打印被取代的Router(如有替换遗漏,请指出,谢谢!)

在web.php定义一条路由: Route::apiResource(‘/module_example’,’ExampleWeb’);
通过php artisan route:list 能够正常打印出路由
重写Laravel Router类,路由能够打印,访问却提示404

但是在浏览器访问却提示404 NOT FOUND
问:
1.请问如何才能正确替换系统的Router呢?
2.如不能替换,请问如果才能重写Router上的方法呢?谢谢!

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 4

@fangmuke 谢谢回答,试了一下macro只能扩展方法,不能重载方法。

5年前 评论
leo

我个人也是推荐使用 Macro 宏来实现你的需求,你可以选一个其他的名字,比如 myApiResource。

修改框架核心类的方法十分危险,例如某天你引入了一个第三方包,这个包正好用到了 Router 的 apiResource 方法,这个时候就有可能导致这个包没法正常使用。

5年前 评论

@leo 谢谢建议。十分赞同,没有考虑到。

5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!