I'm on Symfony 2.0 and understood that third-party libraries go in /vendor. I have two third party classes I'm using, one is TCPDF and another is a Paypal class. Neither have formal Symfony2 Bundles.
So I followed the instructions here which namespaces them and makes them usable inside /vendor:
Add third party libraries to Symfony 2
This works and I can access them from my Controllers. However I'm rethinking if that's the right thing. Whenever I do..
php bin/vendors install --reinstall
..those custom classes disappear because they don't have a Git repo in 'deps'. This has caused real problems e.g. when trying to deploy on e.g. PagodaBox. I get the strong instinct that this code while 'third-party' belongs closer to the code of my app.
If that's true, should it:
Sit next to my Controllers in src/MyCompany/MyBundle/Controller/tcpdf.php
Be with my other custom-written services in src/MyCompany/MyBundle/DependencyInjection/tcpdf.php
Go in its own directory under my bundle: src/MyCompany/MyBundle/TCPDF/tcpdf.php
If I move these two classes from /vendor to one of the above, would I access it from a Controller with a 'use' statement, or would I need to define it in 'services.yml'?
I hope this isn't so much a matter of discussion or opinion but some guidance I've missed or best practise I'm unaware of that a more experienced Symfony2 dev would know.
Would it be sensible to switch to Composer even before Symfony 2.1 is ready?
Thanks for reading.
If you're using deps to manage vendor libraries then you should add the git repo's for those libraries there.
For TCPDF you can use:
[TCPDF]
git=git://tcpdf.git.sourceforge.net/gitroot/tcpdf/tcpdf
target=/tcpdf
If you have other libraries that aren't in a public repo then you may want to commit them to your own repo.
The same would hold true for Composer. Just the syntax for adding non-packagist repo's is different.
Related
Background
I am developing a framework in PHP. I started by making each component separately so that it can be used independently from the framework.
After creating four libraries A, B, C and D:
A has no dependencies
B and C require A
D requires A, B and C
Now I have some issues when releasing a new version of one library, I may have to change dependencies of others and have to release new versions for them. For example: new version of A means new version of B, C and D.
I looked how other frameworks like Symfony and Laravel solved this issue. I learned that they are using the subtree feature of Git and the replace feature of Composer. It works as follows:
Each component is in a read-only repository with his own composer.json
Each component can require other components but doesn't replace them.
The framework repository uses subtrees to include all components. So no need to require them using composer. But it should require all their dependencies (since this is no longer handled by Compser).
The framework replaces all its components.
I have also noticed that
A component repository contains only the source code (no unit tests !)
Laravel made the component Contracts just to store all the interafces of all component and each component is requiring that.
Questions
Is my explanation of how Laravel and Symfony solved the issue correct ?
Do I really have to remove tests from the components repositories and put them in the framework one ?
If yes, how can someone who wants just to use a single component be sure it passes the tests regardless of the whole framework being passing the wole tests ?
Do I have to make sure that all components dependencies are compatible and require them manually in the framework composer.json ?
What is the point of having a component for Interfaces ? This could not be used standalone anyway !
Is there a better way to solve this problem ?
P.S: here are links to A, B, C and D
Now I have some issues when releasing a new version of one library, I may have to change dependencies of others and have to release new versions for them. For example: new version of A means new version of B, C and D.
You have a multi-repo approach.
Edit of A => new version of A => version bump needed in B, C and D.
I think the most important thing is to get away from using dev-master and versionize your components properly, once they are stablized and ready to be out of dev-phase. Then you might use Composers range operators (caret ^ & tilde ~) to automatically update to the latest released version in a certain major.minor version range. This helps a great deal and takes the tedious manual version updating work out of your hands.
Is my explanation of how Laravel and Symfony solved the issue correct ?
It's not correct. The underlying development concept, publication and consumption of packages work differently, then to what you described.
They use a monolithic repo development style. It's a single repository, which contains code for group of packages. The opposite of the mono-repo is many-repo approach. The alternative are git submodules.
All modules/bundles of a framework and the framework core/kernel are in one repository! For Laravel it's https://github.com/laravel/framework/tree/5.4/src/Illuminate
Each module/bundle folder contains a composer.json and the framework itself contains a composer.json
This allows to "split out" the module folders into standalone read-only repositories. Using a custom git helper, e.g. git subsplit publish like Laravel uses https://github.com/laravel/framework/blob/636020a96a082b80fa87eed07d45c74fa7a4ba70/build/illuminate-split-full.sh or splitsh https://github.com/splitsh/lite, like Symfony uses
The development happens in the main repo.
Finally, from the user/consumer perspective (in the composer.json of your CMS/app whatever), you simply require a module/bundle from the "standalone read-only repository" source. This is many-repo, because your app depends on many repositories.
When you update a dependency using Composer, then Composer replaces your packages with a newer version.
Do I really have to remove tests from the components repositories and put them in the framework one ?
No. You could also leave the tests in the /moduleA/tests folder and adjust your unit test collector.
If yes, how can someone who wants just to use a single component be sure it passes the tests regardless of the whole framework being passing the wole tests ?
Two things. The subject under test is:
(a) the component, which is ideally independently testable and
(b) the framework, which consumes many components and tests functionalities, which rely on functions from multiple components (e.g. a core/kernel). You could also split a kernel out, once it stabilizes and is testable independently. (e.g. your component D)
Do I have to make sure that all components dependencies are compatible and require them manually in the framework composer.json ?
The monorepo developer perspective:
The developer/maintainer of a framework can only release a new version, when all unit-tests of all components and all unit-tests of the framework itself pass, right? Then he can start a subtree split and automatically versionize the new components.
The application developer perspective:
Yes. As the user of components of a monorep you are simply consuming standaloen dependencies (from the read-only repos). That means you have to maintain the versions of the components you require in your composer.json manually or automatically.
What is the point of having a component for Interfaces ? This could not be used standalone anyway !
Good question!
Maybe the developers want to do things differently and "keep things sorted"
Or, they have a bad optimization idea on their minds:
One could argue that interfaces are only development contracts.
When all components are written against interfaces you could simply pull the plug on them, after testing and before doing a production release.
In other words: you could leave the interfaces repository away
and run an interface removal, when you are releasing for production.
Leaving the interfaces repo away would lead to "interfaces X not found" fatal errors. Then you run an "optimizer pass" over the rest of the classes and remove all "implements interfaceX" strings. Less files to include. Less code to parse. Less IO. And now i will probably be killed in the comment section by suggesting this :) And no, Laravel or Symfony are not doing this.
Is there a better way to solve this problem?
I'd suggest to do the following: for a project with <5 components, use multi-repo. If >5 components, go monorepo.
In general there are not so many options to solve this:
git submodules
mono-repo
multi-repo
Each of the approaches has pro's and con's.:
Updating git submodules a.k.a. git version bumping and submodule updating leads to git madness, because it'll be constantly broken. and git madness leads to the dark side. :)
Mono-repo is easy to maintain and easy to publish. It gives you easy maintainace for the developer and multi-repo for the consumer. You can replace/rename/refactor across all modules/components at once.
Many-repo is hard to maintain, when you have a large number of components.
See also:
https://www.tomasvotruba.cz/blog/2017/01/31/how-monolithic-repository-in-open-source-saved-my-laziness/
DrupalCon New Orleans 2016: The Symfony Monolith Repository
Thanks for your attention, this is a question of organization, I work with PHP and GIT for version control. I use Netbeans IDE to program, GIT integrated (although I am still a rookie).
Normally, I follow the approach that Symfony2 specifies for organize the project files, but I use my own framework for my projects.
The (main) question is: Any component or code part which has its own version control must be located under the /vendor/directory?
For example:
I have my project files in src\Acme\ProjectX\, also the utility package which use all my projects: src\Acme\Util\, and it is under the version control too (GIT).
and now let's remember the basic skeleton of a project based on Symfony or similar:
/app (application related elements)
/src (source code of the project)
/vendor (third party libraries)
/web (front end controller, the web directory, assets resources etc...)
So, Must be 'Acme\Util' included in the vendor directory? And, is necessary to use composer to declare the dependences?
In addition, the Utility package has a lot of classes but only few are used in projects. Must I remove those are not using by the project.
Summarizing, It will be nice if someone can contribute his knowledge for help me to represent an scenario like this.
I hope I could explained...
Thanks in advance!
Vendor directory
It's a good practice to separate external dependencies and the application code. If you are using Composer you can change it to something else.
Unused classes
Unused classes shouldn't matter if they aren't being loaded. They'll just take a bit of extra disc space.
It might be a good idea to separate the Utility package into multiple packages if you find yourself frequently using only a small part of it.
Dependency managers
It isn't necessary to use a dependency manager, but it sure does help. Having to install, configure and maintain everything manually (especially with many dependencies and sub-dependencies) would be a horror.
I am working on an application that was built in Zend framework 1. I want to install simpleSAMLphp as a service provider for it and trying to figure how best to do this.
I'm considering a couple of options:
Install it outside the application
(e.g. /var/www/myapp/simplesamlphp where my app's files are at /var/www/myapp/simplesamlphp). This is how it seems it's done in the installation tutorials. I guess this would work with some adjustments to the autoloading so it can pickup the SimpleSamlphp classes. I'm using composer to install dependencies so I can perhaps add the SimpleSAML folder to the class tree - not tried this yet. Or should I use the SimpleSAMLphp autoload file?
simplesamlphp-composer
I sees there is an option install with composer? So, if so, it will go within my application folder and files. However, I've tried this and not sure how to get composer to pick up the SimpleSAML classes. Anyone had much use of this method? I tried doing composer dump-autoload but it didn't add them. I guess I need to do more.
Can anyone give me some advice on how to use simpleSAMLphp with ZF1. Even just a point in the correct direction regarding where best to put files. We want to role this installation out to all our websites eventually so something that is easy to setup would be best I guess. I do like the composer approach but didn't have much luck with it. Previously the project used CAS with a phpCAS client - that was installed using composer which was quite convenient.
Any help would be much appreciated, thanks
I used ZF 1 and had following structure
/lib/Zend/ -- ZF
/lib/Zend.php
/lib/MyCompany/ -- my classes that supports ZF autolaod
/lib/ANyOtherZFCompatible
/lib/external/ -- any other libs that don't support ZF convention
I would put SimpleSAML into /lib/external/simpleSAML/
and at the beginning of your main file
require_once('/lib/external/simpleSAML/lib/_autoload.php'); and try to use init some SAML classes.
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.
I'd like to know what's the best practice
using git for a project using external
library/modules/framework.
Put the case I deploy a project with zend 2
and some modules for instance ZfcUser and BjyAuthorize
should I put it in the repository or not ?
When a developer clone the project get the framework
and modules or not ?
Thanks in advance.
In the case you're using composer to manage your project dependencies, no need to push ZF2, ZfcUser and BjyAuthorize. Just add your composer.json package descriptor and ignore your vendor folder to push your project.
If you're managing dependencies by yourself, i think it can be useful to push all your libraries. (that's how i did for many ZF1 projects where i had embedded some libraries).
I strongly urge you to use composer or any tool like it as you don't have to worry anymore about framework / libraries updates.
If the framework exists as a git repository I would consider using git submodule add yourFramework which will put a reference to the framework in your repository that others can download.
The overhead associated with adding some frameworks to a repository is probably trivial seeing as that code shouldn't get touched. It might just be easier for you to add the framework into the repository to reduce the work that other developers would have to do in order to start working.