[英]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:根据我的经验,您可以执行以下操作:
App\\Providers\\AppServiceProvider
.App\\Providers\\AppServiceProvider
注册函数中。public function register()
{
$loader = AliasLoader::getInstance();
$loader->alias('Illuminate\Routing\CompileRouteCollection', 'App\Helpers\CompiledRouteCollection');
}
"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.