Composer
composer.json and composer.lock¶
Dependencies are specified in the composer.json in the root of your package
These dependencies can demand specific versions, or allow for some flexibility
When running the upgrade
command, composer will traverse all the dependencies in all packages' composer.json
files. Once it's calculated the result of this, it'll write specific versions to composer.lock
Here's a starting point for a composer.json:
{
"name": "edmondscommerce/module",
"description": "Project description goes here.",
"license": "MIT",
"autoload": {
"psr-4": {
"EdmondsCommerce\\Module\\": [
"src/"
]
}
},
"autoload-dev": {
"psr-4": {
"EdmondsCommerce\\Module\\": [
"tests/"
]
}
},
"require": {
},
"require-dev": {
},
"config": {
"bin-dir": "bin",
"preferred-install": {
"vendor/*": "source",
"*": "dist"
},
"optimize-autoloader": true
}
}
require and require-dev¶
require
is for dependencies when your package is itself is a dependency of another
require-dev
is for dependencies when your package is the root of the project
Version matching¶
"1.0.0"
requires exactly version 1.0.0">=1.0""
requires at least version 1.0">=1.0 <=2.0""
requires anything between 1.0 and 2.0"1.0.*""
requires version 1-point-0-point-anything"^1.0.0""
allows for anything matching the major version. Equivalent to">=1.0.0 <2.0.0"
"~1.0.0""
allows for anything matching the minor version. Equivalent to">=1.0.0 <1.0.0"
Stability¶
- Always have minimum stability set to 'stable' in composer.json
"minimum-stability": "stable",
@dev
"edmondscommerce/magento2-data-migration": "dev-master@dev",
Commands¶
Install¶
Installs all of the required dependcies based on the composer.lock
file
Update¶
Ignores the composer.lock
file and pulls in the latest versions that satisfy the requirements in composer.json
, then writes the result to composer.lock
You can update a single package
composer update "edmondscommerce/magento2-data-migration"
Require¶
Adds a new require
node to the composer.json
and runs an upgrade
Info¶
It show you the details of the details of the package installed
composer info "edmondscommerce/magento2-data-migration"
Out Put
name : edmondscommerce/magento2-data-migration
descrip. : A tool to help with data migration
keywords :
versions : * dev-master
type : library
license : MIT License (MIT) (OSI approved) https://spdx.org/licenses/MIT.html#licenseText
source : [git] https://github.com/edmondscommerce/magento2-data-migration.git e6370fb7f485cc1a200640c638612e3f5583546a
dist : [zip] https://api.github.com/repos/edmondscommerce/magento2-data-migration/zipball/e6370fb7f485cc1a200640c638612e3f5583546a e6370fb7f485cc1a200640c638612e3f5583546a
names : edmondscommerce/magento2-data-migration
Verbose mode¶
Add -v
, -vv
, -vvv
to any command to increase the verbosity
Fixing a third party composer lib¶
Track the master branch of the lib. This is done by adding an inline alias.
Figure out which version is currently required. This can be done by looking at either the composer lock file of your project, or the composer.json file of the project that pulls in the module
Update your composer.json file to include the following in the require section
"require": {
"example/example": "dev-master as 2.0"
}
The run composer update example/example
and the master branch will be pulled in. You can confirm this if the following is output
- Removing example/example (2.0.9)
- Installing example/example (dev-master a96add4) Cloning a96add4526
At this point you should check if the bug you are wanting to fix is still in the master branch. IF it is you will need to fork the repo and pull in that version to your project
Package Versioning¶
When working on a package, whether it is hosted open source on Github or hosted privately you will often find that you need to mark certain features as stable. Stability means that it is easier to pull your package as a dependency in a library in the future.
To give your package a version, you need to tag your current commit and push your tags to the repository. If you are using Packagist and it is hooked up to your repository correctly then the version will auto update.
When versioning, be sure to maintain a consistent versioning scheme, most developers follow some form of Semantic Versioning.
1.5.8 - Major.Minor.Incremental
A major version change usually means backwards compatibility breakages and other major changes, a minor version would be smaller changes or added features.
The incremental version will often be a fix or path for bugs.
To set your version, tag your repository with your desired version, Composer will try to fetch the package that resembles the requirements set as close as possible.
git tag 0.1.0
git push --tags
This will ensure that your tags are pushed up to your remote repository, you do not need a new commit to be awaiting push to be able to tag and push the new tag reference.
Forking¶
Find the project on github and press the fork button.
Update your composer.json file to use your version as a repository and pull in the source version so you can work on it, i.e.
"repositories": {
"my-example-repo": {
"type": "vcs",
"url": "git@github.com:edmondscommerce/example.git"
}
},
"config": {
"preferred-install": {
"example/example": "source"
}
}
Run composer update again to bring in the remote version. Note that if the lib has already been installed you may need to delete the current version, i.e. rm -rf vendor/example/example
composer update example/example
Confirm that this has worked by cd in to the directory and running git remote. This should now be pointing at your version of the repo
cd vendor/example/example
git remote -v
composer https://github.com/edmondscommerce/example.git (fetch)
composer https://github.com/edmondscommerce/example.git (push)
origin https://github.com/edmondscommerce/example.git (fetch)
origin git@github.com:edmondscommerce/example.git (push)
Create a new branch, update the composer alias to point at that branch e.g. dev-myfix
, and apply your fix
Push the changes up to your repo, and then make a pull request to the main repo.
If this is accepted then you can remove all of the above and go back to using the main repo.
Working on a Local Repo¶
If you are working on a library that is already on Packagist, but you want to bring in bleeding edge local updates, you have 2 basic ways of working:
1. Work inside the vendor
folder directly¶
You can bring in your dependency and as long as it was brought in as source
rather than dist
then it is a checked out git repo and you can work on it.
Simply
cd vendor/edmondscommerce/packagename
git checkout master
#do stuff
git commit -m 'commit message'
git push
2. Work in a separate project¶
Perhaps a cleaner way to work is to do this:
1. Bring in the dependency to your main project as normal using¶
composer require edmondscommerce/packagename
2. Also clone the repo as a standalone project in a separate location¶
cd /var/www/vhosts/;
git clone git@github.com:edmondscommerce/packagename.git
3. Open this as a separate PHPStorm project and work on it as normal¶
Simply as normal, open the folder using PHPStorm as a new project
4. Commit changes locally¶
cd /var/www/vhosts/packagename
git add -A;
git commit -m 'commit message'
5. On your main project, add a local remote¶
cd /var/www/vhosts/main-project
cd vendor/edmondscommerce/packagename
git remote add local ../../path/to/packagename.git
6. As required, pull in local changes¶
cd /var/www/vhosts/main-project
cd vendor/edmondscommerce/packagename
git pull local master
7. When you are happy with your changes, push them¶
cd /var/www/vhosts/packagename
git push
Warning
Don't forget to push your work to Github!!!
Composer Packages Best Practices¶
It is a very good idea to develop small defined packages that can easily be reused in other projects.
Here are some tips on the best way to do this:
Bin Directory¶
The bin directory is where you should put any command line tools that you want your package to expose.
The file can be a BASH, PHP or any other language you want although these two are most common and advisable.
Bash Command Files¶
Best suited for commands that will actually call other command line tools
Should adhere to standard EC Bash coding practices and implemement the standard Bash script header
Again should make proper use of exit codes.
PHP Command Files¶
Using PHP is the most obvious and is recommended for single use commands.
For complex commands with options, arguments etc then it is highly advised to use the Symfony Console Component.
For commands with no arguments then this is not required.
Finding and Including Composer Autoloader¶
To resolve the path to vendor/autoload.php
and then require it, the following code snippet is very useful:
#!/usr/bin/env php
<?php declare(strict_types=1);
$files = [
__DIR__.'/../../../autoload.php',
__DIR__.'/../vendor/autoload.php',
];
$autoloadFileFound = false;
foreach ($files as $file) {
if (file_exists($file)) {
require $file;
$autoloadFileFound = true;
break;
}
}
if (!$autoloadFileFound) {
echo 'You need to set up the project dependencies using the following commands:'.PHP_EOL.
'curl -s http://getcomposer.org/installer | php'.PHP_EOL.
'php composer.phar install'.PHP_EOL;
die(1);
}
Basic Rules¶
The file name should not have .php
on the end¶
This is just for aesthetics but is recommended
The file should have a shebang at the top¶
The first line should be a shebang that uses env
to associate the file with PHP
#!/usr/bin/env php
The exit code should be 0 on sucesss¶
To be explicit, your script should exit(0);
when it has run successfully
The exit code should be a positive integer on failure¶
To be explicity, your script should exit(1);
on failure. (Or another number if you prefer, though 1 is usual for "general error"
Adding Bin Commands to composer.json¶
To actually have you bin command available to projects that install your library as a dependency, you need to add something like the following to your composer.json
"bin": [
"bin/my-bin-cmd-script",
"bin/another-bin-cmd-script"
],
Packagist¶
Importing a GitHub project into Packagist¶
After importing and hooking up GitHub project to update Packagist, developers will be able to download your project
as a dependency using composer require edmondscommerce/somemodule --dev
Note
If you want to get the the most up to date dev version of dependency enter this instead
composer require edmondscommerce/somemodule:dev-master@dev --dev
. You can read more about branch aliases in here
- Go to Packagist repository submit page which is here
- Click button "Check" and if your Github repository will be found, click "Submit". After that, your packagist repository will get created.
- To sync any changes that are pushed to your Github repository with Packagist, you need to setup a "GitHub Service Hook"
- Got your GitHub repository
- Click "Settings"
- Then "Integrations & services"
- Then search for "Packagist" service
- Enter your Packagist username and token (press "Show API Token" button), which you can find in this page.
- And click "Add". This will create a Packagist service for your repository.
- To test if service is working, select the service and click "Test service button" in up right corner.
- Go back to your Packagist repository and check if you no longer see a message that your repository is not autoupdated. Or go to your packages page and check if it doesn't have words "Not Auto-Updated" nearby your repository. If it doesn't exists, you have successfully hooked Github repository with Packagist auto update.
Working with Modular Projects¶
Managing Multiple Git Repos in a Folder¶
Here are some basic bash tricks to help when working with git
Get paths to all repos¶
find . -maxdepth 2 -type d -name '.git' | xargs dirname
If you need to exclude some folders, you can do it like this:
for example, excluding paths that have /.folder/
type folder names in the path
find . -maxdepth 2 -type d -name '.git' -not -wholename '*./.*' | xargs dirname
Run command in all repos¶
To run a command in all repos, you can use the above command and then I suggest using a sub shell to run the command in the repo directory
For example, git status:
for repo in $(find . -maxdepth 2 -type d -name '.git' | xargs dirname); do (printf "\n\n\n$repo\n" && cd $repo && git status); done