I have a Symfony 2.3 project and I would like to use a custom vendor. I know that on Symfony versions 2.1 and 2.2, you can declare vendors in the deps file.
But how can I declare a custom vendor in Symfony 2.3 project? There is a composer.json file, but I don't really understand how it works.
EDIT:
The custom vendor's code is located on github.
composer.json manages dependencies through the composer tool (which you should have installed). It behaves similarly to npm if you have used that at all.
You can include a custom vendor in a couple of ways - although for the custom vendor code to be (auto)loaded & picked up by composer it will need to have a composer.json file.
Packagist
If the custom vendor has successfully submitted their to packagist then you life is easy, you can search for it and take note of the name (in the <vendor>/<package> format.
Open up your composer.json file and at the end of the "require": {} statement add your vendor. For example if our package was called peterjmit/awesome-package
// ...
"require": {
// ...
"peterjmit/awesome-package": "*"
},
// ...
You can replace the * with a version number if you wish. Once you have done that, you can run the composer update command to pull in your new package. If you only want to update the new package you can use composer update peterjmit/awesome-package.
Thanks to the composer autoloader, and the PSR-0 standard, classes from the package are auto-loaded so there is no other "plumbing" for you to do.
VCS repository
If the custom vendor is not on packagist, but does have a composer.json file then you can specify a custom repository to composer. You need to have the same require statement as before, but you need to add a new statement to composer.json
// ...
"require": {
// ...
"peterjmit/awesome-package": "*"
},
"repositories": [
{
"type": "vcs",
"url": "git#bitbucket.org:peterjmit/awesome-package.git"
},
// .. etc.
If the package does not have a composer.json then you can always fork it and add your own. But if the code does not conform to PSR-0 then you will have to sort out your own auto-loading strategy for the package.
Related
Hi I'm trying to develop a package in Laravel 5.1. Thanks to help here I have the basics set up.
My current problem is how to load dependencies for the package while I'm developing it.
In the packages composer.json I have added dependencies and have these installed now in a vendor folder within my packages development folder. This is not the frameworks root vendor folder.
Here's my require section of the packages composer.json:
"require": {
"illuminate/support": "~5.1",
"php" : ">=5.3.0",
"google/apiclient": "dev-master"
},
Because they are not part of the main autoload process what is the best approach to ensuring the dependencies for my package are loaded correctly from within the development folder? How do I include the autoload? I'm concerned that if I reference them to their current location/namespace that it will break when later installed as a package in another app.
in my code I have the following:
$client = new \Google_Client($config);
which gives the error:
Class 'Google_Client' not found
I can get round this by adding this dependency to the main composer.json but don't think that is the correct approach to keep the package development independent (if that makes sense)
When I developed in L4.2 there was the workbench which took care of the loading which of course no longer features in L5.1
Any help and best practice appreciated
Because they are not part of the main autoload process
I think you misunderstood how composer dependencies are managed. When in your main compose.json file you list a dependency, composer will add it to the main autoload process as well as all their dependencies, and the dependencies of their dependencies, and so on recursively.
You don't have to worry about where the dependencies are stored or how Composer will load them. Composer will automatically add them to the autoload file and all you have to do is make sure you require the composer autoload file. Once you require the composer autoload file, all the classes and functions loaded by composer will be available. Provided you required the composer autoload file all you have to do to use the classes from any of the installed packages is to make sure you address them using the proper namespace. Composer is smart enough to know where all classes are stored and how to load them (that is what psr-0, psr-4,... are for).
So if you are developing a Composer package, lets call it 'A', and you list the package 'C' as one of the dependencies of your package 'A', composer will add it to the autoload file for you. If you use another package, lets say, Laravel, which has a dependency of you package 'A', then also the package 'C' will be available within Laravel, since it is a dependency of 'A'.
I.e: If this is your composer.json file
{
"name": "foo/bar",
"require": {
"google/apiclient": "1.0.*"
}
}
This code will work
require_once __DIR__ . '/vendor/autoload.php';
$client = new Google_Client();
$youtube = new Google_Service_YouTube($client);
Note I've required the composer autoload file, which seems to be your problem. When you are using Laravel, it will add that file for you.
Ok, I'm using Yii2 and I am trying to add a new requirement/library to the project. Said library can be found here: https://github.com/cyphix333/SBBCodeParser
It is a forked project with an added composer.json.
I tried adding it as a requirement in the projects main composer file, ie:
"require": {
//..........
"samclarke/sbb-code-parser": "*"
},
Then I ran:
composer update
It just complained that it couldn't find the package or any version of it.
Then I removed that line and tried:
require samclarke/sbb-code-parser
I have the files already in my Yii vendor folder located at: #app/vendor/samclarke/sbb-code-parser
I'm pretty new to composer and am not sure what I'm doing wrong or how composer actually is supposed to know where to get the files from based on the package name.
The package samclarke/sbb-code-parser can be found at Packagist.
https://packagist.org/packages/samclarke/sbb-code-parser
By default Composer tries to resolve a stableset of packages.
But this packages doesn't provide a stable version (version tag), yet - only the dev-master version exists. Composer can not resolve it.
In order to require it, you need to lower your minimum-stability for this package to development.
You might do this for one package explicitly:
"require": {
"samclarke/sbb-code-parser": "dev-master#dev"
},
Or for all packages by setting:
"minimum-stability": "dev"
The package cyphix333/SBBCodeParser is not on Packagist.
It's a private fork. If you want exactly this code. You might add a repositories section to your composer.json and add repo with url and type with vcs there. Then Composer can load the package from the VCS repository over at Github. This is described here: https://getcomposer.org/doc/05-repositories.md#loading-a-package-from-a-vcs-repository
That would work like this:
{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/cyphix333/SBBCodeParser"
}
],
"require": {
"samclarke/sbb-code-parser": "dev-master"
}
}
But unfortunately, the fork is also not well maintained and doesn't contain a valid composer.json file.
[Composer\Repository\InvalidRepositoryException]
No valid composer.json was found in any branch or tag of https://github.com/cyphix333/SBBCodeParser, could not load a package from it.
This needs to be fixed first....
I have two packages that was pulled to my project with composer.
I don't want to have composer pull updates on these packages from anywhere and don't want composer to try and override my files with any repository.
If I remove the packages from my composer.json file it deletes the packages an removes the autoloaders.
How do I get composer to leave the packages alone and allow me to work on the code without losing the files or autoloaders on update.
I figured out how to do this.
What you want to do is create an artifact directory.
Thus in your main composer.json file you need to do something like this:
"repositories": [
{
"type": "artifact",
"url": "custom/artifact/"
},
..........
the url var should be the file path to the zip files relative to composer.json file.
Now you only need to add a composer.json file with a name and version to a zip file.
If the package already contains a composer.json file you only need to add a version.
example:
vendor-package-1.0.zip needs a composer.json file with:
{
"version": "1.0",
"name": "vendor/package",
"type": "library",
........... etc
}
It is important to define the version in the composer.json file or it will not find it.
Now you call this package by version from your projects composer file:
"require": {
"vendor/package": "1.0",
Now you can create and update files in your package without the worry that some online change or offline server will cause any problems.
As long as the version stays the same it should leave your files alone.
The good thing is that files added or removed will still update the autoloaders as specified in the zip package's composer.json file.
Give a specific version for that package, so it will not be updated when new versions come up
If you don't have too many packages, you can use
composer update package1 package2
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.
My project relies on ZF and on a JS library. I wanted to be able to deploy the ZF library to the normal location (vendor/zendframework/zendframework1) but then deploy my JS library to somewhere else (public/my-vendor/my-library). Is there anyway to do this?
Composer is meant to manage your PHP dependencies, not JS.
Also, it only supports one vendor folder.
You might follow the way Symfony bundles use:
install everything in vendor
link (or copy) public assets to a public directory as part of your deployment process
In my opinion it's safer than installing something in a public folder (as long as you copy/link public part of a library only).
I came across the symlink idea but I wanted to automate this instead of manually creating the symlinks. I was going to create a composer script to create the symlink. I then found that symlinks on Windows and *nix need to be created in different ways which made this solution get messier by the second. I found that in the composer docs they talk about this same type of issue on the custom installers page and say that to solve this to create your own custom installer.
Relavent docs section: http://getcomposer.org/doc/articles/custom-installers.md
My custom installer: https://github.com/ddelrio1986/zf1-public-asset-installer
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.
By default, Composer reads composer.json schema. But, it can also use a different file. For instance, you can have zendframework.json and my-library.json.
In the zendframework.json, you can define:
"config": {
"vendor-dir": "zendframework/vendor"
},
In the my-library.json, you can define:
"config": {
"vendor-dir": "my-library/vendor"
},
Finally, you can update the libraries in this way:
COMPOSER=zendframework.json composer update
COMPOSER=my-library.json composer update
This is a simple idea. The benefit is that you solve the issue without third-party tools.