Composer install and update: why does it not set the PHP interpretor in the "vendor" folder? - composer-php

According to docs, composer install (composer update too, since it includes install script), among other things, downloads the requirements and puts these packages inside the vendor directory: https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies :
It then implicitly runs the install command. This will download the dependencies' files into the vendor directory in your project.
What the docs don't say is: we often write the following in composer.JSON...
"require": {
"php": "^8.0",
... so if we try to apply what the docs say, it means that Composer would download the PHP interpretor (a package available in Packagist for example) and put it inside the vendor directory, when we run either composer install or composer update. What is the interest of putting a PHP interpretor inside a site's folder (here, vendor)?
But we know it doesn't do that. It won't download any PHP interpretor. It won't obviously put it inside the vendor directory. Instead, it will just check the server's PHP interpretor's version and returns a fatal error or something else if this version doesn't match the requirement's version.
So does it mean that in the Composer's install and update scripts, there is an exception made for PHP when treating the require's lines in the composer.JSON file?

In composer there's a special exception for require php, it only checks if your system's PHP version meets the requirement.
It's in the composer website under Package links: https://getcomposer.org/doc/04-schema.md#package-links.
Its not literally written though, its quite hard to find in the composer documentation.

If your require contains something like with
"php": "^8.0",
"ext-json": "*",
this does not mean: Install PHP or the JSON extension through Composer, but require that PHP and that extension in the given versions are already installed. That's what the documentation at https://getcomposer.org/doc/04-schema.md#package-links tells you:
require and require-dev also support references to specific PHP versions and PHP extensions your project needs to run successfully.
A regular expression that matches all such platform requirements can be found at https://github.com/composer/composer/blob/9ba042ded8b26230d33ebceb692bf29111d51ba4/src/Composer/Repository/PlatformRepository.php#L34 - currently, it contains:
const PLATFORM_PACKAGE_REGEX = '{^(?:php(?:-64bit|-ipv6|-zts|-debug)?|hhvm|(?:ext|lib)-[a-z0-9](?:[_.-]?[a-z0-9]+)*|composer-(?:plugin|runtime)-api)$}iD';
...which matches:
PHP runtimes in several versions
HHVM, a virtual machine that runs a forked version of PHP
all kinds of extensions and core libraries, like ext-json or lib-bz2
Composer itself, as some packages require special features of Composer v2 which were not available in v1

All lines in require section of composer.JSON are not packages available on a repository like Packagist: indeed, we can put some "virtual packages" inside this require section (https://getcomposer.org/doc/01-basic-usage.md#platform-packages).
php is one of these virtual packages. So Composer treat the following line...
"require": {
"php": "^8.0",
... as a virtual package (other name: "plateform package"), and not a package that could be put in vendor.
Then, if we extend a little the following definition of require...
Map of packages required by this package. The package will not be installed unless those requirements can be met.
(https://getcomposer.org/doc/04-schema.md#require)
..., then we can say that "if server's PHP interpretor's version doesn't meet the requirements versions, then Composer will raise a fatal error or something like that.
**Conclusion: being seen as a "virtual/plateform package" by Composer, php won't be installed (put) in vendor directory. It will just make Composer to check if server PHP version matches or not the requirements (if not, an error will be raised). This behavior is different than for other packages that would be, them, downloaded from for example Packagist and installed (put) inside vendor directory. **

Related

What happens when new items are placed in composer.json file within Laravel Application

I am having a hard time thoroughly understanding how the composer.json file works within a Laravel application. I can build Laravel projects, but I am self-taught and have never fully understand what happens in the composer.json file.
For example, I have a current project that has the following within composer.json:
"require": {
"php": "^7.2",
I attempted doing composer require livewire/livewire, but then realized livewire required a newer version of php. I am using XAMPP 3.2.4 and the php version is 7.2.28. So, I backed up my files from my htdocs and database and am downloading a newer version of XAMPP.
I assume I would then change my composer.json file to:
"require": {
"php": "^7.4",
But, I cannot understand what is really happening here. Is this just saying that the server needs to have php version 7.4 or higher on it for the application to work? Or is it placing new files in the vendor directory? Do I need to delete any files out of the vendor directory?
composer is the php packages and dependency manager. to not copy past all what you need for your project you use composer.
when you write a package name in the composer.json require section then composer will fetch it from his sources (The main source of composer is packagist).
About the vendor directory, if you delete it your application will simply don't work, if you are storing the app somewhere (in a repo for example), you provide only the composer.json and then you will have the same vendor with taping 'Composer install'
Good luck

Certain folders and files missing when using composer to install silverstripe?

When I run $ composer install in the terminal to install silverstripe using the following composer.json file, it does not bring through certain folder/files. E.g it does not bring in the mysite folder or assets folder and things like the main .htaccess file...
{
"name": "silverstripe/installer",
"description": "The SilverStripe Framework Installer",
"require": {
"php": ">=5.3.2",
"silverstripe/cms": "3.2.1",
"silverstripe/framework": "3.2.1",
"silverstripe-themes/simple": "*"
},
"minimum-stability": "dev"
}
Where as if I run the create project command from the silverstripe website it creates everything
E.g
$ composer create-project silverstripe/installer /path/to/project 3.2.1
How can I bring everything in using my composer.json file?
There is a StackOverflow answer similar to this: Difference between require and install vs create-project in composer
The create-project in essence clones the following repository, which has the files and folders you are looking for:
https://github.com/silverstripe/silverstripe-installer
It also has the composer.json file and runs the composer install after the cloning has finished.
So that is a base you can start your work on.
Note, you wouldn't want composer install to replace your .htaccess as that is something you edit per project (for redirects and things like that).
We have our own fork, of sorts, of the installer that contains our commonly used SilverStripe extensions in the composer.json already.
In our "base repo" we have:
.htaccess with samples of various redirects that you should have (forcing www, exceptions for development domains, etc)
Our own "project" base template that contains loads of helpers
Our commonly used SilverStripe extensions in the composer.json
We start our SilverStripe project by forking the base repository and then cloning that. We then run composer install on it and then start working on the project. We then commit the changes to our forked repository that relates to the project.
Also, in our repository we have vagrant file to start up a dev machine with all the goodies.

Composer, set minimum download stability

i am pretty new with composer and i am having a problem with a download.
I install composer and afterwards i want to install a proyect in beta state trough this command:
composer require google/apiclient:^2.0.0#RC
(This would download the google api client libraries with all their dependencies configurated).
I receive an error telling me that the package is not available in a stable-enough version for my minimum stability settings.
I have read a lot comments from people regarding this issue, but it always involves a composer.JSON file in a local project (not an external download from step 1).
My question is, how could i dowload that project? I would first have to set the minimum stability of composer to "dev" instead of "stable", but how can i do this?
This is what I get:
The windows command shell requires to enclose the package and version into double quotes (and it isn't a bad idea in Linux as well):
Doesn't work in Windows:
composer require google/apiclient:^2.0.0#RC
Does work:
composer require "google/apiclient:^2.0.0#RC"
Please don't set "minimum-stability" to "dev", because this is a global setting and will instantly install development versions that you probably don't want, because they are no final release and may be unstable. This would be true for ALL packages you require, and their dependencies.
SOLUTION: I finally solved it this way:
First you need to create an empty composer.json file wherever you want.
Afterwards you do something like this (or literally this, in my case):
{
"name": "Your title",
"minimum-stability": "dev",
"require":
{
"google/apiclient": "2.0.*"
}
}
Afterwards you go to the directory with this file in the cmd (windows console) and type "composer install".
This will solve the problem and install all the libraries with its dependencies. It is not the same as setting the minimum stability to "dev" for all libraries, but it will solve the problem for specific packages.

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