I have been making a CMS as a project for a little while now, and am currently working on the plugin management section. Instead of building my own repository & update manager, I've been toying with the idea to use composer instead. The issue is I want the admins on the site to be able to add/remove plugins at will.
So I was thinking, how bad of an idea would it be to build a front-end which runs composer? Composer is just PHP after all, it's meant to be run on production environments (granted with a composer.lock file though), and it'd resolve all of my repository, update, and dependency needs.
I knocked out a quick test script, I built and passed in a custom configuration file (instead of composer.json, the installed plugins list is stored in the database), and everything seems to be working fine. But I can't shake the feeling of this being a bad idea.
Does anyone have experience with this, and whether or not it is a good or bad idea?
Using Composer as an embedded dependency manager with a front end is actually a very valid use case for it. Here are some links with information, as well as a project meant specifically to help with embedding composer into an application.
https://github.com/dflydev/dflydev-embedded-composer
https://sculpin.io/documentation/embedded-composer
http://srcmvn.com/blog/2013/05/23/symfony-live-2013-portland-embedded-composer
Related
I'm developing an application that consists of several modules/packages which i also want to offer as standalone packages. I know how to create composer packages but i'm not exactly sure on the best way to do the actual development and need your help on this.
One way would be installing the packages with composer but that would mean that, for each change, i would have to commit and then do a composer update on my app, just to able to test it. Not very practical.
Another way would be to have them included in my app, although having the package internal structure. That would work fine for developing but would pose a problem on publishing individual packages since all the code would belong to the same repository.
I think a good example on this is the way modern frameworks, like Laravel, are available. They have the whole code available in a repository but, at the same time, have each individual component available standalone.
What's the best way (in your opinion) to accomplish this?
Thanks in advance.
Symfony2 uses Git subtree split. That is, a single development repository which is split into multiple repositories later.
Don't make any mistake about it though, the code is the same, but they "are different" repositories, and the procedure to maintaining them is rather long winded.
http://www.craftitonline.com/2012/03/git-subtree-split-this-is-what-symfony2-does-every-night-to-set-standalone-components/
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.
I'm wondering what the best way (if there is a way) for an application to auto-discover [relevant] PHP "packages" installed by Composer.
My use case specific scenario:
I have a PHP app that includes my "framework" (for lack of a better word). This framework brings some basic functionality (routing, admin etc).
I'm slowly building in more advanced functionality, say, a blog module. This module is entirely self contained in it's own directory (but obviously has dependencies on the framework).
I'd like this blog module to be a self contained Composer package, so that I can selectively require the package in my app's root composer.json file.
Now, I need for the framework to know that it's there so that it can, for example, set the routing correctly and load up any admin functionality that the module requires.
What I've thought so far:
I'm relatively experienced in PHP, but "proper" OOP and autoloading is a little bit beyond my knowledge at the moment, so please forgive if there are inbuilt functions to do this. I don't even know what terms to Google!
I have thought I could maybe read the installed.json file which composer puts at vendor/composer/installed.php but I'm not sure how to set up my packages (e.g. blog) so they announce what they are. I'd like to future proof it so that I'm not looking for known module names (or regexing vendor or package names), but rather looking for packages to say "hey framework, I know you! You can use me!"
Maybe I can somehow instruct Composer (through the package's composer.json file) to stick in an arbitrary key/value pair in installed.json?
Any suggestions welcome, or directions as to what sort of Googling I should be doing.
Oh welcome to the world of managing dependencies on your framework.
I have some experience with auraphp, where we dealt with similar issue. You can read the blog post Composer-Assisted Two-Stage Configuration .
So what we finally ended-up adding https://github.com/auraphp/Aura.Web/blob/a3870d1a16ecd3ab6c4807165ac5196384da62cd/composer.json#L26-L36 these lines in the packages that need to understand to load by the framework.
You can also see how this bundle can also get autoloaded with the configurations.
in your composer.json
https://github.com/harikt/Aura.Asset_Bundle/blob/6ea787979390e69bf6ecb1e33ce00ed90f306e2f/composer.json#L21-L27
and the config/Common.php ( https://github.com/harikt/Aura.Asset_Bundle/blob/223126cedb460e486c4f0b242719c96c14be5385/config/Common.php ) , note we have other development modes also. For a detailed look check https://github.com/auraphp/Aura.Web_Project or https://github.com/auraphp/Aura.Framework_Project
Hope that helps a bit to look into the code and work on your own solution.
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.
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.