在 Laravel 中安全地编辑第三方作曲家(供应商)包并防止在发布新版本的包时丢失自定义更改

Posted

技术标签:

【中文标题】在 Laravel 中安全地编辑第三方作曲家(供应商)包并防止在发布新版本的包时丢失自定义更改【英文标题】:Safely edit a third party composer (vendor) package in Laravel & prevent losing customized changes on release of a new version of the package 【发布时间】:2015-09-13 20:25:57 【问题描述】:

我想在我的 Laravel 5 项目中编辑从 composer 提取的包,但是我相信如果我运行 composer update 并且该包的新版本已经发布,我将丢失所有更改。我应该如何去编辑包?有没有办法将包从供应商目录中复制出来,以便我可以在项目的其他地方使用它?

【问题讨论】:

【参考方案1】:

简单、快速、安全的方法:

    在 Laravel 的根目录中创建一个目录并将其命名为包或任何您喜欢的名称。 将修改后的包从供应商目录移动到您的包目录。 更新 composer.json 以从您的包目录而不是供应商目录加载包。

首先将其从require中移除

"require": 
    "php": ">=5.6.4",
    "laravel/framework": "5.3.*",
    "laravelcollective/html": "^5.3.0", <==== remove this line                           
    "barryvdh/laravel-debugbar": "^2.3",
    "doctrine/dbal": "^2.5"
,

然后将其添加到自动加载中

"autoload": 
    "psr-4": 
        "App\\": "app/",
        "Collective\\Html\\": "packages/laravelcollective/html/src", <==== add this line
    ,

请不要忘记运行

composer dumpauto

第 3 步的替代方案。

如果您使用的是最新版本的作曲家,还有一个新的选择。

将此添加到您的 composer.json

"repositories": [
    
        "type": "path",
        "url": "./packages/laravelcollective"
    
]

然后将包的版本修改为dev-master

"require": 
    "php": ">=5.6.4",
    "laravel/framework": "5.3.*",
    "laravelcollective/html": "dev-master", <==== this line                           
    "barryvdh/laravel-debugbar": "^2.3",
    "doctrine/dbal": "^2.5"
,

终于

composer update

【讨论】:

当您处理包裹时,例如 Collective\\Html\\ 确保您检查包裹的 composer.json 并将您的地址与它匹配。可能需要处理多个命名空间。 也不要以为你没有使用包的composer文件。包中可能会自动加载 laravel,如下所示:code "extra": "laravel": "providers": [ "Company\\Package" ] 确保将包添加到 /config/app.php => 'providers' 数组【参考方案2】:

出于您指出的原因,实际上编辑作曲家包并不安全。

我所做的是扩展我想要/需要更改的类。

我在这里使用 Filesystem 类完成了它。它不能确保它不会中断,但它可以让您在不覆盖更改的情况下进行更新。

config/app.php

<?php

return [

    'providers' => [

//        'Illuminate\Filesystem\FilesystemServiceProvider',
        'MyApp\Filesystem\FilesystemServiceProvider',
    ],

    'aliases' => [
        ...
    ],

];

MyApp\Filesystem\FilesystemServiceProvider.php

<?php namespace MyApp\Filesystem;

use Config;
use Storage;
use League\Flysystem\Filesystem;
use Dropbox\Client as DropboxClient;
use League\Flysystem\Dropbox\DropboxAdapter;
use Illuminate\Filesystem\FilesystemManager as LaravelFilesystemManager;

class FilesystemManager extends LaravelFilesystemManager

    public function createDropboxDriver(array $config)
    
        $client = new DropboxClient($config['token'], $config['app']);

        return $this->adapt(
            new Filesystem(new DropboxAdapter($client))
        );
    

【讨论】:

感谢您的回答。在这种方法中,我是否必须将每个类中的命名空间更改为“MyApp”,或者在我复制之后从我的 composer.json 中删除原始包会更好吗? 这取决于您需要更改多少软件包。对于我所做的,我只需要更新 2 个类,所以我只是将这两个类拉到我的命名空间中,并进行了调整。我原封不动地保留了原始类,并在我的应用程序中引用了更新的类。如果它很广泛,你总是可以在 github 上 fork 存储库并在那里进行更新。这样,当发生更改时,您就有时间更新代码。 我通常 fork 存储库并在我的 composer.json 文件中的 repositories 部分下引用我的 fork 存储库。缺点是当所述包更新时你不会得到更新。 只是想知道这对 Laravel 8.x 仍然有效吗? @KevinChavez 它在 8.32.1 上仍然为我工作【参考方案3】:

如果您想保留您的更改并同时从原始 repo 更新包,您可以分叉此包并让 composer 从您的 fork 中提取,而不是从原始 repo 中提取。

您所要做的就是将您的 fork 添加为存储库并更新 版本约束指向您的自定义分支。您的自定义分支 名称必须以 dev- 为前缀。

更新您的composer.json 文件如下:


    "repositories": [
        
            "type": "vcs",
            "url": "https://github.com/MyGithub/html"
        
    ],
    "require": 
        "laravelcollective/html": "dev-bugfix"
    

请注意,除了指定错误修复分支外,您不会更改 require 语句。您仍然引用上游包 (laravelcollective/html),而不是您的个人分支 (MyGithub/html)。

另外,请注意 dev- 是自动添加的,因此分支名称是 bugfix 而不是 dev-bugfix。如果您将分支命名为 dev-bugfix,则需要将其命名为 dev-dev-bugfix

【讨论】:

【参考方案4】:

如果你想改变一个包的类,你必须

    创建一个扩展包类并进行更改的类

    创建一个扩展类的服务提供者的服务提供者,并更改registerBinding类来绑定你的扩展类

    将该新服务提供者放入providersarray 中config\app

    禁用此包的包发现,您可以在应用程序的 composer.json 文件的额外部分中列出包名:

    "extra": 
        "laravel": 
            "dont-discover": [
                "barryvdh/laravel-debugbar"
            ]
        
    , 
    

【讨论】:

【参考方案5】:
    使用严格版本的供应商包,例如代替 "vendor/package": "~1.3" 或 "vendor/package": "^1.3.2",你可以使用 "vendor/package": "1.3.2", 将修改后的源文件复制到公共(如果是开源的)或私有文件的存储/应用程序(例如 laravel) 只需在 Controller 中编写代码:File::copy('foldername/filename.php', '../vendor/namevendor/subfolderwhatever/filename.php'); 将此作为部署例行程序,与部署同事共享 喝杯咖啡,享受生活,完成

【讨论】:

以上是关于在 Laravel 中安全地编辑第三方作曲家(供应商)包并防止在发布新版本的包时丢失自定义更改的主要内容,如果未能解决你的问题,请参考以下文章

作曲家更新 Laravel

Composer下载软件包并放入供应商地图,但服务提供商无法识别它,laravel 6

找不到'Carbon Traits ObjectInitialisation'laravel5.8

在现有项目上安装 laravel

Laravel,如何在没有作曲家的情况下手动安装包

如何防止在“作曲家更新”命令时覆盖文件