composer 从两个 composer.json 文件安装

Posted

技术标签:

【中文标题】composer 从两个 composer.json 文件安装【英文标题】:composer install from two composer.json file 【发布时间】:2018-03-16 18:31:10 【问题描述】:

我有多个 composer.json 具有多个单独的依赖项,并希望使用单个 composer install 命令在两个 composer.json 中安装所有依赖项。

位置是这样的:

| - composer.json
| - Custom
    | - Package1
        | - composer.json

第一个composer.json


    "name": "laravel/laravel",
    "description": "The Laravel Framework.",
    "keywords": ["framework", "laravel"],
    "license": "MIT",
    "type": "project",
    "require": 
        "php": ">=5.6.4",
        "barryvdh/laravel-debugbar": "^2.3",
        "laravel/framework": "5.4.*",
        "laravel/tinker": "~1.0",
        "laravelcollective/html": "^5.4.0"
    ,
    "require-dev": 
        "fzaninotto/faker": "~1.4",
        "mockery/mockery": "0.9.*",
        "phpunit/phpunit": "~5.7",
        "symfony/css-selector": "3.1.*",
        "symfony/dom-crawler": "3.1.*"
    ,
    "autoload": 
        "classmap": [
            "database"
        ],
        "psr-4": 
            "App\\": "app/",
        
    ,
    "autoload-dev": 
        "psr-4": 
          "Tests\\": "tests/"
        
    ,
    "scripts": 
        "post-root-package-install": [
            "php -r \"file_exists('.env') || copy('.env.example', '.env');\""
        ],
        "post-create-project-cmd": [
            "php artisan key:generate"
        ],
        "post-install-cmd": [
            "Illuminate\\Foundation\\ComposerScripts::postInstall",
            "php artisan optimize"
        ],
        "post-update-cmd": [
            "Illuminate\\Foundation\\ComposerScripts::postUpdate",
            "php artisan optimize"
        ]
    ,
    "config": 
        "preferred-install": "dist",
        "sort-packages": true,
        "optimize-autoloader": true
    

Package1目录中的第二个composer.json


    "name": "custom/package1",
    "description": "",
    "require": 
        "php": ">=5.6",
        "composer/installers": "~1.0",
        "lavary/laravel-menu": "1.7.1"
    ,
    "autoload": 
        "psr-4": 
            "Custom\\Package1\\": ""
        
    

我想将Package1 中的lavary/laravel-menu 安装到安装了所有默认软件包的主供应商目录中。

|- vendor  //<==want here
| - composer.json
    | - Custom
        | - Package1
            | - vendor  //<== not here
            | - composer.json

我已经测试过这个解决方案:

https://***.com/a/27735674

像这样:


    "config": 
        "vendor-dir": "../../vendor/"
    

这会安装包,但我们需要进入第二个 composer.json 而不是主 composer.json 并从第一个 composer.json 中删除已安装的包。

如何在不进入单个供应商目录中的第二个或多个 composer.json 的情况下从主 composer.json 安装所有依赖项?

【问题讨论】:

尝试合并这 2 个作曲家文件。 composer 已经处理了这一切。你不应该接触供应商代码。如果您无法获取要解析的软件包,请尝试删除 composer.lock 文件 @MohammadTrabelsi 我无法合并不同的作曲家,因为它们应该分开保存以维护依赖关系,如果我们删除自定义包,它们将被删除 Composer 本身不支持此功能,但您可以使用 composer-merge-plugin 包。 @delboy1978uk 我不是在谈论触摸供应商代码。它将删除其他依赖项,因为将在供应商中列出但在第二个 composer.json 中没有列出的依赖项。 composer.lock 也不会妨碍我,因为我可以使用 composer update 但这对我来说不是问题。 【参考方案1】:

经过一些研究和建议,我发现有多种方法可以实现此解决方案。

    使用外部包维护依赖。

感谢rickdenhaan让我知道

Composer 合并插件

https://github.com/wikimedia/composer-merge-plugin

首先我们需要这个包:

composer require wikimedia/composer-merge-plugin

然后我的 composer.json 变成这样:


    "name": "laravel/laravel",
    "description": "The Laravel Framework.",
    "keywords": ["framework", "laravel"],
    "license": "MIT",
    "type": "project",
    "require": 
        "php": ">=5.6.4",
        "barryvdh/laravel-debugbar": "^2.3",
        "laravel/framework": "5.4.*",
        "laravel/tinker": "~1.0",
        "wikimedia/composer-merge-plugin": "^1.4"
    ,
    "require-dev": 
        "fzaninotto/faker": "~1.4",
        "mockery/mockery": "0.9.*",
        "phpunit/phpunit": "~5.7",
        "symfony/css-selector": "3.1.*",
        "symfony/dom-crawler": "3.1.*"
    ,
    "autoload": 
        "classmap": [
            "database"
        ],
        "psr-4": 
            "App\\": "app/"
        
    ,
    "autoload-dev": 
        "psr-4": 
          "Tests\\": "tests/"
        
    ,
    "scripts": 
        "post-root-package-install": [
            "php -r \"file_exists('.env') || copy('.env.example', '.env');\""
        ],
        "post-create-project-cmd": [
            "php artisan key:generate"
        ],
        "post-install-cmd": [
            "Illuminate\\Foundation\\ComposerScripts::postInstall",
            "php artisan optimize"
        ],
        "post-update-cmd": [
            "Illuminate\\Foundation\\ComposerScripts::postUpdate",
            "php artisan optimize"
        ]
    ,
    "config": 
        "preferred-install": "dist",
        "sort-packages": true,
        "optimize-autoloader": true
    ,
    "extra": 
        "merge-plugin": 
            "include": [
                "Custom/*/composer.json"
            ],
            "recurse": true,
            "replace": false,
            "ignore-duplicates": true,
            "merge-dev": true,
            "merge-extra": false,
            "merge-extra-deep": false,
            "merge-scripts": true
        
    

现在, 运行

composer install

 composer update

那么你在每个目录下的composer.json会被合并到默认的vendor目录中。

    下一个解决方案可能是将包发布到 packagegist 并在 composer.json 中要求,并且在 composer install 期间将安装所有依赖项。

    就像Asgardcms 所做的那样。

    将私有仓库添加到 composer.json。

    Configuring composer.json with private bitbucket mercurial repository

    该选项需要将metapackage的composer.json添加到composer.json主文件中。

(我不确定该选项,但感谢JParkinson1991 知道此解决方案的人可以添加对此选项的解释。添加只是为了让某人知道此解决方案存在。)

这里是示例解决方案:

PHP & Composer, how do I combine composer.json files

在这第一个解决方案适合我的情况。希望这对花费大量时间搜索的人有所帮助。

【讨论】:

你试过作曲家路径存储库吗? getcomposer.org/doc/05-repositories.md#path您提到的插件报告了很多问题,不再更新。作曲家存储库路径也不能解决您的问题吗? 另见 Drupal 上的这个问题“停止使用 wikimedia/composer-merge-plugin”。但是,使用此插件有许多缺点:它有性能损失(作曲家进程较慢并下载更多元数据)和复杂性损失。建议的解决方案 删除 wikimedia 合并插件并用 Composer 'path' 存储库替换它,这是一种原生 Composer 功能,可满足与合并插件相同的需求,但缺点较少。

以上是关于composer 从两个 composer.json 文件安装的主要内容,如果未能解决你的问题,请参考以下文章

如何从docker compose文件中访问env变量

composer修改成国内镜像

深入理解 Jetpack Compose 内核:SlotTable 系统

如何使用 Composer 将代码标记为稳定?

如何使用 Composer 将代码标记为稳定?

深入理解 Jetpack Compose 内核:SlotTable 系统