Search code examples
composer-phpvendor

How to add code to vendor folder manually


I need to clone a project of my company on my local machine.

Problem: There is a module required in the main composer.json from our old agency which does not exist anymore, so I don't have the access keys needed to download it, BUT I have the latest code of that module.

The composer.json of that module says its name is "randomagency/import", so I added the code at vendor/randomagency/import. Then I removed the module from the main composer.json.

But I get this error:

Class 'RandomAgency\ProcessPipelines\Helper\Condition\AbstractCondition' not found#0 /var/www/company/src/vendor/composer/ClassLoader.php(444): include()
#1 /var/www/company/src/vendor/composer/ClassLoader.php(322): Composer\Autoload\includeFile()
#2 [internal function]: Composer\Autoload\ClassLoader->loadClass()
#3 [internal function]: spl_autoload_call()

My colleague told me that I need to add the module in the main composer.json under the autoload section, but Im not sure how exactly it works.


The best approach to solve it would be to create a new composer package and replace the agency URL in composer.json with my own, but I need a quick & dirty method for now.


Solution

  • Don't put it into vendor (as it is expected to get removed in time and the name of the vendor-dir is a configuration detail), so technically you have already put it in the wrong location. However, this is easy to recover from, just use a different path within the project root directory, e.g. create a directory where you put packages into (pkg in the following). This works already with autoloader configuration only (if that library requires no other configuration to work):

    PSR-4 Autoloader (only) from Project Directory

    Then add that path to the projects autoload configuration (see autoload (Composer configuration schema) - Autoload mapping for a PHP autoloader.:

    {
        "autoload": {
            "psr-4": {
               "RandomAgency\\Import\\": "pkg/random-agency-import-4.2"
            }
        }
    }
    

    It's good practice you have a single folder for the package - not two as in <vendor>/<package> pattern - and append an identifier of the package version.

    Require as Composer Package from Project Directory

    Better thought, if that package still contains the composer.json configuration file, add it as a path repository and require it with a version constraint that matches the ./pkg/random-agency-import-4.2/composer.json#/version or * if the "version" member is missing:

    {
        "require": {
            "random-agency/import": "*"
        },
        "repositories": [
            {
                "type": "path",
                "url": "./pkg/random-agency-import-4.2"
            }
        ]
    }
    

    You then don't need to configure the autoloader manually as it is taken from the libraries composer.json configuration. This is equally true for any other configuration part incl. the dependencies of the library.

    The great benefit of the path repository is, that is accepts relative paths to your projects configuration file (composer.json).

    Compare with your previous understanding:

    The best approach to solve it would be to create a new composer package and replace the agency URL in composer.json with my own, but I need a quick & dirty method for now.

    You either have solved it by now (the package you require has a composer.json file) or you still need to add the package information, but you don't need to create a new package or exchange URLs.

    Package Repository: Inline a Composer Package from Project Directory

    That is because you can inline the package as well in Composer with the package repository that now has the path and if you look at /repositories/0/package closely, you can see that this is another composer.json document, just inline at that place (and the /dist member is new):

    {
      "repositories": [
        {
          "type": "package",
          "package": {
            "name": "random-agency/import",
            "version": "4.2.0",
            "dist": {
              "type": "path",
              "url": "./pkg/random-agency-import-4.2"
            },
            "autoload": {
              "psr-4": {
                  "RandomAgency\\Import\\": ""
              }
            }
          }
        }
      ],
      "require": {
        "random-agency/import": "4.2.0"
      }
    }
    

    When you do updates etc., Composer then will install the packages files into the vendor folder (where-ever it may be, and regardless how often you remove it).

    If - and only if - there is no ./pkg/random-agency-import-4.2/composer.json file, you would need to create a "package", as that is the composer.json in the end.

    Alternative: compser.json within the package directory

    Similar as you added the autoload part to composer.json and as an alternative to the package repository, you can create the ./pkg/random-agency-import-4.2/composer.json file your own, then the path repository already suffices and it is perhaps easier to configure / maintain as the roots project composer.json file does not expand all the package details.

    But that is your preference, just showing that you have a couple of options within the project itself without creating outside / "new" packages.