If I create an empty folder and put composer.json there:
{
"require": {
"silex/silex": "1.0.*#dev"
}
}
and than run composer install - it works fine, microframework silex and all it's requirements will be installed into vendor folder. Ok.
Now more complex example that I cant understand why it does not work.
I have a project (called "FB") which depends on my own "some kind of framework" (called "light/light4").
FB project's composer.json:
{
"repositories":[
{
"type":"hg",
"url":"http://bitbucket.org/pqr/light4"
}
],
"require":{
"light/light4":"dev-default"
}
}
As you see it depends on my framework light/light4 hosted on bitbucket.
Then light/light4 composer.json:
{
"name":"light/light4",
"version":"1.0.0",
"require":{
"php":">=5.4.0",
"silex/silex": "1.0.*#dev",
"twig/twig":">=1.8,<2.0-dev",
"monolog/monolog":">=1.0.0",
"symfony/validator":"2.1.*",
"symfony/console":"2.1.*"
},
"autoload":{
"psr-0":{
"Light":"src/"
},
"files":[
"src/functions/body.php", "src/functions/db.php", "src/functions/file.php", "src/functions/misc.php"
]
}
}
light/light4 depends on silex/silex and some other things.
Since I never metioned "minimun-stability":"dev" - assume all packages by default will be installed for stable versions. Except silex/silex required by light/light4 as "silex/silex": "1.0.*#dev"
Unfortunatelly, when I run composer -v install on the root project (FB), I get following error:
Loading composer repositories with package information
Reading composer.json of light/light4 (default)
Importing branch default (dev-default)
Installing dependencies
Your requirements could not be resolved to an installable set of packages.
Problem 1
- light/light4 dev-default requires silex/silex 1.0.*#dev -> no matching package found.
- light/light4 dev-default requires silex/silex 1.0.*#dev -> no matching package found.
- Installation request for light/light4 dev-default -> satisfiable by light/light4 dev-default.
Potential causes:
- A typo in the package name
- The package is not available in a stable-enough version according to your minimum-stability setting
see <https://groups.google.com/d/topic/composer-dev/_g3ASeIFlrc/discussion> for more details.
Read <http://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.
silex/silex 1.0.*#dev -> no matching package found - WHY??? It works for simple empty project, but does not work for requirements chain :(
Someone from composer-dev irc adviced to put "silex/silex": "1.0.*#dev" into general composer.json of FB project. I tried - and now it works: all packages installed in stable versions and the only silex/silex in dev version as I wanted. Now I totally confused.
The question is still there - why it works in general composer.json and does not work in nested (required) project light/light4? I what to understand to root of the issue, or it's just a bug of composer?
As the docs say: "require and require-dev additionally support stability flags (root-only)"
Those flags are only read from the root package (see definition of root-only) because that way it gives your project the full control over the stability of the packages. Obviously that's a problem when some of your dependencies rely on unstable stuff, but that situation should get better as more and more packages have composer-available stable releases.
Related
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)
I have a local git repo and project where I want to use it.
composer.json in project folder:
"repositories": [
{
"type":"package",
"package":{
"name":"api",
"version":"0.1.0",
"source":{
"type":"git",
"url":"/var/www/modules/api",
"reference":"master"
}
}
}
],
"require": {
"api": "*"
}
composer install get source from the repo. Then I commited changes in the repository and make git tag "0.1.1"
In composer.json I changed version to "0.1.1"
run composer update:
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 0 installs, 1 update, 0 removals
- Updating api (0.1.0 => 0.1.1) Checking out master
Writing lock file
Generating autoload files
But files was not updated.
Don't use package as the repository type. You'd have to manually change all information inside if something changes.
package really only is for the situation where you have code that you cannot add a composer.json for, or that is not hosted in version control.
For all other situations, i.e. you have the code in version control, and you can add composer.json to it, use "type" = "vcs" with the repository URL. Composer then works so much better.
See the documentation:
package: If you depend on a project that does not have any support for composer whatsoever you can define the package inline using a package repository. You basically just inline the composer.json object.
See the documentation:
Note: This repository type has a few limitations and should be avoided whenever possible:
Composer will not update the package unless you change the version field.
Composer will not update the commit references, so if you use master as reference you will have to delete the package to force an update, and will have to deal with an unstable lock file.
I want to achieve the following setup (I've omitted other dependencies and stuff for clarity):
Project's composer.json
{
"require": {
"vendor/masterpackage": "*"
}
}
Master package's composer.json
{
"require": {
"vendor/package-1": "dev-master",
"vendor/package-2": "dev-master"
}
}
The master package is versioned with releases, child packages are not, hence the dev-master requirement.
Since minimum-stability can only be set in the root composer.json and is applied to all dependencies (which is undesired in my case), is it possible to set a dev-stability flag for only the master package AND its own dependencies so that its child packages get installed properly? I've already tried "vendor/masterpackage": "*#dev" but to no avail...
The way you experiment with it, it will not work.
The dependencies of depended packages cannot be influenced directly. So if your project prohibits development packages, you are out of luck.
You'd can add these indirect packages into your projects composer.json, adding them with the necessary #dev or dev-X surroundings. That way the will be required directly, allowing for development stability, and the master package requirement will also be fulfilled.
However, be warned that depending on branches is a very very bad habit and makes your dependencies very brittle. The commit id that has been used is recorded, but once you update and it goes wrong, you'll have a hard time juggling all the moving parts, i.e. all repositories that are only providing a branch.
I've found a way to get this working and thought it would be beneficial to post it as an answer for future reference.
Project's composer.json
{
"require": {
"wikimedia/composer-merge-plugin": "dev-master",
"vendorname/masterpackage": "*"
},
"merge-plugin": {
"require": [
"vendor/vendorname/masterpackage/dev-composer.json"
]
}
}
Master package's dev-composer.json
{
"require": {
"vendorname/package-1": "dev-master#dev",
"vendorname/package-2": "dev-master#dev"
}
}
The merge plugin makes this working since it treats dependencies of specified JSON files as if they are in the root composer.json
I am trying to install package Payum/PayumBundle,I add
"require-dev": {
"payum/payum-bundle": "1.0.0-BETA2"
}
to indicate I also need to download dev version.
this gives me an error:
Problem 1
- The requested package payum/payumbundle could not be found in any version, there may be a typo in the package name.
Potential causes:
- A typo in the package name
- The package is not available in a stable-enough version according to your minimum-stability setting
see <https://groups.google.com/d/topic/composer-dev/_g3ASeIFlrc/discussion> for more details.
how do we find the right version constraint from git tag ,branches?
what I tried :
2. tried the version constraint following
1.0.*#beta , 1.0.0 , 1.0.*#beta ,1.0.*#dev,1.0.0#beta
the result is still the same
the latest tag for this project is
1.0.0-BETA2
what is the correct version constraint for this? this post explains what a version constraint can be , but it doesn't explain how to find the right version constraint from git tag.
The easier way how to get proper version name, is go to package detail on packagist.org.
There you'll find out there are no BETA tags available. It might be caused by not triggering autoupdate by Github.
You can see, the last dev version is: 1.0.x-dev
So this command would normally do the trick:
composer require payum/payum-bundle:1.0.x-dev
But this package depends on another dev package, so you need to mention them both in your composer.json. Like this:
{
"require": {
"payum/payum-bundle": "1.0.x-dev",
"payum/core": "1.0.x-dev"
}
}
And run:
composer update
That's all :). Verified!
I want to put https://github.com/timrwood/moment into my composer.json for easy maintenance.
It's not an official packagist project (of course, as it's not PHP), but it contains a packages.json for nodejs. Can I use this in my composer.json?
I tried this, but it didn't work:
{
"repositories": {
"timrwood/moment": {
"type": "git",
"url": "git://github.com/timrwood/moment.git"
}
}
}
It throws an error message saying "No valid composer.json was found in any branch or tag of git://github.com/timrwood/moment.git, could not load a package from it."
And it is lacking the version string to define the version I want to use...
Can anyone help here?
Or shouldn't I use composer here at all cause I'm mixing JS and PHP?
Composer only manages composer packages. It does not know how to parse a package.json file. There are different approaches to this problem. Composer may be able to deal with frontend dependencies in the future.
For the time being I'd recommend using a separate dependency manager for your JavaScript dependencies. Either NPM or something like jam or ender.
Check out composer plugin to handle components via bower, nodejs and git repositories: fxpio/composer-asset-plugin.