【问题标题】:Laravel 6-7 How Can I Override/Change a Vendor Class?Laravel 6-7 如何覆盖/更改供应商类?
【发布时间】:2020-07-05 14:10:51
【问题描述】:

我最近遇到了一个问题,我需要更改 Laravel 的供应商文件之一以获得所需的结果。 该文件是vendor/laravel/framework/Illuminate/Routing/CompileRouteCollection.php

在该文件中,需要更改一个函数。

protected function requestWithoutTrailingSlash(Request $request)
{
    $trimmedRequest = Request::createFromBase($request);

    $parts = explode('?', $request->server->get('REQUEST_URI'), 2);

    $trimmedRequest->server->set(
        'REQUEST_URI', rtrim($parts[0], '/').(isset($parts[1]) ? '?'.$parts[1] : '')
    );

    return $trimmedRequest;
}

更具体地说,这部分:rtrim($parts[0], '/')。需要删除最后的 / 才能使我的部分路线正常工作。

我尝试在内部创建自己的自定义类:App\Helpers\CompiledRouteCollection.php。我在其中复制了上面列出的函数并进行了自己的更改。

App\Helpers\CompiledRouteCollection.php

namespace App\Helpers;

use Illuminate\Http\Request;

class CompiledRouteCollection extends \Illuminate\Routing\CompiledRouteCollection
{
    protected function requestWithoutTrailingSlash(Request $request)
    {
        $trimmedRequest = Request::createFromBase($request);

        $parts = explode('?', $request->server->get('REQUEST_URI'), 2);

        $trimmedRequest->server->set(
            'REQUEST_URI', rtrim($parts[0], '').(isset($parts[1]) ? '?'.$parts[1] : '')
        );

        return $trimmedRequest;
    }
}

然后我进入 App\Providers\AppServiceProvider 并在 register 函数中运行它。

public function register()
{
    $loader = AliasLoader::getInstance();
    $loader->alias('App\Helpers\CompiledRouteCollection', 'Illuminate\Routing\CompiledRouteCollection');
}

但是什么也没发生。

更新 1

我将别名更改为:

$loader = AliasLoader::getInstance();
$loader->alias('Illuminate\Routing\CompiledRouteCollection', 'App\Helpers\CompiledRouteCollection');

但现在在我的 Helper 类中,它在尝试访问任何页面时都会返回此错误: Class 'Illuminate\Routing\CompiledRouteCollection' not found

感谢任何有兴趣帮助我的人。如果您需要更多信息,请告诉我!

如果您需要更多上下文,我在 laravel/framework 上打开了一个问题,其中包含完整的背景说明 here

【问题讨论】:

    标签: php laravel composer-php laravel-6 laravel-7


    【解决方案1】:

    在别名中第一个参数必须是供应商类,之后是覆盖类

    public function register()
    {
        $loader = AliasLoader::getInstance();
        $loader->alias(CompileRouteCollection::class, CompiledRouteCollection::class);
    }
    

    public function register()
    {
        $loader = AliasLoader::getInstance();
        $loader->alias('Illuminate/Routing/CompileRouteCollection', 'App\Helpers\CompiledRouteCollection');
    }
    
    

    如你所愿))

    【讨论】:

    • 如果没有变化并不代表它没有工作,把dd('it works)放在你的CompiledRouteCollection中,然后拨打电话
    • 刚刚尝试了将供应商类放在别名中的方法。它现在返回未找到扩展类。
    • CompileRouteCollection::class在第一个varint中制作类似你永远不会遇到这样的问题)
    • 为什么不赞成这个答案?就论据顺序而言,它是正确的。 laravel.com/api/7.x/Illuminate/Foundation/…
    【解决方案2】:

    我改用作曲家来覆盖文件,因为我以前的方法根本不起作用。这就是我所做的。

    首先,在composer.json 文件的自动加载部分我添加了这个:

    "exclude-from-classmap": [
        "vendor\\laravel\\framework\\src\\Illuminate\\Routing\\CompiledRouteCollection.php"
    ],
    "psr-4": {
        "App\\": "app/",
        "Illuminate\\": "app/Overrides/"
    },
    

    接下来,我在 app 文件夹中创建了 Ovverides 文件夹,然后我复制了 CompiledRouteCollection.php 文件并将其粘贴到了 Ovverides 文件夹中。

    【讨论】:

    • 你有赏金跑,是吗?您是否尝试在RouteServiceProvider 中交换它?我喜欢你的作曲家解决方法,但我想要那个绿色的复选标记,伙计。拥抱!呃,嗯,现在不拥抱,没关系。
    【解决方案3】:

    尝试在您的RouteServiceProvider 而不是AppServiceProvider 中换掉它

    只是猜测,因为它是路由系统的一部分。在它到达AppServiceProvider 之前,它可能已经作为原始类被调用。

    我在https://github.com/laravel/framework/issues/32082 上查看了您的问题,我很惊讶他们不建议尝试。如果我没记错 Laravel 的请求生命周期,RouteServiceProvider可能是你的票。

    我钦佩您在寻找解决方法方面的足智多谋。

    【讨论】:

      【解决方案4】:

      根据我的经验,您可以这样做:

      1. App\Providers\AppServiceProvider 的注册函数中添加以下内容。
      public function register()
      {
          $loader = AliasLoader::getInstance();
          $loader->alias('Illuminate\Routing\CompileRouteCollection', 'App\Helpers\CompiledRouteCollection');
      }
      
      1. 像这样编辑作曲家文件。
      "psr-4": {
          "App\\": "app/",
          "Illuminate\\Routing\\": "app\\Helpers\\"
      },
      

      然后请compose install 运行该项目。

      【讨论】:

        【解决方案5】:

        您可以在 composer 中覆盖供应商类

        您需要编辑您的 composer.json 文件并在自动加载部分中添加两行额外的行以换出实现。

        "exclude-from-classmap": ["vendor/packagename/diraction/to/File.php"],
        "files": ["app/Overrides/File.php"]
        

        第一行将排除加载原始类,第二行将指向具有适当命名空间的原始类以供您的实现使用。

        然后您需要创建app/Overrides 文件夹并在其中复制File.php(您要覆盖的文件)。

        最后一步是运行:

        composer dump-autoload
        

        你很高兴!

        【讨论】:

          猜你喜欢
          • 2018-06-04
          • 1970-01-01
          • 1970-01-01
          • 2019-04-05
          • 2019-02-20
          • 2018-04-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多