Composer: how can I install another dependency without updating old ones? - composer-php

I have a project with a few dependencies and I'd like to install another one, but I'd like to keep the others the way they are. So I've edited the composer.json, but if I run composer install, I get the following output:
Installing dependencies from lock file
Warning: The lock file is not up to date with the latest changes in composer.json. You may be getting outdated dependencies. Run update to update them.
Your requirements could not be resolved to an installable set of packages.
Problem 1
- laravel/framework dev-master requires ext-mcrypt * -> the requested PHP extension mcrypt is missing from your system.
- laravel/framework dev-master requires ext-mcrypt * -> the requested PHP extension mcrypt is missing from your system.
- Installation request for laravel/framework dev-master -> satisfiable by laravel/framework dev-master.
First of all, I do have mcrypt installed, so I don't know why it's complaining about that there.
So, how can I install this new dependency?
My composer.json:
{
"require": {
"opauth/opauth": "*",
"opauth/facebook": "*",
"opauth/google": "*",
"opauth/twitter": "*",
"imagine/Imagine": "dev-develop",
"laravel/framework": "4.*",
"loic-sharma/profiler": "dev-master"
},
"autoload": {
"classmap": [
"app/libraries",
"app/commands",
"app/controllers",
"app/models",
"app/database/migrations",
"app/tests/TestCase.php"
]
},
"minimum-stability": "dev"
}

To install a new package and only that, you have two options:
Using the require command, just run:
composer require new/package
Composer will guess the best version constraint to use, install the package, and add it to composer.lock.
You can also specify an explicit version constraint by running:
composer require new/package ~2.5
–OR–
Using the update command, add the new package manually to composer.json, then run:
composer update new/package
If Composer complains, stating "Your requirements could not be resolved to an installable set of packages.", you can resolve this by passing the flag --with-dependencies. This will whitelist all dependencies of the package you are trying to install/update (but none of your other dependencies).
Regarding the question asker's issues with Laravel and mcrypt: check that it's properly enabled in your CLI php.ini. If php -m doesn't list mcrypt then it's missing.
Important: Don't forget to specify new/package when using composer update! Omitting that argument will cause all dependencies, as well as composer.lock, to be updated.

Actually, the correct solution is:
composer require vendor/package
Taken from the CLI documentation for Composer:
The require command adds new packages to the composer.json file from the current directory.
php composer.phar require
After adding/changing the requirements, the modified requirements will be installed or updated.
If you do not want to choose requirements interactively, you can just pass them to the command.
php composer.phar require vendor/package:2.* vendor/package2:dev-master
While it is true that composer update installs new packages found in composer.json, it will also update the composer.lock file and any installed packages according to any fuzzy logic (> or * chars after the colons) found in composer.json! This can be avoided by using composer update vendor/package, but I wouldn't recommend making a habit of it, as you're one forgotten argument away from a potentially broken project…
Keep things sane and stick with composer require vendor/package for adding new dependencies! 😉

We can install a new package without updating other dependencies like this:
composer require package/name --no-update
this will add your package to composer.json (no update to composer.lock)
composer update package/name
this will now install/update your new package, adding it to composer.lock without updating other deps

My use case is simpler, and fits simply your title but not your further detail.
That is, I want to install a new package which is not yet in my composer.json without updating all the other packages.
The solution here is composer require x/y

In my case, I had a repo with:
requirements A,B,C,D in .json
but only A,B,C in the .lock
In the meantime, A,B,C had newer versions with respect when the lock was generated.
For some reason, I deleted the "vendors" and wanted to do a composer install and failed with the message:
Warning: The lock file is not up to date with the latest changes in composer.json.
You may be getting outdated dependencies. Run update to update them.
Your requirements could not be resolved to an installable set of packages.
I tried to run the solution from Seldaek issuing a composer update vendorD/libraryD but composer insisted to update more things, so .lock had too changes seen my my git tool.
The solution I used was:
Delete all the vendors dir.
Temporarily remove the requirement VendorD/LibraryD from the .json.
run composer install.
Then delete the file .json and checkout it again from the repo (equivalent to re-adding the file, but avoiding potential whitespace changes).
Then run Seldaek's solution composer update vendorD/libraryD
It did install the library, but in addition, git diff showed me that in the .lock only the new things were added without editing the other ones.
(Thnx Seldaek for the pointer ;) )

Related

Update composer dependencies in json file on updating

When I run composer update, a lot of dependencies and my composer.json get updated. But, my composer.json didn't change, so next time I run composer install, I'll get the outdated ones again.
For instance, I have:
"require": {
"symfony/form": "^4.1",
}
When I run the command It shows:
Updating symfony/dotenv (v4.1.4 => v4.1.5): Loading from cache
But the json line stays the same, and composer install will install the 4.1.4 version.
Is there a way to update the composer.json file when I run composer update?
Thanks in advance!
You should have a composer.lock file after performing composer update. You commit this file to version control and then the next person checks out the code can do composer install to obtain the correct version.
The composer.json file contains the version constraints whereas the composer.lock file contains the specific version.
Take a look at the example you had:
"require": {
"symfony/form": "^4.1",
}
Here the version constraint for the symfony/form package is ^4.1. This means that it will accept any version 4 build from 4.1, but not version 5 or higher. So it could obtain version 4.1.1, or 4.2.13 or anything higher (but below version 5).
https://getcomposer.org/doc/articles/versions.md#caret-version-range-
here are the docs on lock files
https://getcomposer.org/doc/02-libraries.md#lock-file

Is there a way to composer require without actually pulling the package?

Is there a way to composer require some/thing without actually pulling the package? In my workflow, it would hasten things if I knew a command to just check version requirements and update composer.json without actually doing anything with regard to the vendor directory.
You can use --no-update switch to avoid updating and installing new dependencies - it will only add new dependency to composer.json.
composer require --no-update symfony/symfony
But since require does not check if required package can be installed (it always pick the newest version compatible with your PHP as a constraint, without checking if it will be possible to install), this can leave composer.json in non-installable state.
It will also not update composer.lock so composer install may ignore your new dependency. So this is probably a bad idea unless you want to do something with it before you commit new composer.json.
You may try to use --dry-run switch to test what will happen after composer update - you will be able to check if composer.json is installable, but composer.lock still will be out of date.
composer update --dry-run

composer - install new package without updating other packages

I added a package in the require block of my composer.json.
I do a composer install and it says Nothing to install or update.
In my understanding, composer update would work but I shouldn't do that because it updates the versions of the other packages to the latest, but I haven't tested my code on them.
How do I install that new package?
The Command Line.
You don't have to add the new packages manually to your composer.json file and then do a composer install or update. Use The Command Line
Installing new packages from the command line automatically adds it to your composer.json file and it does not update previously installed packages.
From the project root, simply run:
composer require package/name
Hope it helps
For future readers, if you have already added package(s) to your require block in composer.json, it's as simple as listing them all after the update command to exclude existing packages from being updated. First, simulate update to ensure you're happy with the result:
composer update --dry-run vendor/project vendor2/project2
If okay, run it again with the --dry-run argument removed.
You can see the output of updating new/specific packages is different from that of:
composer update --dry-run
Your composer.lock file should be on version control or otherwise backed up so you can restore it & revert all packages in the event of failure.
Using composer require will also update other dependencies.
We can install a new package without updating anything else like this:
composer require package/name --no-update
this will add your package to composer.json, leaving composer.lock intact.
composer update package/name
this will now install/update your new package, adding it to composer.lock. This will not update any other dependencies.

what's the purpose of composer's `require` command

Here is the definitions from the docs:
The require command adds new packages to the composer.json file from
the current directory. If no file exists one will be created on the
fly. After adding/changing the requirements, the modified requirements
will be installed or updated.
If you do not want to choose requirements interactively, you can just
pass them to the command.
I can't seem to understand the purpose of the require command and the difference from install. Can you elaborate on that?
And here is the example of using the command:
composer global require "fxp/composer-asset-plugin:~1.0.3"
Can you tell me what's the difference from:
composer global install "fxp/composer-asset-plugin:~1.0.3"
It's just a convention. There might be some fallbacks in other commands for common people missuses, but every command is optimized for a different feature. It's just better user experience.
Same goes for similarity of composer install and composer update.
As for conventions, in order of common workflow:
composer install is for installing all packages of new application (all mentioned in composer.json), use: composer install
composer require is for adding a new package, use: composer require symfony/symfony
composer update is for updating current dependencies, use: composer update
composer require->It will write the modules in composer.json file and install the module.
composer install->It will install the modules which are already present in the composer.json file.

Do not update a specific package

Is there a way to tell composer that each time I do a composer update I want him to ignore a specific package?
Have you considered specifying the required version for the package you are trying to ignore? For instance:
"require": {
"some/package": "~1.2"
}
This may get updated, because you are saying any version >=1.2,<2.0, But if you strictly say you want only version 1.0, you should not see any updates to that package:
"require": {
"some/package": "1.2"
}
Actually I don't know if there is any way to tell composer to exclude one specific package from updating but you can tell which packages to update as
composer update <package> <package2>; // or
php composer.phar update <package> <package2>;
For example,
composer update foo/package1 bar/package2; // or
php composer.phar update foo/package1 bar/package2;
Also, I think, if you don't list them in composer.json (remove after installation) by yourself, then they will not be updated unless also specified in the list.
From Composer:
If you only want to install or update one dependency, you can whitelist them:
$ php composer.phar update monolog/monolog [...]
Check this link and also check Composer.
Update : (found on internet but not tested)
To do that, just remove the package from composer.lock
Update: Only availble for composer versions 1.0.0-alpha6 and lower. Using it in version 1.0.0-alpha7 and higher will remove all packages in "require-dev".
I believe currently you can trick composer with some mess if you can afford it in your project. Something like: Put all packages you don't want to update in "require-dev" and run updates with composer update --no-dev
Just be careful of that if you run composer install as i recall they will be removed from your project.
All this trickery is really nasty, so we should wait for official way of doing things like that, personally i update packages explicitly specifying them
To ignore a specific package, you can use provide (if it's part of your own package) or replace. This tells Composer that you wish to provide/replace a specific package, so it won't download it.
Here is the composer.json file example which should work:
{
"require": {
"radic/tmp-underscore-php": "~1.2.0"
},
"replace": {
"patchwork/utf8": "*"
}
}
In this example, the patchwork/utf8 package would be ignored on composer install or update.
To exclude specific version, see: Composer exclude specific versions.

Resources