简体   繁体   English

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

[英]Laravel 6-7 How Can I Override/Change a Vendor Class?

I recently ran into a problem where I need to change one of Laravel's vendor files to get a desired result.我最近遇到了一个问题,我需要更改 Laravel 的供应商文件之一以获得所需的结果。 That file is vendor/laravel/framework/Illuminate/Routing/CompileRouteCollection.php .该文件是vendor/laravel/framework/Illuminate/Routing/CompileRouteCollection.php

Inside that file, a function needs to be changed.在该文件中,需要更改 function。

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

More specifically, this part: rtrim($parts[0], '/') .更具体地说,这部分: rtrim($parts[0], '/') That / at the end needs to be removed in order for parts of my routes to work.最后需要删除那个 / 才能使我的部分路线正常工作。

I have tried creating my own custom class inside: App\Helpers\CompiledRouteCollection.php .我尝试在内部创建自己的自定义 class: App\Helpers\CompiledRouteCollection.php In which I copy the function listed above and make my own changes.其中我复制了上面列出的 function 并进行了自己的更改。

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

Then I go into App\Providers\AppServiceProvider and I run this inside of the register function.然后我将 go 输入 App\Providers\AppServiceProvider 并在寄存器 function 中运行它。

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

But nothing happens.但是没有任何反应。

UPDATE 1更新 1

I changed my alias to this:我将别名更改为此:

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

But now in my Helper class it returns this error when trying to access any page: Class 'Illuminate\Routing\CompiledRouteCollection' not found但是现在在我的 Helper class 中,它在尝试访问任何页面时返回此错误: Class 'Illuminate\Routing\CompiledRouteCollection' not found

To anyone who is interested in helping me out thank you so much.对于任何有兴趣帮助我的人,非常感谢。 If you need more information please let me know!如果您需要更多信息,请告诉我!

If you need more context I opened up an issue on laravel/framework that has the full background explanation here如果您需要更多上下文,我在 laravel/framework 上提出了一个问题,这里有完整的背景解释

In alias first argument must be a vendor class, and after is overrided class在别名中,第一个参数必须是供应商类,然后是覆盖类

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

or或者

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

as u wish))像你所希望的))

I resulted to using composer to ovveride the file instead, as my previous method was not working whatsoever.我的结果是使用 composer 来覆盖文件,因为我以前的方法不起作用。 Here is what I did.这是我所做的。

Firstly, in the autoload section of the composer.json file I added this:首先,在composer.json文件的自动加载部分中,我添加了以下内容:

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

Next I created the Ovverides folder in the app folder and then I copied the CompiledRouteCollection.php file and pasted it inside of the Ovverides folder.接下来,我在 app 文件夹中创建了 Ovverides 文件夹,然后复制了CompiledRouteCollection.php文件并将其粘贴到 Ovverides 文件夹中。

Try swapping it out in your RouteServiceProvider rather than AppServiceProvider尝试在您的RouteServiceProvider而不是AppServiceProvider更换它

Just a guess, being as it is part of the routing system.只是猜测,因为它是路由系统的一部分。 It may have already been invoked as the original class before it ever hits AppServiceProvider .在它到达AppServiceProvider之前,它可能已经作为原始类被调用。

I looked at your issue at https://github.com/laravel/framework/issues/32082 and I'm surprised they didn't suggest trying it.我在https://github.com/laravel/framework/issues/32082 上查看了您的问题,我很惊讶他们没有建议尝试。 If I remember the request lifetime of Laravel correctly, RouteServiceProvider may be your ticket.如果我没记错 Laravel 的请求生命周期, RouteServiceProvider可能就是你的票。

I admire your resourcefulness in finding a workaround.我很欣赏你在寻找解决方法方面的机智。

By my experience, you can do something like this:根据我的经验,您可以执行以下操作:

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

And then please compose install and run the project.然后请compose install并运行该项目。

You can override vendor classes in composer您可以在作曲家覆盖供应商类

you'll need to edit your composer.json file and add two extra lines inside the autoload section to swap out the implementation.您需要编辑您的composer.json文件并在自动加载部分中添加两行额外的行以换出实现。

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

The first line will exclude the original class from being loaded, and the second class will point to the original class with the proper namespace for your implementation.第一行将排除加载原始类,第二行将指向具有适当命名空间的原始类以供您的实现。

then you need to create app/Overrides folder and copy the File.php (file that you want to override) inside it.那么您需要创建app/Overrides文件夹并在其中复制 File.php(您要覆盖的文件)。

and the last step is to run:最后一步是运行:

composer dump-autoload

And you're good to go!你很高兴去!

Probably what you want to use is $bindings on AppServiceProvider .可能您想使用的是AppServiceProvider上的$bindings

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

In this case I wanted to override $redirectTo variable in the Login Controller of a package:在这种情况下,我想在 package 的登录 Controller 中覆盖$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';
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM