phplaravel-5composer-phpvendor

composer install from two composer.json file


I have multiple composer.json having multiple seperate dependency and want to install all the dependency in the both composer.json using single composer install command.

The location is like this:

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

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

Second composer.json inside Package1 directory

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

I want to install the lavary/laravel-menu inside the Package1 to the main vendor directory where all the default packages are installed.

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

I have tested this solution:

https://stackoverflow.com/a/27735674

like this:

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

This installs the packages but we need to get into the second composer.json instead of main composer.json and removes the installed package from first composer.json.

How can i install the all the dependency from the main composer.json without getting into the second or multiple composer.json in single vendor directory?


Solution

  • After some research and suggestion i figured out there are multiple ways to achieve this solution.

    1. Using external package to maintain the dependency.

    Thanks to rickdenhaan to let me know about

    Composer Merge Plugin

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

    First we need to require this package:

    composer require wikimedia/composer-merge-plugin
    

    Then my composer.json becomes like this:

    {
        "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
            }
        }
    }
    

    Now, run

    composer install
    

    or

     composer update
    

    Then your composer.json in each of the directory will be merged into default vendor directory.

    1. Next solution could be to publish the package to the packagist and require in the composer.json and during composer install all the dependency will be installed.

      Like the Asgardcms has done.

    2. Adding the private repository to the composer.json.

      Configuring composer.json with private bitbucket mercurial repository

    3. This option needs to add the composer.json of metapackage to the main composer.json file.

    (I am not sure about the option but thanks to JParkinson1991 Someone who knows this solution could add explaination on this option. Adding just to let someone know this solution exists.)

    Here is the example solution:

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

    In this the first solution suits my case. Hope this helps someone who spent alot of time searching.