When I run
$ composer.phar install
where do the packages that get installed come from?
I understand that Packagist is the default repository for PHP packages, and that lacking a different package in composer.json, this is where composer will look for packages.
However, what I'm not clear on is how Composer and Packagist interact.
Does Composer download files directly from packagist.org
Or does Composer get a git/svn/hg repository link from packagist and download the files from the repository directly?
Or something else?
It depends on the contents of your composer.json file.
For example, if your composer.json contained simply
{
"require": {
"phpunit/phpunit": "3.8.*#dev"
}
}
then composer searches packagist, and finds phpunit here:
https://packagist.org/packages/phpunit/phpunit
which tells composer to load phpunit from here:
https://github.com/sebastianbergmann/phpunit.git
If instead your composer.json contained
{
"repositories": [
{
"type": "vcs",
"url": "http://github.com/sebastianbergmann/phpunit"
}
],
"require": {
"phpunit/phpunit": "3.8.*#dev"
}
}
then composer will not look to packagist, but go directly to github to download the repo.
The packages registered on Packagist are usually the "authoritative" version of the package (not a fork), but I have found several instances where this is NOT the case, so you should check it to be sure you are pulling the package you expect.
Packagist.org offers users to register their software there by pointing Packagist to read their composer.json file that is published somewhere on the web.
The usual case would be some of the common open source hosters like github, which makes it really easy because composer can deal with such a git repo right away. You could however host your own git or svn or hg repository, or even just publish ready-made ZIP or TGZ files for each software version.
Composer downloads directly from the source, e.g. Packagist only knows those source and tells your composer instance where to go. It does this by downloading a bunch of json files from Packagist.org that have all the infos. This is way easier than to find out where the libraries that you want are hosted and add this info as a repository entry into your local composer.json file. :)
Related
I have a project with the following structure:
- src
----/ /* Relevant files */
- tests
----/ /* Irrelevant files */
- composer.json
- phpunit.xml
The project is sent to packagist on every commit already. But, it is sending the test files.
I'd like to ignore tests folder, so composer wont download unecessary files when someone calls composer require my/package
Here is whats the content of my composer.json looks like:
{
"name": "my/package",
"description": "...",
"type": "library",
"license": "MIT",
"require": {
"php": ">=7"
},
"require-dev": {
"phpunit/phpunit": ">=5.4"
},
"autoload": {
"psr-4": {
"MyProject\\": "./src"
}
}
}
Ignore tests folder when send to packagist
Let's first clear up some confusion.
When you enable Packagist for your repository, Packagist will load the composer.json to get metadata about your project and fetch the version informations from the tags/branches.
But you are not sending your PHP code or any tests to Packagist.
I'd like to ignore tests folder, so composer wont download unecessary files when someone calls composer require my/package
This question pops up quite often. I'm referencing a detailed answer, which i've written some time ago, which explains a lot of the background: https://stackoverflow.com/a/32476500/1163786
Usage of a .gitattributes file with export-ignore directive
Technically, you could add a .gitattributes file to your repository, which declares a export-ignore rule for the test folder.
This means that any git export will no longer have the tests folder, including the Github zip file.
Ok, exclude done..
But, when someone composer require's your project, it will now depend on the --prefer-dist setting to install the package from the dist (zip). (You would get the tests with --prefer-source).
If it is a small library, stop to worry. Be happy.. :)
If it is a bigger application, then a better solution is to package your application properly, instead of relying on the git exported zip distribution.
Most developers don't use a build.xml or any build script anymore, but that's the correct way to do it in my opinion.
That means once you are ready to tag a new release.
You trigger your build script, which fetches all the dependencies, runs the tests once more and when everything is ok, drop all the tests and packages the files for deployment.
Small hint: don't forget to add a autoload-dev section for your tests to composer.json.
If your Packagist package is linked to a GitHub repo, just create a "Release" in GitHub that does not contain the development files.
This works out-of-the-box for your end users, because Composer install/update uses --prefer-dist by default, which serves the package zip that is in the "Release".
The easiest way to do this (And it's how some Symfony packages does it, for instance), is to create a .gitattributes (as Jens suggested) with the following content:
/tests export-ignore
Now, when you create a tag/release in GitHub, the release zip won't contain the tests folder.
The only scenario where tests folder would be included in this case is if the user installed your package with --prefer-source, but if they do that, they should know what they're doing.
I have installed composer.
My project dir tree looks something like this
/home/myproject/public_html/myproject.com
I initially installed it in:
/home/myproject/public_html/myproject.com/bin/composer/
But later moved it to:
/home/myproject/usr/local/bin/composer
Questions:
Where to I create composer.json ?
In the official docs they mention that in order to install new packages I need to write a require key in the json format in that file, does this mean that I dont have to upload the package through ftp?
The docs further say that I can simply install dependencies like ths:
php composer.phar install
I dont understand the workflow of this process (im fairly new).. what exactly do I need to do to get some packages going (like Respect)
Composer has 2 basic elements for you to consider:
The composer.php file itself - this can be located anywhere on your system - usually it is convenient to have it in you search path so you can invoke it by name (no path) from the command line.
Composer.json - this file is the configuration for your project. This is usually best located at the top level of your project. Ideally this is a directory outside the scope of your web server - so that it will never be exposed or served.
Symfony2 has some great documentation and examples of composer in use.
Also be aware that some packages you reference via composer will themselves have composer files - to ensure they match your required dependancies - and they may also have their own dependancies that need to be considered.
I would install composer.json in the following
/home/myproject/composer.json
It would be out of scope of the web server and could be used to manage many assets e.g.
public_html/
libs/
config/
docs/
vendor/
Where to I create composer.json ?
You should create composer.json to your project root like /home/myproject/public_html/myproject.com/composer.json. If all files of your application live inside your myproject.com folder.
In the official docs they mention that in order to install new
packages I need to write a require key in the json format in that
file, does this mean that I dont have to upload the package through
ftp?
Yes as long as you're not in shared hosting because most of them don't allow CLI (SSH).
The docs further say that I can simply install dependencies like this
php composer.phar install
Yes you can simple type the above command and composer.json will install the latest version of your package.
Composer.json (Respect Package)
{
"require": {
"respect/validation": "dev-master"
}
}
Now run composer install will install the require package.
For further packages
{
"require": {
"respect/validation": "dev-master",
"doctrine/orm": "2.*"
}
}
Now run update composer update it will download the doctrine/orm as well.
I recently published my library in GitHub and Packagist. When I load it to a project, using the Composer, entire repo is being downloaded, along with the hidden .git directory.
How to prevent Composer from downloading this unnecesary directory?
Composer will clone a repository if you do require a development version. And if you reduce the allowed minimum-stability of your application, ALL possible packages are being cloned.
This is actually a good thing because you seem to be in development mode, and after the initial cloning updating these repositories is usually faster - and you can more easily edit these packages and push your changes back.
I tested your package, and it was correctly downloaded as a ZIP file with this composer.json:
{
"require": {
"mikemix/zend2-auth": ">=1.0"
}
}
And after deleting /vendor and the composer cache, it cloned your repo with this composer.json:
{
"require": {
"mikemix/zend2-auth": ">=1.0#dev"
}
}
Changing back to the above version, but not deleting anything, a run of composer update only checked out that tag, but did not download the ZIP file.
So Composer tries to minimize network activity, and tries to not destroy an existing repository, because that repo might have some valuable code committed in another branch.
Scenario: I am working with Symfony 2.2. In my list of required packages is also one of my github repositories, let's call it "TestLib".
I know that I can define the github url as additional repository in Symfony's composer.json to download "TestLib" via Composer from Github.
Problem: I cannot commit to "TestLib" repository as there is no local .git directory in the "TestLib" directory. I guess composer is fetching a zip from Github and not cloning it.
So my question is: is there a way to specifiy in Symfony's composer.json that Composer should clone TestLib?
Question 2: Maybe my workflow is wrong - so if you also have this scenario - how do you handle this?
Adding #dev to the package version clones the repository too.
{
"require": {
'package': '*#dev'
}
}
Also is possible setup source as preference in the composer.json
{
"config": {
"preferred-install": "source"
}
}
What I typically do if I notice that a vendor has an issue is rm -rf vendor/foo/bar to remove it and then I run composer install --prefer-source to get it back as a git repo.
What I did was add my github repo to packagist.org then I did this:
composer require malhal/createdby dev-master --prefer-source
This appears to add the require line to composer.json and also get it as a git repo, unfortunately this only works once so if you wouldn't be able to reuse the composer.json for a new install and would need to delete the require line and then remember to do this same command again. This command also downloads the git repo you don't have to do another composer update.
I see there is already a question but it did not answer the question
How can I install a composer package into the /src dir?
How can I install a bundle in the /src directory?
Reason I would like to do this is for development and deployment, so
I don't have to check in Symfony's base code into my subversion repo
I could use Composer to deploy
Looking over the Composer docs some more I did come across this:
http://getcomposer.org/doc/04-schema.md#config
vendor-dir: Defaults to vendor. You can install dependencies into a
different directory if you want to.
Could I set this at a Bundle level? or is this for the overall install?
https://github.com/composer/composer/blob/master/res/composer-schema.json
I know this is late, but in case anyone is searching for an answer that I painstakingly (hours and hours) found: vendor-dir
The documentation says:
By setting this var you can make composer install the dependencies into a directory other than vendor
Example:
{
"config": {
"vendor-dir": "website/password/vendor/"
}
}
From this doc and this doc
Again, hope to save anyone else a couple hours.
{
"extra": {
"installer-paths": {
"sites/example.com/modules/{$name}": ["vendor/package"]
}
}
}
Read more.
If you find composer's custom installers too complex or rigid, and you can plan what types of systems you will be deploying to, you might consider using post-install scripts.
Here's an example that creates a symlink from a package installed under vendors to the location where it might be expected:
"scripts": {
"post-install-cmd": [
"test -d vendor/foo/bar && ln -s ../vendor/foo/bar lib/bar"
]
}
This will create a symlink at lib/bar/ pointing to vendor/foo/bar/.
I have implemented this composer plugin to install packages into user (custom) defined folders you can just include it in your composer.json, follow the example and tell me if you have more questions :)
https://github.com/mnsami/composer-custom-directory-installer
composer-custom-directory-installer
A composer plugin, to install differenty types of composer packages in custom directories outside the default composer default installation path which is in the vendor folder.
This is not another composer-installer library for supporting non-composer package types i.e. application .. etc. This is only to add the flexability of installing composer packages outside the vendor folder. This package only supports composer package types,
https://getcomposer.org/doc/04-schema.md#type
The type of the package. It defaults to library.
Package types are used for custom installation logic. If you have a package that needs some special logic, you can define a custom type. This could be a symfony-bundle, a wordpress-plugin or a typo3-module. These types will all be specific to certain projects, and they will need to provide an installer capable of installing packages of that type.
How to use
Include the composer plugin into your composer.json require section::
"require":{
"php": ">=5.3",
"mnsami/composer-custom-directory-installer": "1.1.*",
"monolog/monolog": "*"
}
In the extra section define the custom directory you want to the package to be installed in::
"extra":{
"installer-paths":{
"./monolog/": ["monolog/monolog"]
}
by adding the installer-paths part, you are telling composer to install the monolog package inside the monolog folder in your root directory.
As an added new feature, we have added more flexibility in defining your download directory same like the composer/installers, in other words you can use variables like {$vendor} and {$name} in your installer-path section:
"extra": {
"installer-paths": {
"./customlibs/{$vendor}/db/{$name}": ["doctrine/orm"]
}
}
the above will manage to install the doctrine/orm package in the root folder of your project, under customlibs.
Note
Composer type: project is not supported in this installer, as packages with type project only make sense to be used with application shells like symfony/framework-standard-edition, to be required by another package.