Composer install package with dev dependencies - php

How do I install a composer package with dev dependencies?
So for example:
When I have this package:
https://github.com/spatie/laravel-demo-mode
And I run:
composer require spatie/laravel-demo-mode
The tests folder is not installed?!

In short you don't (ever). If you want to contribute, you need to set up new Laravel project and set up composer to autoload your version of package, either from your fork or from somewhere on your disk. And when you do that you are just using your version of the package (again without the possibility to run packages's tests).
In order to run tests of the package you need to change directory to the root of the package and install its dependencies ($ composer install), after you've done that you may run $ phpunit.
What I am usually doing in when I want to contribute is:
have empty Laravel project ready (unversioned)
have packages folder in root
in that packages folder I usually do $ git clone <repo fork> (It may be more than one package at once)
in case I want to run package's tests I do $ composer install and $ phpunit (your IDE may squeak at you about duplicate definitions but you may ignore it)
improve and test the code of package in packages folder
test your changes "live" on Laravel project right-away
composer.json may look like:
...
"autoload": {
"classmap": [
"database/seeds",
"database/factories"
],
"psr-4": {
"App\\": "app/",
"Vendor\\Package\\": "packages/path-to-src/"
}
},
...
You may find useful this example repo I use https://github.com/Kyslik/column-sortable-example to demonstrate how to work with package I maintain. Mainly take a look at folder structure and composer.json.
There may be better ways on how to do contributing but I have only found (and developed) this one.
If I have small changes in mind (like typo, or just return type or whatever is "small") I do change package within vendor folder, and see if it breaks anything; after that I fork package source and edit the change right in the Github's web interface. To clean up just run $ composer install/update from root folder of your Laravel project.

Related

Using PHP Composer to develop a local package and then copy it on deploy

I've got a local PHP project (a website), and I want to use another project I've made (a tiny web framework) as a Composer package for the website project. I'm developing them in tandem, but want to keep them as separate projects; when I deploy the website, I want to use Composer to install the framework project as a package, just like I would with Guzzle or any other common Composer package.
The website project has the following composer.json:
{
"repositories": [
{
"type": "path",
"url": "/local/path/to/framework/package"
"options": {
"symlink": true
}
}
],
"require": {
"my/framework": "dev-master",
"guzzlehttp/guzzle": "6.3.3"
}
}
In /local/path/to/framework/package/composer.json I have:
{
"name": "my/framework",
"description": "A tiny framework.",
"autoload": {
"psr-4": {
"MyFramework\\": "src"
}
}
}
I run php composer.phar update and it sets up a symlink to the framework package in my website project. If I update code in the framework, it's immediately available to the website code. This is great.
However, later on I want to deploy the website project to my web server. For a clean deployment, I have a deploy script that exports an archive copy of the appropriate branch of the website git repo, and then runs php composer.phar install to make sure all the proper packages are installed. With the above config, the deploy script creates a symlink to the framework package, which is obviously no good when the deployment artifact is zipped up and scp'd out to the web server.
If I remove the symlink option above, then I have to run php composer.phar update every time I make any changes in the framework package, which is irritating since I'm developing the packages in tandem. But then on deploy, the package is copied in, rather than being symlinked in; this is good for deploy, except it always copies in the master branch (because I specified dev-master in composer.json).
Is there a way to set up Composer so that I can have the convenience of a local symlinked package for development, but to let the deployment script get a clean copy of the framework package, without having to change composer.json every time I want to deploy?
I also tried changing the repository type to vcs instead of path, but then Composer clones the framework package repository, and I really don't need a clone of the repo in my local vendor/ tree, either during development or deployment. I just want to be able to have a symlinked tree (which gets me instant updates) during development, and have a clean package installed for deplotment.
I may have to resign myself to developing the framework project "properly," that is, as a Composer package that I tag with actual release version numbers, and then update my website project to use a specific version of when it comes time for a deployment. I still haven't figured out the easiest way to do that, though.
You can use Composer Studio plugin.
It uses a separate file for configuration and allows you to have symlinks in development and a regular Composer install for prod deploy, without touching composer.json.
With it, your website composer.json will look like a regular file:
{
"require": {
"my/framework": "dev-master",
"guzzlehttp/guzzle": "6.3.3"
}
}
And with studio.json in the root of the project, with the following content:
{
"version": 2,
"paths": [
"/local/path/to/framework/package"
]
}
you can tell the plugin where to locate my/framework. Studio will then symlink the packages from the provided paths.
To have a regular install, just remove or rename studio.json, remove the vendor folder and composer.lock file and run the install again when deploying.
I made a composer plugin to make it more easy to test packages.
It doesn't require a configuration file, changing your composer.json and doesn't change the upgrade behavior of composer update
https://github.com/SanderSander/composer-link
It works as simple as calling composer link ../path-to-package to link the local package into your project.

Composer.lock, composer.json workflow and version control

I thought the workflow with composer was like this:
Define your dependencies and other data in your composer.json
Run composer install or later composer update
Include composer.json and composer.lock in your versioned repository
After cloning your repository, run composer install and you're ready
But, at step 4, when I clone my repository to the remote server and run composer install I am getting an error
[ErrorException]
Undefined index: hash
A quick search says that I have to delete my composer.lock, which is up to date with my local repository. So, what am I doing wrong ? Isn't composer.lock there to make sure that both my repositories have the same versions on the included dependencies ? I don't feel like it should be excluded from my repository ...
UPDATE
And I see frameworks like OctoberCMS to include composer.lock into their .gitignore. I'm really confused, composer's documentation clearly states that the composer.lock is the one that actually locks your dependencies to the same version, composer.json is just the guidelines on what version to pick.

Where do PHP Composer Packages Come From?

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. :)

How to clone repository with Composer without --prefer-source? (using Symfony 2)

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.

Use composer to install bundle in custom directory

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.

Categories