I'm working on a project which contains couple of parts written in different languages. One of these parts is a PHP application. When distributing the project there is a phase to distrib this PHP app. I use Phing for that. So apart from other dependencies, I have
"require": {
"php": ">=5.3.13",
"phing/phing": "2.7.*"
}
As composer.json in Phing package suggests, Composer creates autoload_classmap entries for Phing. There are some Phing targets that copy vendor libraries further, but they don't copy Phing itself (it's not a runtime dependency for PHP project itself). As a consequence, there are many entries in autoload_classmap that are problematic. My application itself uses classmaps so I want to use the mechanism but not for all packages.
Is it possible to suppress generation of classmap entries on a per package basis ?
This is probably a hen-and-egg problem, but I think Phing does not belong into the softwares dependencies, so it has to be taken out. Problem with the classmap solved.
Where does it belong? It is infrastructure you have to install to deploy or distribute the software. Phing should be installed on the machine executing the deployment, or anywhere else where it is needed, but this is part of the infrastructure requirement for this machine.
You can use Composer to install Phing globally (it's way better than using PEAR for this). Or you can create a deployment project that includes Phing, probably other stuff, and has the task to deploy/distribute that software.
Related
There is a main application, let's call it APP.
APP has several dependencies (including open source projects and proprietary libraries).
There are multiple clients that use their own instance of APP (on different domains that I manage). Some of these clients use a slightly adjusted version of APP. I implemented this by creating a specific module (let's call it SM) for each client that I just add to their instance of APP (so that I don't change any of the code from APP).
Currently, I've implemented this as follows:
Develop APP locally, use Composer to update its dependencies (composer update), push APP on central repo
For each regular client, pull APP from central repo and install the Composer dependencies (composer install)
For clients with specific implementation, create a new SM (specific module), that has the following composer.json file:
...
"require": {
"APP": "X.X.X"
}
...
Then apply the same steps as before for this SM (composer update locally, PUSH to central repo, PULL from central repo, composer install).
Everything is fine, except for two issues that I'd like to overcome:
composer.lock from APP will be ignored by SM (since APP is loaded as a library in the vendor/ folder, and composer ignores the composer.lock files of libraries); this is not good at all, as I will not be confident that the specific clients will use the exact same libraries as APP.
Each time I fix a bug or implement a new feature in APP (and this happens frequently - a few times a day), apart from the steps that I perform for the regular clients, I also need to rebuild the SMs (since one of their libraries - APP - was updated to a new version that I need to use). This is an overhead since most of the changes that I perform are inside APP (and not SM). So, if it was the other way (APP having SM as a dependency), it would have been working faster (since I wouldn't need to composer update on each SM).
Are there any known workflows or best practices that cover this scenario in order to mitigate the two issues above or at least to decrease the complexity of the upgrade/deployment process?
Please note that most of the steps above are already automated, so my question is not about the automation part, but the complexity of this architecture
I implemented this by creating a specific module (let's call it SM) for each client that I just add to their instance of APP
For clients with specific implementation, create a new SM (specific module), that has the following composer.json file:
It's an application with a client specific module (next to other dependencies).
The application has the module as dependency (APP having SM as a dependency).
And not: the module pulls the application as it's vendor dependency in.
This will only cause extra steps to take during the development phase (your issue 2).
I would suggest to refactor the application and it's modules until you get the following folder structure:
|-application #< the application has dependencies
|-src
|-tests
|-vendor
|-framework #< maybe your application is framework based
|-libs #< more dependencies
|-... #< other modules
|-sm #< the client specific module
This allows to pull in dependencies, which extend "the application" for client-specific needs.
This overcomes your issue 1, because APP is the main repository and contains the lock file. It's essential to lock the versions, so that all developers are bound to the same versions and also for packaging exactly the same set of versions.
So, if it was the other way (APP having SM as a dependency), it would have been working faster (since I wouldn't need to composer update on each SM).
Yes! The need to rebuild the module, each time you change APP would vanish, if you start to "develop inside APP" with module dependencies.
And for multiple clients, simply use multiple application repos, which have a custom set of requirements. 10 clients, 10 application repos, 10 composer.json files. Run composer install no-dev then pre-package each repo and place zip into downloads. Done.
You can use a "container" or "packaging" project here, where the composer.json of each project would include the app and the specific modules. You might utilize the caret or tilde operator to specify a version range for the app ("vendor/app": "^1.2.3") and then simply update and repackage, after a new version of the application is released. This approach should work with the composer autoloading, because the application will remain inside the vendor folder, too. Only a little wrapper is needed, to set the composer autoloader up and switch over to your application.
Or, if the application is really modular. Just package the main application and provide the client-specific modules as extra downloads. With this approach upgrades will have multiple download steps: upgrade app, upgrade modules. Think of it as "wordpress-style" updates/upgrades.
You might reduce the complexity of the upgrade/deployment process further by dropping the composer install --no-dev part on the client machine
by building "client-specific application archives" on the developer machine.
These are basically the "--no-dev" package of the application with all it's dependencies, including the client-specific module(s) = pre-packaged.
Like, Application-v1.2.3-WithModuleAForClientA-v3.2.1.zip.
On the dev machine: composer install --no-dev --optimize-autoloader + zip.
To install or upgrade simply download to the client, extract, execute the upgrade script. Done.
I downloaded Laravel from github and save it on c:/htdocs/laravel1
and I created a copy of my laravel with CMD (with composer) and I install this as laravel2 in c:/htdocs/laravel2 directory.
Laravel1:
c:/htdocs/laravel1
Laravel2:
c:/htdocs/laravel2
And I have access to both of them in localhost:8080/laravel1/public/ and
localhost:8080/laravel2/public/
My question is : Why should I install laravel by composer? There is no different between the installed laravel and downloaded laravel.
There are many, many valid reasons to use composer:
Composer creates optimized autoloaders if you want it to
Allows you to add thrird party dependencies easily (just add them to composer.json)
You can track the composer.lock file, and use composer install to ensure the exact same versions of the dependencies are being used throughout (on all environments, by everyone contribbuting) This is a must-have, if you're using automated builds!
Updating all dependencies, including Laravel, is a simple matter of composer update
Composer supports post-install and post-update scripts, to be executed after a composer install/update is run. This is quite commonly used to prompt the dev for configuration parameters. Downloading the code means you have to edit the config files by hand, and worse of all: track them in git or svn
... I'll probably add more reasons along the way, these are just a few off the top of my head
Update:
Just thought of some more reasons why using composer is a good idea:
Composer packages themselves can, and often do, define dependencies and requirements. Things like "php": ">=5.4.0", or "ext-curl": "*" will alert you to any missing PHP extensions or a version mismatch. These requirements can also trigger composer to fetch additional dependencies. Which brings me on to the next point:
Laravel itself has dependencies: Laravel uses components from Symfony2, for example. The easiest way to manage its own dependencies is to use composer, seeing as Symfony does, too. If you run composer update, the dependencies of Laravel will be checked, and updated where needed. Doing this manually is possible, but it's tedious, and really not worth the bother. Repetitive, dull jobs make people grumpy. Computers don't have this problem.
Composer is a dependancy manager similar to node's npm which allows quick and easy management of 3rd party libraries & packages on a per-project basis.
I recommend reading https://getcomposer.org/doc/00-intro.md to find out more about composer and explore https://packagist.org to find out the kind of things that are available through composer
I have been using maven in JAVA and started using PHP Maven, recently I switched to composer.
My project is with Zend Framework 2 and the team only checks in the application code not anything on the vendor directory. This is done to avoid conflicts and not to have the libraries under SVN.
Now each time a developer sets his or her new environment, we observe that, the composer pulls the dependencies from internet. This takes quite a long time.
Is there any better idea/approach to make this faster or handling the project in different way to avoid this problem?
maven uses maven proxy servers which can cache the download and can be used in the network again, but do we have any solutions to handle problems like this?
Composer is a very young project, so there might be things missing which e.g. Maven can co without hassle.
You could set up your own Packagist server as described in the composer docs. I believe packagist has some caching options which can be used to store packages on the packagist server.
What you also could do is fork your dependencies and push them to a company-owned private repository. In your composer.json you would now only use this dependencies, making it faster to clone. Of course this would require you to maintain all the different dependencies (although this could be done with a script and a cronjob, pulling the data from the github repo and pushing it into your company owned).
I also believe composer has some proxy options, but I don't think these are meant to cache dependencies.
Last option would be to develop something like this, either as part of composer/packagist or as stand-alone.
In PHP there is an existing option for running a composer like repo locally and it's called Satis (it's actually provided by Composer) here: https://github.com/composer/satis
So you can run it locally on your server and point your composer to use that as a default composer repository and Satis makes sure that all installed packages and different versions are cached on disk as ZIP files so could be retrieved quicker compared to always downloading them from Internet.
You can do something like this:
{
"repositories": [
{
"type": "composer",
"url": "http://satis.example.org/"
}
],
"require": {
"company/package": "1.2.0",
"company/package2": "1.5.2",
"company/package3": "dev-master"
}
}
This also allows you to have private packages and libraries without exposing them on GitHub.
Another BIG advantage is when GitHub goes down for whatever reason you can still deploy as all of your dependancies are cached locally. This is assuming you haven't added new, non-existent packages to the release.
We created a ZF2 project with skeleton app and it works fine for a simple test application. Now we are working on a real project. My question is what we should store in the repository (SVN), the whole project structure or just the new source code? ZF2 comes with a vendor directory which is almost 31MB in size (which has the ZF libraries). Should we store the whole vendor folder in SVN?
This is the first time we are using PHP and ZF so are not clear in how we will deliver the complete project to production from SVN. Also what is the build process if at all exists. Any clues/links to "ZF2 project packaging" is appreciated.
No, don't include dependencies in your repository! Putting your dependencies under version control doesn't do any good, it just blows up your repo for no reason.
You want to add the skeleton to your repository and your own library but definitely not the framework or any other dependencies.
The way to go is to use composer for dependency installation and some kind of build tool like Phing to automate installation of your project.
See the relevant chapter on phptherightway for more information on how to build your application.
The most simple build process doesn't even need a build tool
checkout your project from SVN/git
run php composer.phar install to install the needed dependencies (defined in your composer.json)
But most probably you want to do some more stuff like setup up the environment, deleting some files, etc.
A word about ZF packages. They're not available from packagist but you can install them with composer anyways. You just have to add the dedicated repository to your composer.json as described here: http://framework.zend.com/downloads/composer
I want to use both Phing and Composer for my applications. Phing as the build system and Composer to manage dependencies. But which way around should they be used?
Currently we're installing Phing globally on all servers. Phing is supposed to completely automate the build of our various projects. Just checkout a copy of the project, run Phing with the default target and you should be good to. This also implies that there should be a Phing target in there that calls on Composer to install all dependencies. So, Phing calling composer. But I have been unable to find anything about this setup. There's no ComposerTask or anything similar and googling around doesn't reveal anyone working that way.
But I do see a lot of it the other way around. People using Composer to install Phing as a project dependency.
So, what are the (dis)advantages of each method? Am I trying to do it from the wrong way?
I think the main advantage of installing phing via composer, is that for open source projects it's easier to make sure your users have phing installed that way. Typically in those setups phing is just a tool used by some libraries to achieve some tasks.
The other advantage is that every project can use a different version of phing, which you can't do if you have a system-wide one.
If you use phing to manage your entire project build/setup, calling composer from it might make sense, but the other way around as well. For example you could use composer scripts to fire off the phing tasks after every dependency update. That way a project setup would be:
checkout
run composer
composer runs phing after updating/installing deps
project is built
I honestly don't know if there is a right answer. You can make both ways work, but by doing it this way you at least skip having to install phing first. Obviously you need to install composer instead, but arguably that's easier and you'd need it anyway.
Additional thoughts about this topic.
Generally Seldaek is right that both are possible. There are arguments for phing first too, though. On the level of build architecture I think composer first doesn't make sense. The build process has broader scope and longer lifetime and should therefore manage the dependency manager, not vice versa.
Furthermore, if you work with Phing token replacement to determine what dependency versions you want to install in which environment, it's close to impossible to go composer first because phing will generate the composer.json and must therefore be installed before composer can run.