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.
Related
I'm building an SDK for developers to use to build modules for ecommerce platforms that will consume our API for a new startup.
Obviously it would be ideal to use composer, which I am doing right now. But as I examine most of the ecommerce platforms out there right now, or at least the most popular ones, they don't use composer.
So I'm wondering what's the best way to get all the dependencies all my current packages need and build them into a freestanding SDK.
This way I can have a version that will work for both composer and non-composer enabled platforms.
Is there a standardized way to do this in terms of a design pattern? How would I lay out all the dependency packages in any organized way?
Because those e-commerce platforms don't use composer, that doesn't force you to exclude composer from equation. You can't distribute your package as a plugin/module/whatever for that particular e-commerce platform, but you can still use composer's autoloader in production.
You could prepare the package for deployment on your machine or on a build server, archive the result and distribute the archive.
For the sake of simplicity, my example will assume that you will prepare your package on your local machine:
Create a temporary working directory:
$ mkdir -p ~/.tmp && cd ~/.tmp
Clone your package:
$ git clone <package>
Install dependencies1
$ cd ~/.tmp/<package> && composer.phar install --no-dev --optimize-autoloader
or if you do this from an automated tool:
$ cd ~/.tmp/<package> && composer.phar install --no-ansi --no-dev --no-interaction --no-progress --no-scripts --optimize-autoloader
Remove .git directory.
Create the zip/tar archive from ~/.tmp/<package>
Distribute the archive.
Assuming that your package is already a plugin/module for that e-commerce platform, it can be installed as usual from that zip/tar archive.
1) Regarding --optimize-autoloader, please read this answer from Sven, which explains why in some cases doesn't help your application to become faster.
Don't have dependencies!
Yes, seriously. If you'd develop an API client that would use Guzzle as the HTTP client, you'd have to make a choice: Use Guzzle version 3, 4, 5 or 6?
Guzzle 3 is out of maintenance and abandoned. You wouldn't want to use it.
Guzzle 4 is also considered end-of-life, because version 5 came very fast. Nobody really use this version.
This boils down to using either version 5 or 6. But Guzzle is using the same namespace and likely the same class names in both versions, but is incompatible to each other. No matter which version you choose: Your customer will have made the opposite choice - and now you have a codebase where two versions of Guzzle are running at the same time - this will not work.
If you don't have dependencies, but deliver everything within your own codebase, you have all of your code under your control, and are reducing the need to use Composer as a tool to easily install all your dependencies. Your package will have everything already included, it's unlikely that there will be any namespace conflicts.
You'd be able to offer a ZIP file for download. And if you additionally offer a composer.json to allow developers to include your package that way, everyone will be happy.
Update
Now after finding out that everyone thinks I am crazy proposing not to use stuff invented elsewhere, I challenge you to think about the situation once again: You find that you have to produce code that will likely be included in a codebase that is NOT managed with Composer. That means you have no idea what kind of software is put together there.
It may simply be so that you have a version of Guzzle in the existing codebase - undetectable, because there is no composer.json. Now you provide your own package with a bundled Guzzle version (whatever way made it appear there). This will likely crash the entire software at some point because of conflicts, because the autoloading will of course be merged at some point, and then some part of the code will request some Guzzle class to be loaded, which is included twice from two different versions of Guzzle.
WHAT SHOULD HAPPEN IN THIS CASE? THINGS WILL CRASH!
And it is unavoidable that this will happen. Even in the lucky case of being able to use Composer, it will conflict - the software won't crash, but the entire package won't be installed. The good thing is: You will notice this immediately.
If the primary goal is to deliver an API client anyone can use in every situation, without using a dependency manager: Don't have dependencies!
Alternatively, be completely sure that you know which software is already being used, and create a package that will not conflict in any case. However, this is still an effort, because there might be other addons also being installed, which might include conflicting software.
My central point is: If you don't have a dependency manager like Composer being able to manage the dependencies, you are better off NOT to have dependencies in your own code to make it super easy to include your own code in someone else code base.
And the question above clearly states that Composer is not an option in the general case.
Now there is one light at the end of the tunnel: When it comes to general tasks, the PHP-FIG has started to standardize interfaces that should leverage interoperability. For HTTP, the standard is PSR-7.
You COULD provide an API SDK that depends (and brings with it) the PSR-7 interface and requires the user of the SDK to provide a HTTP client that implements this interface.
The problem with this approach I see is that you will still run into trouble if you try to use for example Guzzle for the same reason: The only valid choice now is to use Guzzle 6 for the SDK - what if Guzzle 5 was already used elsewhere? Conflict! The good thing is: You can avoid using Guzzle 6 if you are already using Guzzle 5 by using any other PSR-7 capable HTTP client.
I wonder if someone can help me. I've been handed in a Cake PHP app that I need to 1) add minor changes 2) deploy. I've never really worked with Cake before and was wondering whether do I need to anything in order for it to work?
For instance, With a Node app, you need to install modules npm install. With a Rails app you'll likely need to install the gems bundle install.
Is there something similar with Cake? I've set the localhost server, but when I try to access the url I get all sort of errors. Some I've fixed (missing environment settings which I just override the Redis host and port). The latest one is:
{
"exception":{
"class":"MissingControllerException",
"code":404,
"message":"Controller class Controller could not be found.",
"file":"\/Library\/WebServer\/Documents\/php\/oompbe\/vendors\/cakephp\/lib\/Cake\/Routing\/Dispatcher.php",
"line":154,
"trace":[
"#0 \.../app\/webroot\/index.php(109): Dispatcher->dispatch(Object(CakeRequest), Object(CakeResponse))",
"#1 {main}"
]
}
}
PS: What's up with all the crazy \/\/?
PPS: Can I find out the version Cake I'm running?
CakePHP is just php. As most properly done php apps these days it comes with composer. I recommend you to read at least the basics of it's manual. Composer is an awesome tool.
git clone <repo>
cd <reponame>
composer install
If you start a new Cake application the official documentation tells you how to this as well:
composer create-project --prefer-dist cakephp/app [app_name]
If you want to automate things further composer provides you callback scripts. They'll allow you to automate tasks, basically trigger commands, after different actions. This is pretty useful to build assets after a composer update for example. I recommend you to not put lots of commands into that section but instead have dedicated script files you trigger by the callbacks.
Can I find out the version Cake I'm running?
If installed via composer it is usually in vendor/cakephp/cakephp/version.txt. Check the content of that file.
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'd like to run phpunit on an external server, the feed those results into a Jenkins plugin like the Clover PHP Coverage Report action.
The code base has some library dependancies that the owner of the Jenkins server does not want deployed.
Well with some tweaking I guess it is possible to make use of the monitoring external plugin. You will have to figure something out to get the files on the jenkins server.
An other option is, if the server owner is willing, to create a specific build agent for your needs. That doesn't affect his jobs and you can use your builds like you want.
Yes, library dependencies shouldn't be installed globally on a Jenkins server, but this is where Composer comes into play: You'd essentially install exactly the dependencies your current software needs locally in the workspace of your job.
Nobody should be bothered by this, because you could also include the needed library code there manually - or even worse, you could use the same file and class names and code something entirely different. All of this must not interfere with any other job running on that same server, and it doesn't.
You can't really avoid Composer, because PHPUnit will stop being distributed via PEAR, as well as some Symfony components that are being used. Better go to the Composer project page and learn how to use it. By the way: You can include the needed version of PHPUnit with Composer as well, so you need not rely on a centrally installed version (which is hard to update because there are so many jobs that would need updates then - too much work in one go).
I am working on a PHP application that uses many features from PEAR. The app is meant to be distributable kind of like Wordpress but really scaled down.
Now the problem I've run into is that PEAR needs to be installed and configured alongside the PHP server without which my app simply will not function unless the users go through all the painful steps of installing PEAR on their server. Users can very well be newbies or non-technical so it's not an option for them.
Therefore there is a need to somehow package everything PEAR into the application itself. As far as I know it may not be possible.
Are there any alternate solution to this? Any solution at all will help. Thanks..
PEAR installs system wide dependencies which makes things like what you describe hard. Composer on the other hand is exactly what you'd need, because it's a per-project dependency manager with much better support for resolving and installing of dependencies. Basically, compared to Composer, PEAR sucks... it always did, Composer on the other hand rocks!
The first thing I would do for each package you need is to see if it is also provided on https://packagist.org/. If it is, problem solved, include the installation into your build process with composer. If you end up with only a few packages from PEAR, you have several options:
inspire the author to provide it on packagist
make your own mirror on packagist (not recommended but sometimes necessary)
see if the project is on github and install directly from git with composer
install the PEAR package via composer anyways, it's possible.
Short answer: switch to composer!
If you are talking about the PEAR packages or class files, you can put the PEAR packages anywhere you want. Just put the ones you use into a dir within your app dir structure and add that to the include path.