Working on dependent, unpublished libraries with Composer - php

Let me first describe what I'm doing:
I'm working on two libraries, call them A and B - neither of these are public anywhere, and I don't want to publish them until they're stable.
Library A depends on Library B.
These two libraries are in separate, local Git repositories, and have individual composer.json files.
My problem is this: during development, I need a way to specify the dependency on Library B in Library A - which is simple enough, it's just an entry in the "require" section of Library A, and since nothing is versioned or committed yet, I'm specifying "dev-master" as the version requirement.
The issue is, library B of course does not really "exist" anywhere yet, as this is all local development on local Git repositories.
What I don't want, is I don't want to have to commit changes to Library B and having to do a composer install for Library A for every incremental change.
In fact, I don't want to "install" library B at all, as long as I'm just working on the repositories locally - that is, I don't want copies of Library B in Library A's vendor folder, I just want the generated auto-loader for Library A to point directly to my local Library B folder.
Surely there must be a way to do this? I have spent half a day searching and reading the documentation, blog posts, third-party guides, stack overflow questions, etc. - and found nothing.
Isn't this a totally common scenario and requirement for pretty much any developer?
Ideally, I also would like to be able to do this with a local file somehow - that is, I would rather not have to pollute my composer.json file with settings that are only relevant to me while I'm developing. But this is secondary - I can live with having to "hack" my local composer.json and avoid checking in the changes during development, but I cannot live with having to commit and install/update/copy files with every incremental change.
Any ideas?

It's not that common I think that people work on two brand new libs at once, but I agree we should support this better somehow.
I think the easiest/only way to do this is to install libB in libA using a local VCS repository definition (file:///path/to/foo/.git works), and then replace vendor/lib/A by a symlink to libA's folder. Just be careful if you run update because I'm not quite sure what happens in that case.
The other less pretty but perhaps easier way is to just develop libB in the vendor dir of libA, you can run install in libB's folder to get any dev dependencies. It's a bit ugly but not so dramatic IMO.

Related

Should I check in libraries in the vendor folder that are pulled in by composer?

I've already spent a few hours searching for an answer to my question but still haven't found a suitable answer.
Basically, I've taken over a PHP project which uses composer to pull in third party libraries/dependencies. However, a lot of the dependencies are no longer managed and is possible that the author might remove them completely from github anytime.
I'm currently thinking that I should check in the whole vendor folder so even if the libraries are no longer available through composer, I will still have them with me.
Alternatively, I could fork those libraries repo and have composer to pull from my account instead. Is this acceptable?
I would really hope to get some advice on the best method to deal with this.
Thanks in advance!
Should i check in the whole vendor folder in, so even if the libraries are no longer available through composer, I will still have them with me?
My suggestion is to create a backup branch containing your application with all it's vendors. Just do a git checkout -b {VERSION}-backup, followed by composer install (which gets you the composer.lock and all dependencies into the defined vendor folder) and then a git push origin {VERSION}-backup.
This allows to rely on dynamic package management as long as the packages are available via Packagist and downloadable from their source (Github, etc.).
Now, in case, a dependency gets deleted and becomes un-available, you remove it from your composer.json and merge the code from the last {VERSION}-backup branch into the master branch. = You replaced a dynamic dependency with a static one from you backup.
By the way: ever thought about getting a security audit for your code?
This will not work, with dynamically pulled dependencies. Security audits are done for specific versions - for a static set of dependencies. Given this context, pushing in a complete app with all it's dependencies is common and a best-practice. But what do we have: Composer in the backend to install new themes and composer install --no-dev --optimize-autoload on the production box to "install" software. Modern times ;)
Could I fork those libraries repo and have composer to pull from my account instead. Is this acceptable?
Yes! And you might also ask the guys over at Packagist to remove no-longer maintained packs or get them replaced or aliased to a new personal fork.
It really depends on whether your project needs to be optimized for portability or not.
Although, it's better safe with a best-practice violation, than sorry with an unavailable dependency you have to spend time replacing and refactoring for ...
From her packagist - theoretically it is possible but unlikely.
From the practice the main problem with packages directly connected to CVS. But if it is live project you allays can find another copy of code to recover functional.

Can we use Composer with sparse SVN checkout to share dependencies?

Our current development setup uses a single Subversion repository containing multiple projects, each with branches, tags, and trunk. We then use a "sparse checkout" to select the projects, and branches of those projects, to work with.
The result is that the directory structure of a working copy matches that of the repository, including branch information, and we never use svn switch. (This style of working will probably be familiar to anyone who uses SVN, but may be surprising to those who don't.)
We are thinking of using Composer to manage both external and internal dependencies, but I'm not sure how this can work with the sparse checkout style of working.
I would like some way of using a directory within the existing checkout to satisfy a dependency, rather than each "root project" needing a separate copy.
For example:
sites/Foo/trunk
depends on lib Aaa, so references lib/Aaa/trunk
depends on lib Bbb 1.5.*, so references lib/Bbb/branches/release-1.5
sites/Bar/trunk
depends on lib Aaa 1.0.*, so references lib/Aaa/branches/release-1.0
depends on lib Bbb 1.5.*, so references lib/Bbb/branches/release-1.5
At present, if I edit the code in lib/Bbb/branches/release-1.5, I can test those changes on both sites, without needing to commit one and update the other.
Is there any way of using Composer to manage these dependencies?
(PS: Please don't answer with "give up on SVN, use Git, it is teh awesomez"; that is an answer to a different question.)
No - I do not believe that you can do this with Composer as standard: it expects to copy the files from whichever source (Packagist/VCS/Zips) to the local vendor folder, which is not what you want.
That said, I believe there are two potential ways you could get this working (at least in part):
Autoloader
You could try using the autoload field in the composer.json file to include the correct files into the project. You would still need to manage the checkouts of the relevant branches/versions manually (like I assume you do now), but you would be able to manage the inclusion of the internal libraries through Composer. This will probably require that your libraries are properly namespaced. The paths to the files for each namespace are relative to the root of the project, but can go below the root (via the /../ path) if required.
To be honest though, if you already have an autoloader for these files, there may not be much advantage to this solution. Relevant Docs
Composer Plugin
You could also write a composer plugin/"custom installer" that could probably manage this. This would have the advantage that you could have it manage checking out the correct parts of the sparse repository to have the correct version available, as well as doing correct wildstar version checking, but would be a much more difficult and riskier venture.
The basic process would be that you would define a new package type (e.g. 'internal-svn-package'). You would create the plugin as an external library that gets installed normally via Composer, which declares (via it's composer.json) that it handles this new type of package. Your custom logic would then be used for any packages that are listed with this custom type. I'm not sure how much of the internal composer logic for SVN checkouts you would be able to reuse however. Relevant Docs

Using Composer, can dependencies be shared between multiple projects?

First of all, I'm a complete newbie to Composer. I've been trying it out since it's a sounds awesome and mainly because Zend Framework 2 uses it.
Zend Framework 2 is actually also the reason for this thread.
It get the basics of Composer. But with my current server setup I have a request, which I can't seem to figure out if possible.
Let me explain.
I have multiple Zend Framework 2 projects:
/home/morten/sites/Project-1/
/home/morten/sites/Project-2/
/home/morten/sites/Project-3/
All of these projects should be running ZF2. When running composer in each project - each of them get their own separate download of the ZF2 Library files. Which is a bit redundant with my setup.
I have a complete and up-to-date download of ZF2 Library located at:
/var/www/shared/Zend/
And my php.ini has that path added to PHP's include_path, so the whole ZF2 library is available for all the three projects.
IS IT POSSIBLE to make Composer use in it's setup. Because if I try to change stuff and try things out in the composer files, then it just re-downloads Zend because it's a required component for other modules.
Can this be done? And if yes, how can I do it?
Hope I have explained myself good enough for you guys to understand what I'm trying to do and want :)
Thanks a lot in advance!
Regards,
Morten
You might be able to have one composer.json file stored in /var/www/shared/Zend, where you would put your dependencies and use Composer do manage them. Then all projects could include the same autoloader.
However, I wouldn't recommend that approach:
Your project's dependencies (composer.json) should be stored with your project. If you want to install your project somewhere else (for instance if you want to move one project to another server), you are missing the composer.json to install the required dependencies.
It will not be possible to update the dependencies of one project, without updating the dependencies of all other projects. If you want to introduce a new feature in Project 1, which requires a new version of a certain dependency, all other projects will get this new version as well - which might introduce backward compatibility breaks if an older feature that Project 2 relies on, is no longer supported. Since you can only have one version of each dependency, it is not possible for two projects to have different versions of the same dependency.
This approach might be useful if all projects will have the exact same functionality and code, but in that case you should probably merge them into one project.
In all other cases, I would suggest to use Composer the way it's supposed to be used: give all projects their own composer.json file and let Composer download the dependencies per project, in each project's vendor directory. The downside is that it'll cost you a little more disk space, but you'll get a lot of flexibility for it in return.

Is there a simple way to remove composer from an app or a framework

For example, if I want to remove composer from fuelphp... is there any easy way to remove composer?
I mean I ask to use fuelphp (or some framework else) without composer.
Since composer is part of the framework. You "Do" need it. Period. Otherwise you have to follow #Sven's advice.
Having said that, you often only have a need for composer on your development platform, since that is where you'll want to pull the new code or updates in.
It's perfectly fine to deploy your application (to a staging or production environment) without composer, and without the .git folders. You would not want to have updates pulled in in those environments anyway, all code on these platforms should be under your version control.
No, there is no "simple" way.
To do what Composer does, you'd need to have:
Download all the libraries in the correct version that are directly included.
Also download all libraries that are required by any library in step 1.
Repeat downloading new libraries in step 2 unless you do not find any new, i.e. you completely downloaded all these.
Then create an autoloader for every downloaded library depending on what every configuration for every library said has to be done, i.e. either register a PSR-0 (or PSR-4 if some libs like to live on the edge), or parse the whole source tree for occurrences of classes, interfaces and traits and create an array listing every such class name and the containing file name.
Last but not least find a way to place everything downloaded and created where the regular Composer results would be expected.
Doing this manually is not impossible, but it is ridiculous to do so.
While I do admit that Composer makes it a little bit harder for the uninformed hobbyist programmer to fiddle with his home-brewn scripts when trying to download a new library because he now has to get to know Composer, in the end it makes the lives of everyone much easier - the time invested into getting to know Composer is well invested. Composer will not go away soon. In fact, every other language has something like Composer for a very long time, and nobody complains or tries to remove these dependency managers there.
FuelPHP from version 1.7+ (I think) requires composer, you would have to modify the autoloader to prevent it from trying to use composer's autoloader. This is not advisable as it means it becomes harder to keep up to date with maintenance releases.
Unfortunately for you composer is rather widespread and so is something that you will have to use if you continue working with frameworks. Fuel ships with a version of the composer.phar so you don't even have to go to the bother of downloading/installing it on your system.
If there is no dependencies, you can always simply do something like :
set_include_path(dirname(__FILE__).'/framework_XYZ');
spl_autoload_extensions(".php");
spl_autoload_register();
without forgetting to change the "framework_XYZ" by the directory where the core/system classes are hiding... ;)
J.

What's the best way to develop a library using composer?

We're starting a new project, and we're managing dependencies with Composer. We'll probably build our app on top of Laravel 4. But we'll also create our own library, which we will use for all our next projects, not just this one.
So, we have this terrible doubt: what's the best way to develop a library using composer?
If we list that new library as a dependency, every time we modify it we will have to commit the change to the repository and then call composer update.
That seems terrible!
Is there a better way to do that?
I think there are two ways to handle this, which I use depending on the case:
The library is a pure library, which is standalone, fully tested, and develop it using TDD to ensure that it all works. That way it can be used with the "commit, update" cycle you described just fine I think.
You are developing a plugin or something that must be integrated in something else (application/framework) and testing it standalone is more difficult, or you are developing it very tightly with your application. In this case require the dev-master version of the library so Composer installs it with a git clone (if it was already installed as a tag you will have to rm -rf vendor/your/library to force a reinstall as opposed to an update). You can also force this for tagged releases using the --prefer-source flag. Then once you have a clone in the vendor dir you can very easily work directly in there. If you do work in a team though you will still need to do this commit and then update to make sure the others get the latest version.
The third alternative is to just develop the code in the src/ directory of your application until it is mostly stabilized and then you can extract it as a new package and add it back as a dependency, then fall back on the first two ways I described because it will then be a lot more viable.
If you set the dependency to the repository master branch instead of a packaged distribution file, Composer will check out a working copy into the vendors folder. You can modify this working copy right in the vendors folder, as if it's part of the main project, but then commit it into its own repository. You'll indeed have to make sure to composer update after that to keep the composer.lock file in sync with the development of that library though.
It's still the more convenient way to develop a project in tandem with a dependency.
If you aim to develop a truly awesome library, then you should try to develop it independently of any other software you create.
It should fulfill one exact task only. And this probably is done after some commits, so the initial creation of the library should take only a week or two to come to a stable first version. And this version can be tagged and then used elsewhere.
When tagging, strictly try to follow semantic versioning - that way you can use the library with a version restriction like "~1.0", meaning at least version 1.0, but anything up to 1.9999 is acceptable, as long as it is not 2.0 (which would mean incompatible changes).
And then you really do not need to update any other software when you release a new version of the library. You only need to update if you want to include fixed bugs. Without bugfixes, you can update, but there is no need to do so immediately after the library's new version release.
Composer will take care of all the dependencies you need. The most important thing if you start a new library is to include the composer.json right from the start into the repository.
What if you really want to always include the newest release of the library in every other software you write? I'm not sure you realize the implications this has. It means that you are strictly binding your other software to the most recent library version. Break that version, or introduce a nasty bug, and all your software breaks. So being able to update or not actually is a feature. You will find that all foreign libraries you might use will follow the same release mechanism: They tag a new version if an important bug was fixed, or if a reasonable amount of new features was implemented. They do not wait for you to approve a new version - you have to approve THEIR new version in your software by explicitly updating to the most recent one. And the same should apply to an internal library.
Try to avoid fiddling with "dev-master" solutions mentioned here. They might work, but Composer works best if used with tagged versions. If you have a reasonably stable state of your library, tag it with "0.0.0" and include that version everywhere else instead of "dev-master". And then tag according to semantic version rules.

Categories