Laravel 6-7如何覆盖/更改供应商类?

10
我最近遇到一个问题,需要更改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中。在其中复制上述函数并进行自己的更改。
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
6个回答

10

编辑app\Providers\AppServiceProvider.php文件。 alias()方法的第一个参数必须是供应商类,其后是覆盖类:

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');
}


如果没有更改并不意味着它没有起作用,请在您的“CompiledRouteCollection”中放置“dd('it works)`”,并进行调用。 - Bohdan Petrenko
刚刚尝试了您将供应商类放在别名中的第一位的方法。现在返回扩展类未找到。 - Tyler Shannon
使用第一种变量的方式,例如 CompileRouteCollection::class,您将永远不会遇到这样的问题。 - Bohdan Petrenko
为什么要对这个答案进行踩?它是正确的,就参数顺序而言。https://laravel.com/api/7.x/Illuminate/Foundation/AliasLoader.html#method_alias - Jeremy Anderson

8

由于我的先前方法完全不起作用,我决定使用composer来覆盖文件。以下是我的做法。

首先,在composer.json文件的autoload部分中,我添加了以下内容:

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

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


你正在运行赏金任务,是吗?你试过在“RouteServiceProvider”中交换它吗?我喜欢你的Composer解决方法,但是我想要那个绿色的勾号,伙计。抱抱!啊,现在不要拥抱,算了。 - Jeremy Anderson

2

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

您需要编辑composer.json文件,并在autoload部分内添加两行额外的内容来替换实现。

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

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

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

最后一步是运行:

composer dump-autoload

你已经准备好了!


2
可能你想要使用的是 AppServiceProvider 上的 $bindings

https://laravel.com/docs/9.x/providers#the-bindings-and-singletons-properties

在这种情况下,我想重写一个包中的登录控制器中的$redirectTo变量:
class AppServiceProvider extends ServiceProvider
{
    public $bindings = [
        \Vendor\Http\Controllers\Auth\LoginController::class => \App\Http\Controllers\Auth\LoginController::class,
        ...

use Vendor\Http\Controllers\Auth\LoginController as OriginalLoginController;

class LoginController extends OriginalLoginController
{
    protected $redirectTo = '/dashboard';
}

1

尝试在你的RouteServiceProvider中替换它,而不是AppServiceProvider

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

我在https://github.com/laravel/framework/issues/32082上查看了你的问题,我很惊讶他们没有建议尝试一下。如果我正确记得Laravel的请求生命周期,RouteServiceProvider 可能 是你的救星。

我钦佩你发现解决方法的机智。


1

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

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

    然后请执行compose install命令来运行该项目。

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接