At the moment I use Travis CI in order to test a Symfony Bundle. PHPUnit is installed by Composer since PHPUnit is declared as a dev dependency:
{
…
"require" : {
"php": ">=5.5",
"symfony/symfony": "~2.7 || ~3.0"
},
"require-dev": {
"doctrine/orm": "^2.4.8",
"symfony/assetic-bundle": "~2.3",
"symfony/monolog-bundle": "~2.4",
"doctrine/doctrine-fixtures-bundle": "~2.3",
"liip/functional-test-bundle": "~1.4",
"phpunit/phpunit": "4.8.* || ~5.1"
},
…
}
Even if I use Travis CI's cache to cache the ~/.composer folder after each build, installing PHPUnit with Composer takes some time because PHPUnit has to check all the dependencies before installing them.
So I was thinking about using the PHAR version of PHPUnit that can be installed in one command:
wget https://phar.phpunit.de/phpunit.phar
But if I use this command on Travis CI, PHPUnit will be downloaded once in each build. Is there a way to cache this phpunit.phar file? An easy way may be to put the file in the cache, check the date of this file and download a new version if the file is older than 1 day, but there may be a simpler solution.
There is --self-update option for PHPUnit but it will be removed in the next major release.
You can configure Travis to keep certain directories between builds (called "caching" in their documentation).
Simply add the following configuration to your Travis config file and the /vendor directory should persist across builds:
cache:
directories:
- vendor
You should still include a composer install call to your build to update dependencies when the composer.json file changed. To further speed up the composer install process, you can also add you composer.lock file to version control.
Alternatively, you can of course use the same feature to simple keep a downloaded phpunit.phar file between builds.
Related
I found the composer.json & composer.lock(php) has conflict section (not to be confused with merge conflict ). The other similar files like package.json/yarn.json (nodejs) or Pipfile (python) and the corresponding lock files package-lock.json/yarn.lock or Pipfile.lock, do not have such format even though all these lock files serve the same purpose (lock the dependence to the exact version) and implement in the similar way (at least looking from the surface)
So what is usage of it and what should I do with it ? I read the composer document https://getcomposer.org/doc/04-schema.md#conflict but I still feel confused, e.g.
Map of packages that conflict with this version of this package. They will not be allowed to be installed together with your package.
For example after running composer install I have a composer.lock saying
{
"name": "symfony/http-kernel",
"version": "v4.4.20",
...
"conflict": {
"symfony/browser-kit": "<4.3",
"symfony/config": "<3.4",
"symfony/console": ">=5",
"symfony/dependency-injection": "<4.3",
"symfony/translation": "<4.2",
"twig/twig": "<1.43|<2.13,>=2"
},
...
It is easy to guess "symfony/console" 5.0 is conflicted with "symfony/http-kernel" 4.4.20 so symfony/console 5.0 will not be installed.
Do I need to do anything with the conflict ? So far I feel like that as a package user (not the package developer) those info is just a FYI and I don't need to do anything. But then why bother to list them for me ? After all package.json and Pipefile don't have such information and I don't find the problem without it.
--- update ---
From the answer I got I realize I need to emphasize this: I understand composer.lock is for composer so I don't need to worry about it.
What I don't understand is the purpose putting it in composer.json, this file is for human users. So if it has a conflict section what should I do about it?
I want to know a practical use case of "conflict" section in my composer.json if I am not a package developer but a package user.
When building an application, you are free to choose your dependencies way better than when you are building a reusable library like symfony/http-kernel which you've mentioned in your question.
Putting any other package constraint in the conflict section of such a package means: if you want to install the package in the current version, no other package version must be installed that is listed in the conflict section. From your example: symfony/http-kernel in v4.4.20 must not be installed if symfony/browser-kit is installed in any version <4.3.
In your own application, you have more freedom to use stricter constraints for the packages you use. You could require all packages with pretty strict version numbers, but this makes updates less comfortable. For example, this is a part of the require section in one of my current projects:
"doctrine/annotations": "^1.0",
"doctrine/doctrine-bundle": "^2.2",
"doctrine/doctrine-migrations-bundle": "^3.0",
"doctrine/orm": "^2.7",
"easycorp/easyadmin-bundle": "^3.1",
"exercise/htmlpurifier-bundle": "^3.1",
"knplabs/knp-snappy-bundle": "^1.8",
"league/csv": "^9.6",
"lexik/jwt-authentication-bundle": "^2.10",
"nelmio/cors-bundle": "^2.1",
All these packages might install tons of other dependencies which I cannot control. But if I know that any version of the other dependencies causes trouble, I can list them in the conflict section of my application such that this version is not installed.
For example, in the past I've needed that for an update of doctrine/migrations where the configuration has changed. I wanted to be able to update all packages except this one, because I didn't want to bother with the configuration changes I had to apply to my application for a while.
"conflict": {
"symfony/console": ">=5",
this means that for some reason your package can't work with symfony/console version 5 and higher, so it will keep it below 5.
E.g. you can exclude some package faulty version:
"conflict": {
"foo/bar": "1.420.69",
}
I know this is an old post, but thought I'd add a point to what's already been said:
You may still benefit from a conflict section in composer.json if you know any of your code conflicts with any packages. It could be any reason from both your code and the package trying to do similar jobs and stepping on each other's toes or simply that a package is badly written and breaks your code.
In that case, you can add a conflict section in your composer.json to tell composer to never download that package (or some releases of it).
This would be useful if you work with other developers and someone else might try to require that package, or if you worry that composer may try to install it as a dependency of yet another package e.g. X is the package you don't want, but another package Y depends on X and you don't know. Without the conflict section, composer would download package X without you even knowing/noticing.
I inherited a legacy code base where a previous developer did not commit the composer.lock file to version control, but instead committed all the packages in vendor. I know.
I have the composer.json, but it appears incomplete as it only has require-dev. Here's the complete composer.json:
{
"require-dev": {
"phpunit/phpunit": "4.3.*",
"squizlabs/php_codesniffer": "1.*",
"phpdocumentor/phpdocumentor": "2.*"
}
}
Can composer generate a composer.lock file from the packages already installed in vendor without updating those packages? When I run composer install, a lock file is created, but the packages are updated to their most recent versions instead of maintaining the version already installed.
run composer update --lock will only updates the lock file hash to suppress warning about the lock file being out of date without upgrade your packages.
reference: https://getcomposer.org/doc/03-cli.md#update-u
I have been trying to deploy a php app on heroku but I keep getting this error:
-----> PHP app detected
-----> Bootstrapping...
-----> Installing platform packages...
ERROR: neither your composer.json 'require' section nor any
dependency therein requires a runtime version, but 'require-dev'
or a dependency therein does. Heroku cannot automatically select
a default runtime version in this case.
Please add a version requirement for 'php' to section 'require'
in composer.json, 'composer update', commit, and deploy again.
! ERROR: Couldn't load 'composer.lock'; it must be a valid lock
file generated by Composer and be in a consistent state.
Check above for any parse errors and address them if necessary.
Run 'composer update', add/commit the change, then push again.
! Push rejected, failed to compile PHP app.
! Push failed
anyone know how I can solve it?
So this is what I would look at, and sorry if any of these assumptions are wrong, or I am going through stuff you have already done.
Your composer.json should be divided up into require and require-dev. Require would be installed in production with require-dev added locally.
{
"name": "something/something",
"description": "A description of my project",
"type": "project",
"require": {
"php": ">=5.5.9",
"doctrine/cache": "1.4.*",
"elasticsearch/elasticsearch": "~2.0",
"monolog/monolog": "~1.0",
"knplabs/github-api": "~1.2",
"ezyang/htmlpurifier": "~4.6",
"easyrdf/easyrdf": "0.9.*",
"hoa/compiler": "~2.15",
"hoa/visitor": "~1.15",
"collectiveaccess/service-wrapper": "v1.1",
"phpoffice/phppresentation": "dev-master",
"phpoffice/phpword": "v0.13.*"
},
"require-dev": {
"phpunit/phpunit": "4.3.*",
"maximebf/debugbar": ">=1.0.0"
}
}
If you have not got composer installed you need to do so. https://www.hostinger.com/tutorials/how-to-install-composer
Run php composer install in the first instance of php composer update later on to install your dependencies.
Please commit everything except, the vendor files and any cache or logging. This would include composer.lock which is a list of installed dependencies and the versions you are using.
Heroku will install these dependencies in production making sure it uses the same version as specified in the lock file.
I am trying to create a PHP library which includes other libraries, and I bet I'm missing something fundamental.
Using the AWS PHP SDK as a guide, I'd like to create a library which, after installing with Composer, requires other libraries, yet the entire scope of classes (both from the current library, and required libraries) all become available simply by using require 'vendor/autoload.php;'.
What are the basic requirements to set this up? Is it a matter of configuring composer.json, namespacing in a particular way, or both?
What you're describing is exactly Composer's main purpose - the definition of a package of code that may require and implement other packages.
Using the AWS SDK as a guide, if you look at the composer.json file, which provides all of the Composer configuration information, you'll see two require blocks, one labeled require and one labeled require-dev:
"require": {
"php": ">=5.5",
"guzzlehttp/guzzle": "^5.3.1|^6.2.1",
"guzzlehttp/psr7": "^1.4.1",
"guzzlehttp/promises": "~1.0",
"mtdowling/jmespath.php": "~2.2"
},
"require-dev": {
"ext-openssl": "*",
"ext-pcre": "*",
"ext-spl": "*",
"ext-json": "*",
"ext-dom": "*",
"ext-simplexml": "*",
"phpunit/phpunit": "^4.8.35|^5.4.0",
"behat/behat": "~3.0",
"doctrine/cache": "~1.4",
"aws/aws-php-sns-message-validator": "~1.0",
"nette/neon": "^2.3",
"andrewsville/php-token-reflection": "^1.4",
"psr/cache": "^1.0"
},
This is how you define what other packages/libraries your library depends upon. The require section lists all other libraries that must be installed when your library is installed. The require-dev section lists libraries that may only be necessary when you are working in a development environment, and are not needed in your production environment.
When you specify other libraries that are required, Composer will install your library, and then go out and also require the libraries your library requires (and then the libraries those libraries require, and so on and so on).
Also included with the libraries to include, you'll notice that the version numbers are also included, to ensure compatibility.
The easiest way to add new dependencies I find is on the command line, with the composer require command, documented here: https://getcomposer.org/doc/03-cli.md#require. The command helps you search for the package you want if you don't know it exactly, and can resolve the latest version for you automatically (which you can override if you need/want to).
If you wish to require a development-only dependency, add the --dev flag when running the command.
Using this command, Composer will automatically update your composer.json file, pull down the dependency onto the local machine, and update your autoloader.
You should never need to do anything more than require_once vendor/autoload.php to ensure dependencies can be autoloaded - Composer will do all the legwork of setting up the autoloader so you don't have to, and keep everything up to date as new dependencies are added.
Here's the complete documentation on the composer.json schema: https://getcomposer.org/doc/04-schema.md. You will want to have a composer.json config file in the root of project, so you can configure composer for your project (and any others that require your library later). If you don't have one, you can use the composer init command to interactively create one. Documentation on that command is available here: https://getcomposer.org/doc/03-cli.md#init
And here's their basic usage guide, in case you haven't gone through it already: https://getcomposer.org/doc/01-basic-usage.md
When I use composer to install packages in my project I am only able to do so if I update my json file manually.
For example, if I run the following command in Git-Bash in my project directory (which contains my composer.phar and composer.json file):
php composer.phar require php-di/slim-bridge
It returns the following error:
[Invalid Argument Exception]
Could not find package
php-di\slim-bridge at any version for your minimum-stability (stable).
Check the package spelling or your minimum stability.
However, if i were to just update my json file to the following (example I've provided contains multiple packages I am using in my project):
{
"require": {
"slim/slim": "^3.0",
"slim/twig-view": "^2.1",
"illuminate/database": "^5.2",
"respect/validation": "^1.0",
"slim/csrf": "^0.6",
"slim/flash": "^0.1",
"phpmailer/phpmailer": "^5.2",
"php-di/slim-bridge":"^1.0"
},
"autoload":{
"psr-4": {
"App\\": "app"
}
}
}
... And I run the command: $ php.composer.phar update
Everything installs to project correctly.
What is going on that I am not able to install packages using the require method thus making me resort to manually updating my json file each time?
Since I am using windows, I used the windows installer for composer rather than install through command line and I got this working correctly. Much much easier now since I don't have to update my JSON files manually.