How to add code to vendor folder manually - composer-php

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.

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.

Figured it out. Had to add it like this:
"autoload": {
"psr-4": {
"RandomAgency\\Import\\": "vendor/random-agency/import"
},

Related

Composer error when trying to include multi level public personal repositories

I'm splitting up some of my personal code to modularize and reuse it on different projects.
I've started using composer recently and have been using it for referencing these modules on my projects.
The following has worked for me so far:
First project composer.json
{
"name": "mpf/apimodule",
"version":"dev-main",
"autoload": {
"psr-4": {
"APIModule\\":"classes/"
}
}
}
Second project composer.json
{
"name": "mpf/crawler",
"version":"dev-main",
"autoload": {
"psr-4": {
"API\\": "classes/"
}
},
"repositories": [
{
"type": "vcs",
"url": "git#github.com:{User}/{Repo}.git"
}
],
"require": {
"fabpot/goutte": "^3.2",
"mpf/apimodule": "dev-main"
}
}
Both composers are compiled and the project works as intended.
But when I try to add a third layer
Third project composer.json
{
"autoload": {
"psr-4": {
"API\\": "classes/"
}
},
"repositories": [
{
"type": "vcs",
"url": "git#github.com:{User}/{Repo}.git"
}
],
"require": {
"mpf/crawler": "dev-main"
}
}
I get the following error when running the composer update command
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Root composer.json requires mpf/crawler dev-main -> satisfiable by mpf/crawler[dev-main].
- mpf/crawler dev-main requires mpf/apimodule dev-main -> could not be found in any
version, there may be a typo in the package name.
I've found a similar issue, but my repositories are all public and that was the problem for them.
I've tried running composer -vvv / composer diagnose, but couldn't find any useful information with the results.
From the description given in your question, you add repositories into root composer.json files. This works fine as long as you're using the root composer.json file. That is the project having this file.
Now while this works on each per-project basis, when you put the third (or fourth, fifth etc. ) composer.json file into the mix, or as you word it "add a third layer", it stops working.
Technically it does not stop working, however Composer can not resolve that inherited repository any longer to resolve the root dependency:
- Root composer.json requires mpf/crawler dev-main \
-> satisfiable by mpf/crawler[dev-main].
- mpf/crawler dev-main requires mpf/apimodule dev-main \
-> could not be found in any version, there may be a typo in the package name.
As honest as Composer is here, it may be puzzling in your situation. You've certainly already double-checked there is no typo and still though, Composer can not find any version.
That is because Composer uses the composer.json#/repositories configuration only from the root composer.json - that is the file itself. Let's visualize this a bit:
composer.json
vendor/mpf/crawler/composer.json
My educated guess is that, albeit you've added the repository for mpf/crawler to composer.json the repository for mpf/apimodule has not been added to it but only to vendor/mpf/crawler/composer.json.
The fix is easy, add all repositories your root project requires to resolve all dependencies to that projects configuration file (composer.json in the project you install the dependencies in).
If you think this through, it might become more clear why that is so:
The moment you install from composer.json, all repositories should be defined already as otherwise the outcome of the install will be a pure game of luck. Packages would be able to overwrite your repositories configuration and you would not be in control any longer.
My recommendations to continue your journey:
Add repositories inside your root composer.json file, to ensure your projects' configuration is complete. (Goal: understanding root configuration, the project level)
When working with this, consider if you want to have a global configuration of repositories. That is you can on the level of your computer user configure a list of repositories shared across projects (on that host). (Goal: understanding global configuration, the level of your host, working with projects)
Take a Safari-Tour on the different types of repositories Composer offers (compare with the documentation) as you may find even more in there (e.g. path repositories, another central .json file you can share etc. - there are quite some options). (Goal: understanding of the different repository configuration types)
kuba points to an entry in the Composer FAQ for this topic (via):
Why can't Composer load repositories recursively? (Composer FAQ)

Composer - Using a custom fork of a package dependency

I am using the package teamtnt/laravel-scout-tntsearch-driver and I wish to make a very small change to one of the files within teamtnt/tntsearch which is one of the packages dependencies.
Usually I would:
Create a fork of the package.
Add the repository into my composer.json as follows:
"repositories": [
{"type": "vcs", "url": "https://github.com/user/packagefork"}
],
Require/Upgrade the package to the correct version (usually dev-master) keeping the original name spacing and it all works fine.
However, with a dependency which is not directly included in my composer.json file, this does not seem to work. Do I need to fork both the base package, and the dependency package even though I do not need to change anything within the base?
I am hoping there is a simple way to do this, without having to fork each level.
This was actually quite simple. Not too sure why it did not work originally! Instructions below for anyone wondering:
Fork the package (i.e. GitHub)
Add the repo from your username, to your projects main composer.json as follows:
"repositories": [
{"type": "vcs", "url": "https://github.com/youruser/tntsearch"}
],
Edit the composer.json file within the new fork you created in step 1 (youruser/tntsearch) and create/add to the extras key:
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
}
This effectively allows you to install your dev-master version, but allow other packages where this is a dependency to request the 2.0 version (in this case). You do need to be careful in this case that you have forked the correct version and any upgrades are correctly managed later down the line, or things may break!
More info on composer alias here
Require/Upgrade the package using original package namespace, at the dev-master version.
composer require teamtnt/tntsearch:dev-master
The name spacing and package versions will remain the same as before your fork, but the edits from your fork will be pulled into your project instead.

How to set custom folder path for sub folders in vendor when installing a package?

I want to install a package into my local project.For that I'm creating a composer.json file in my project folder is given below, it gives the total vendor folder of that package into my custom folder in my project. Its working fine.....
{
"config": {
"vendor-dir": "/var/www/html/Test2/Testing/Down"
},
}
It gives the package into 'Down' folder.
But, now I want the sub folders or files in that packages to be installed in my custom folders like js/css folders in my project.
For example i want jquery.js file into my local folder path
/var/www/html/Test2/Testing/assests/js
From the package "frameworks/jquery".
For that, what changes are needed in my composer.json file?
Composer is used to bring in packages to support the PHP code of a project, here is how they describe it on the Composer website:
Composer is a tool for dependency management in PHP. It allows you to
declare the libraries your project depends on and it will manage
(install/update) them for you.
In other words, if you need to do logging in your PHP code and decide to use the publicly available monolog package, you use composer to bring that package into your project, then in your PHP code, you can call monolog functions.
Using config to rename the vendor directory is trying to use Composer in a way that doesn't fit the intent of the tool. The vendor directory is used to hold the packages brought in (such as the monolog code). The vendor-dir value is simply renaming that directory.
Since you have GitHub listed as a tag, you could possibly use cloning to get your files to your website directory.
I've modified my composer.json file, it looks like the below:
{
"config": {
"vendor-dir": "/var/www/html/Test2/Testing/Down"
},
"require": {
},
"scripts": {
"post-package-install": [
"php -r \"exec('cp -r /var/www/html/Test2/Testing/Down/frameworks/jquery/* /var/www/html/Test2/Testing/assets/js');\""
]
}
}
It will gives all selected files in a package to my local folder.
Briefly the files in the folder 'frameworks/jquery' are copied into my local 'assets/js' folder.

Nested dependencies and private repositories with composer

At the company I'm currently working we've recently started to move our code into different private repositories so that it's more maintainable and reusable (and also to make it easier to open-source it later).
Every PHP repository is also a Composer package that can be required in our project whenever we need it.
At the moment there's an issue with this approach: every time we need a package that depends on other packages we need to specify those also in the root composer.json.
For example, let's say that the in the root composer.json we need to require two packages company\b and company\c, and that the package company\c needs another package company\d. Then the resulting root composer.json will look like this:
{
"require": {
"company/b": "dev-master",
"company/c": "dev-master",
"company/d": "dev-master"
},
"autoload": {
"psr-4": {
"Company\\" : "src\Company"
}
},
"repositories": [
{
"type": "vcs",
"url": "git#bitbucket.org:company/b.git"
},
{
"type": "vcs",
"url": "git#bitbucket.org:company/c.git"
},
{
"type": "vcs",
"url": "git#bitbucket.org:company/d.git"
}
]
}
Is there a way to avoid specifying nested dependencies in the root composer.json and use the ones specified in the composer.json in every package?
Edit:
Everything I stated before is valid only for the private packages. If a package, let's say company\b, needs a public package that can be found on Packagist then that dependency CAN be specified in the company\b composer.json and it will be imported.
As you correctly found out, only the root package can add repository metadata to the collection of known packages.
I would suggest you take a look at Satis to create a local Composer repository. This would only require you to add this single repository to all your composer.json files of all packages, and it will be used as an updatable source of knowledge about all your private repositories. You no longer have to add a list of Git repos everywhere.
I am successfully hosting around 120 internal packages for our IT enterprise that way. Take this as a sign that once you start splitting isolated tasks into a package, you will get more of them pretty fast.
Also note that it is important to take versioning seriously. Stop depending on branches - tag your software, make releases, use semantic versioning. If you don't, things will break at some point, and people will curse you (correct) or Composer (incorrect) for not working or messing things up.
After a quick search and a look at the Composer documentation I discovered that the repositories can only be specified in the root composer.json.
Additionally it's possible to specify in the root composer.json whether to allow or not development versions of the packages using:
"minimum-stability": "dev",
"prefer-stable": true
Also this issue on GitHub was really useful.

Autoloading a third party library via Composer's autoloader?

I've got a little Laravel4 project into which I need to incorporate a third party library. This library is not available via GIT or Packagist (only from the vendor), so I downloaded it into my vendor directory (had to add some custome vendor and package directories).
Rather than just include()-ing it as suggested by the vendor's documentation, I'm hoping to just use the existing Composer autoloader, and can use a hand figuring out what I'm doing wrong.
My dir tree is like this
path/to/project
|__ app
|__ vendor
| |__ merchantcompany
| |__ client
| |__ src
| |__ client.php
|__ blah
|__ blah
And I updated my compser.json to include:
"autoload": {
"psr-4": {
"MerchantCompany\\": "vendor/merchantcompany/client/src"
},
...
I also tried "MerchantCompany\\": "src", but to no avail.
WHAT am I missing?
NOTE: The class from the vendor is not namespaced.
Am I under the correct assumption that this is fine, or should I be adding a namespace to the class script?
You are currently doing it wrong. You manually inject the package into a folder that is managed by Composer (which can wipe that directory if seen fit), and you incorporate the autoloading sort of into your own code.
Composer offers a way to add the needed metadata to projects which do not have them. This is the "package" type of repository described in https://getcomposer.org/doc/04-schema.md#repositories
If you look at the example given there for Smarty, you see that you basically need to add a key "type" with value "package" and a key "package" with the content of the composer.json file you'd like to see contained inside the project.
In this case there is a version tag added (in sync with the version of Smarty being used, just in case some later versions make use of Composer and Packagist, which Smarty does since some version 3.1.x) to allow Composer to reference this version, a name for that package (both values can be arbitrarily made up if you doubt you'll ever get that software with Composer support), and a URL to download the code from (you don't have to provide both a ZIP download AND a repository if you don't know them).
The thing that is missing is the definition of autoloading, which can be added just the same way as everywhere else. If nothing else works, use "classmap". Composer will then scan all files for occurrences of classes, interfaces and traits and will generate an array containing the accompanying filenames. You can however also use PSR-0 or PSR-4 if the code conforms to that standard.
Note that PSR-4 can only be used for classes using namespaces! Without namespaces, you must use either PSR-0, or classmap. From the short piece of directory listing I doubt the code is compatible with PSR-0, so just use classmap for quick results.
As a suggestion:
"repositories": [
{
"type": "package",
"package": {
"name": "merchantvendor/client",
"version": "1.0.0",
"dist": {
"url": "http://example.com/zip-download-url.zip",
"type": "zip"
},
"autoload": {
"classmap": ""
}
}
}
],
"require": {
"otherstuff": "...",
"merchantvendor/client": "1.0.0"
}
PSR-4 is a namespace-based autoload standard. You won't be able to use it if your vendor's PHP package does not utilize namespaces.
If the package's files are class based (not procedural functions like a helpers file), then you can use Composer's classmap autoloader instead. Otherwise you can use the files autoloader, which basically includes the file on every request, regardless if you use it or not.
Note that since you are defining the path to these files manually, they do not need to be in your vendor folder. I'd actually recommend that you put the library in a different, non-.gitignore folder, since it is an external dependency that you can not automatically include into your project via Composer.
Of course you can always nag your vendor into updating their package to be more compliant with things like PSR-4 and namespaces. :)

Resources