require and require-dev dependencies of composer Laravel - php

I have a Laravel App and I want to install require dependencies but I was wondering how does composer know whether to load dev dependencies or production dependencies?
just got confused by this concept so if somebody could clarify this concept for me than that would be of great help.

When you run composer install --dev, composer installs all packages including require-dev. This is the default behaviour, exclusion of the flag would result in the same action.
When you run composer install --no-dev, composer skips the require-dev packages.
Also, composer will not install the require-dev package of a required package unless you specifically ask it to do so

The regular require dependencies are such packages that you will ALWAYS use, meaning that the framework itself (in this case Laravel), your application code and/or other 3rd party code is dependent on such packages. These dependencies are often referred as prod dependencies since you use them in production (because without them, your app wouldn't run)
The require-dev dependencies are "optional", in the sense that your core application logic would run, but you would not be able to run "development" stuff, such as Unit tests (phpunit/phpunit package) and instantiate fake data (fzaninotto/faker).
I hope this helps!

Related

How to composer install latest of require-dev and lowest for require

I want to run tests for the lowest support version of the packages installed using composer, but I ideally want the development packages at the latest versions.
Specifically, I want to run this to install the lowest version of packages for the purpose of testing:
composer update --prefer-lowest --prefer-stable
However, this will also downgrade PHPUnit and other development packages, which may cause tests to fail because of bugs in those development packages.
I can get more explicit with version required of each development package, however, whilst I may want to test my package with the lowest version of the packages it uses, it never makes sense to run these tests with lower versions of PHPUnit and other development packages.
Is there a way to force require to --prefer-lowest whilst keeping require-dev at the latest?
The simplest solution is to use correct constraints for development packages. If your tests requires PHPUnit 8.3.4 to run correctly and may fail on 8.3.3, use ^8.3.4 as a constraint for phpunit/phpunit package.
The --no-dev flag skips the development packages for install|require|update operations.
Update to get the latest versions of application (require) and development (require-dev) packages:
composer update --no-autoloader
Run the following command to downgrade your application dependencies (require) to the lowest stable versions but use --no-dev to prevent downgrading the development dependencies (require-dev).
composer update --no-dev --prefer-lowest --prefer-stable --no-autoloader
Dump the autoloader for require and require-dev packages.
composer dump-autoload

How to force dev-dependencies from a dependency to also install with composer?

I'm currently working on a package (cms), which has a dev-dependency to a certain package (code-generator) to create code. This package is not needed in production.
However, when creating a website that uses the cms package, dev-dependencies (including the code-generator) are not installed (which is correct composer behavior btw).
But while developing the website, the code-generator is required.
Is there any way to force a certain dev-dependency to also install when the package is installed?
This is not possible. Dependency can either be required for the package to work properly (then it should be in require section and it is always installed), or required only for development of this package (then it should be in require-dev section and is installed only when package repository is root). There is nothing in between. If this code-generator dependency is required by your package to work it clearly fails into first category (require section).
Usually in this case the best solution is to split this package into 2 packages: regular package and dev package with all tools used only during development process. So it should be installed by 2 commands:
composer require myvendor/mypackage
composer require myvendor/mypackage-dev --dev
This will still require everyone to install two packages instead of one, but it should not be a big problem if it is properly documented. Result should is more clear (it should be quite obvious what is the purpose of myvendor/mypackage-dev package) and gives more control to package owner (he can easily add new dependencies for dev package) and end user (he can always skip installing myvendor/mypackage-dev if he don't want to use this code generator).

Avoid installing composer's require-dev libraries in production

According to this answer, packages listed in composer.json's require-dev section will still be installed when you do
composer install
Since composer install is a normal thing to do as part of a production install, to install all versions specified in the composer.lock file, how do you avoid installing things you only need for development? I'm accustomed to Gemfiles, where specifying something for dev means it is ignored in production, and can't quite wrap my mind around why anyone would ever want to install everything in production.
Aha... I missed the --no-dev flag previously. Apparently you have to specifically tell composer install that it should ignore the require-dev sections. In a way this makes sense, since you more often type composer install on your development laptop, and composer install --no-dev will probably be a part of a deployment script where you don't need to think about it. So the defaults are set up for developer convenience.

Why does Composer Install a Different Package?

I've been working with the Magento Firegento custom Composer installer, and I ran into this odd bit of Composer behavior I don't understand.
Consider the following dead simple composer.json file
{
"require": {
"magento-hackathon/magento-composer-installer": "*"
}
}
If I run compser.phar install with this composer.json file, I get the following.
$ composer.phar install --no-dev
Loading composer repositories with package information
Installing dependencies
- Installing aoepeople/composer-installers (v0.0.1)
Loading from cache
Writing lock file
Generating autoload files
From my mostly lay-person's understanding composer.phar, I've said
Hey, composer, please install the magento-hackathon/magento-composer-installer package from packagist.org
And composer has said back to me
Sir, yes sir! Here's the aoepeople/composer-installers package
I don't understand why composer installed aoepeople/composer-installers, when I asked for magento-hackathon/magento-composer-installer.
To be clear: I understand the reason magento-hackathon/magento-composer-installer wasn't installed is this is a package that lives in a different composer repository. My original mistake was not including this repository in my composer.json file.
However, it doesn't make sense to me that composer would install a different package than the one I asked for. When I search packagist there's no magento-hackathon/magento-composer-installer extension.
Why does packagist install a different extension? What's happening behind the scenes to make magento-hackathon/magento-composer-installer resolve to aoepeople/composer-installers? How/where in the composer source could I debug this sort of thing myself in the future?
Vinai published a great writeup on Magento and Composer here.
Quoting from there
Composer will use packagist.org to look where to get the libraries. Because Magento modules aren’t listed there, you will have to add the packages.firegento.org repository to the configuration as follows [...]
So you will need the repository
"repositories":[
{
"type":"composer",
"url":"http://packages.firegento.com"
}
],
to get the magento composer installer.
And yes composer offers replacements. On the packaging entry for aoepeople/composer-installers you will notice the replaces section:
And since magento-hackathon/magento-composer-installer is not available on packagist composer will deliver you aoepeople/composer-installers.
OK, so that's a weird behavior :) I'm the author of the aoepeople/composer-installers package and the idea behind this is that this package provides an alternative (very basic and simplified implementation of the composer package-type magento-module - and adds another type magento-source. I only want the installer to put the package in the right place - keeping it simple. That's why I decided to come up with an alternative package.
The reason why the aoepeople/composer-installer replaces the magento-hackathon/magento-composer-installer is because many Magento modules already come with a composer.json that requires the magento-hackathon/magento-composer-installer. In order to be able to seamlessly use the simpler installer that one is "pretending" to be the hackathon-installer. But unless you actively require aoepeople/composer-installers in your project's composer.json you should continue using the original installer as no Magento module's composer.json out there (not even ours) is directly referring to aoepeople/composer-installers.
The fact that packagist tries to be "smart" and returns a package that replaces a package that's not registered is new to me and - to be honest - very disturbing. While this might be intended behavior I share the opinion that this could easily be abused. I start liking Alan's idea to bypass packagist completely using "packagist":"disabled". Especially in the case of Magento modules this seems to happen easily because most of the Magento modules are unknown to packagist while being registered at packages.firegento.com only.
A simple quickfix/workaround to this specific situation could be to register magento-hackathon/magento-composer-installer on packagist.org.
The Packagist package at https://packagist.org/packages/aoepeople/composer-installers has metadata saying that it replaces the magento-hackathon/magento-composer-installer package. Packagist would then install this as it's the package that replaces what you asked for.
Docs here: https://getcomposer.org/doc/04-schema.md#replace

What's the difference between require and require-dev? [duplicate]

This question already has answers here:
What is the difference between require and require-dev sections in composer.json?
(6 answers)
Closed 4 years ago.
I would like to know the difference between require and require-dev.
The composer website doesn't offer a good explanation the difference between these two.
The part that I don't get is Lists packages required for developing this package, or running tests, etc. from Composer Official Docs.
The require-dev packages are packages that aren't necessary for your project to work and shouldn't be included in the production version of your project.
Typically, these are packages such as phpunit/phpunit that you would only use during development.
The key distinction is that Composer will only install require-dev dependencies for the "root package" – the directory where you run composer install. The documentation describes this as:
The root package is the package defined by the composer.json at the
root of your project. It is the main composer.json that defines your
project requirements.
…and the require-dev documentation specifies that it is "root-only".
In practice, this means that a package's require-dev dependencies aren't used if the package is being installed as a dependency for something else (ie it's installed to another project's vendor folder).
So if you have phpunit in the require-dev list for YourProject, and I clone down YourProject and run composer install in the yourproject/ directory, Composer will install phpunit to yourproject/vendor/, because it's likely I'm doing some development on YourProject. As part of doing development I'll probably want to run YourProject's test suite, and to do that I'll need phpunit.
But, if I add YourProject as a dependency of MyProject, installing the myproject package will install the yourproject package as well, but it will not install phpunit.
You can override this behaviour with the --dev and --no-dev options, but the default behaviour is based on whether the package concerned is the root package.
seems clear to me:
require
Lists packages required by this package. The package will not be
installed unless those requirements can be met.
require-dev (root-only)
Lists packages required for developing this package (1), or running tests,
etc. The dev requirements of the root package only will be installed
if install is run with --dev or if update is run without --no-dev.
http://getcomposer.org/doc/04-schema.md
1. the packages used to develop a package

Categories