Bundle Structure and Best Practices:
A bundle should not embed third-party libraries written in JavaScript,
CSS, or any other language.
Why shouldn't i create for example a bootstrap, or jQuery bundle?
I think it would be easier to maintain if all third-party CSS and JavaScript libraries live in their own bundle.
Well, for one, It's counter-intuitive. Symfony Bundles are for packages of PHP functionality and you're talking about bundling up front-end libraries.
Secondly - why would it be easier? Things like bootstrap and jQuery are public resources to begin with - they don't need a distributable bundle to achieve high re-use. PHP resources are not public and therefore benefit from this type of system.
The chaos comes when two or more bundles uses the same 3rd party library but different versions. A user of your bundle won't be able to choose which library to include and therefore can't use both bundles at the time.
It's fine to store them in a bundle folder if your bundle is a standalone application, i.e. your application's main bundle. For example, SonataAdminBundle includes 3rd party libraries: bootstrap.css, qtip, famfamfam icons.
look at MopaBootstrapBundle https://github.com/phiamo/MopaBootstrapBundle it integrates TwitterBootstrap & jQuery lib for you, also HTML5BoilerPlate if you enable initializr addon.
Related
Is there a tool or a bundle in Symfony2 that allows me to create normal templates with css files, and then on the fly convert it to inline css rules so it can be used as the body of an email?
I know of three tools that can do this and which you can use in Symfony:
Premailer is an online tool which provides this service. It has an API and a php wrapper for that API
CssToInlineClass is a php class that offers this functionality
Mailchimp offers a function in their api that offers this functionality
The first two donĀ“t have a direct symfony implementation, though they will be easy to use. For mailchimp, there is a mailchimp bundle which offers this functionality, though the bundle is not very well documented.
Today I discovered through another question that exists such a Symfony2 bundle that fits your needs (I didn't tested it).
You can use ToInlineStyleEmailBundle, it embeds the CSSToInline library that Carlos Granados suggested in his answer.
With this Symfony2 bundle you can get the converter as a service ($this->get('css_to_inline_email_converter')) and then use it for your needs. It also supports templates generations.
I've had great results with integrating the Emogrifier PHP class within CakePHP. Inlines all styles very nicely. Not sure if it has a Symfony bundle but shouldn't be hard to integrate.
https://github.com/jjriv/emogrifier
In the Symfony 2 docs it's said:
A bundle should not embed third-party libraries written in JavaScript, CSS, or any other language.
Then how should I do that? I want to install Twitter Bootstrap, DataTables, and many other things as dependencies using Composer. But the only way I can think of is creating a bundle and embedding them.
What is the correct way to do this?
You should use Bower by Twitter. It is a package manager for HTML, CSS and Javascript. It was created to address this very issue you are having.
EDIT:
As of now, there are very good package managers for JS Libraries such as Bower, Jam or Component.
Versioning system
Semantic Versioning - Composer advises to use the semantic versioning system. It uses a X.Y.Z setting, in which X is the major version, Y is the minor version and Z is the patch version. Y and Z should always be backwards compatible while X reflects changes in code which MIGHT break backwards compatibility.
Embeding
Embeding should be read as copy and pasting the code (and binary) as part of your library, rather then requiring it as a third party (vendor) package/bundle. Its like including query.js in a resource folder or copying and pasting propel code to a folder inside your bundle.
Why not embed 3rd party libs
A bundle should not embed third-party libraries written in JavaScript, CSS, or any other language.
This statement comes from a best practice point of view. Embeding (as in copy/paste) third party libraries of any kind (PHP libs especially) is usually not a good idea. For instance, imagine that BUNDLE A uses LIBRARY FOO v1.4.1, and BUNDLE B also uses LIBRARY FOO but with a different version v1.5.2. If any of the BUNDLES (A or B) embeds FOO lib, they might (most probably will) become incompatible. For instance, php classes and functions cannot be redeclared. Any of the bundles can, of course, use workarounds to mitigate this problem, such as namespacing their version of FOO or autoloading rules, but this can rise other problems as well besides surely increasing memory usage as there are 2 versions of the same thing parsed by PHP.
If a PHP package does not follow this best practice, the errors that arise are usually easy to spot (with error: cannot redeclcare function blablabla). With Javascript Libraries, however, that is not true. You can redeclare functions (as they are object properties). So if now FOO is a JS Lib instead, and BUNDLE A and B embed them into their libraries, when they are included, strange problems can arise. For instance, a function can be redeclared that lacks a crucial functionality for one of the bundles and break it.
Symfony is a PHP framework.
It deals with PHP libraries/bundles. Symfony advises to require a library as dependency instead of embedding it since it uses Composer as a Package manager, which takes care of downloading and loading the require packages. As far as I remember, when 2 bundles/packages use the same library, if they have different version requirements, the most actual is used, unless its backwards incompatible. Composer then reports a conflict that you have to manually resolve.
However... There is no way to handle javascript libraries properly. That's because Composer is a package for PHP libraries. You can workaround this in two ways I can think of: (there are probably more and best ways to handle this, I just thought of these two, read them as suggestions)
Create a PHP wrapper around the javascript library and including it (although this potentially creates the same problem if another bundle decides to do the same thing but giving the package a different name)
Creating a bundle which requires the javascript library as a third party dependency through composer. Since the javascript library won't probably have a composer.json file in it's repository (sometimes they live as a standalone minified file), this can be accomplished by creating a custom composer installer, forking the javascript repository (in gitHub for instance) adding a composer.json to it, etc... However, you will need to constantly maintain and upgrade the said library, which can be troublesome.
You will have to keep in mind that:
JS and CSS libs have to be exposed publicly, so that the client can access it (security considerations)
Symfony is a PHP framework and deals with server-side packages. JS/CSS are client side. This as to be taken in consideration so it works properly.
One of the main ideas behind symfony (as with other PHP Frameworks) is code reusability within and between projects. Pure Javascript Library are reusable in themselves. They are usually self contained. Besides, there is no real gain in "bundling" a JS library from the server side. You don't need any kind of bundle to achieve reusability.
My Approach
Since the composer system is so appealing, specially when deploying bundles/packages/libraries to other people, my approach to using third party javascript/css libraries was to create a dependency manager specific to JS/CSS that other packages/bundles could rely on to take care of their JS/CSS dependencies without worrying about this.
My sugestion
If you are planing to release your project to the public, namely as a symfony bundle, you should plan carefully how to approach this.
If your project is self contained (personal use or to a client, not widespread use) then this has much less relevancy since you (the programmer) have total control in what third party tools you use and include in your project. These are just best practice "suggestions" to avoid
future problems.
I am little bit confused with symfony2 bundles.
I want to know that does everything in symfony is bundle including main application.
I was thinking as Core of site is somewhere i can write code to use bundles like we use plugins from main application code.
Or there is no core thing in Symfony . The core itself will be bundle
you can define your website completely as a bundle, meaning
Mycompany/MywebsiteBundle
Or you can define the different, sections of your website as different bundle, which i personally preffer
`Mycompany/ForumBundle
Mycompany/BlogBundle
Mycompany/NewsletterBundle`
Symfony2 is bundle-based framework
=> So, everything, as well as the core itself is a bundle.
You can see which bundle is loaded by default in app/AppKernel.php.
But Symfony2 does also include a library, organized by "components (vendor/symfony/src/Symfony/Components). Code in bundle can use this library..
Indeed, everything is a bundle. As per Symfony2 docs:
http://symfony.com/doc/2.0/book/page_creation.html#page-creation-bundles
I'm just working through the Symfony2 Bible and I'm a little stuck on the bundle system. It is a great feature but I'm not quite sure how to split my flat PHP application into bundles. It's my first time splitting my PHP code into a full featured MVC framework.
I'm working on a few online games (based on PHP) but how would I define the bundles ? Is it like one single onlinegame1 bundle with all the controllers and functions - Or like a login bundle, a register bundle, a war bundle - summarized one bundle for every single PHP file I got ?
I want to start clean and correct but I'm not quite sure if I understand that feature.
You could think of bundle as an independent reusable component - in most of the cases at least.
Let's imagine a personal blog website. I'd split it into ArticleBundle, UserBundle, CommentBundle and finally MainBundle which would stick all these other bundles together, creating your website. The main point is that you can take for example ArticleBundle and reuse it easily on other project without it being tied to any other bundle.
From Symfony2 book:
A bundle is similar to a plugin in other software, but even better.
The key difference is that everything is a bundle in Symfony2,
including both the core framework functionality and the code written
for your application. Bundles are first-class citizens in Symfony2.
This gives you the flexibility to use pre-built features packaged in
third-party bundles or to distribute your own bundles. It makes it
easy to pick and choose which features to enable in your application
and to optimize them the way you want.
As our company starts using Zend Framework as the base framework for most of our projects, we want to share some common elements across all our projects. I talk about things like:
An implementation of a model (based on doctrine2)
RBAC for the model, including user, group, role models
A xml-based templating engine for ajax backend interfaces
(you name it) ...
Basically, all things to put "zend on rails" and get going. What is the best way to package these components? I see two possibilities:
As modules
We include the necessary functions as separate modules into the modules folder.
Pro:
We can set routes and execute code, which is good for many modules (imaginary example: a paypal module needs some kind of callback url. If our module can set it up on its own, no configuration from the "project developer" is needed).
We can provide real functionality (like the user administration) out of the box
We have a bootstrap to set up autoloading and doctrine etc.
Con:
Bad place? Interferes with the users project
A little harder to share between projects (git submodules instead of classpath)
In the library folder
We put it in the library folder and point the classpath to it.
Pro:
Clean solution
Sharing across projects
Con:
Bootstrap has to be explicitly called
No direct routing or actions - everything has to be proxied through the concrete project
So, how do you solve this? Where do you put your reusable, general purpose stuff in zf?
I think you should use both approaches.
When developing "library-like" code, as in kind of "infrastructure" classes and other things that are reusable (like ZF's own components, Doctrine 2's components etc.), you can put them into the library directory. (or its own entirely separate project)
When developing actual ZF modules (like an auth module for example), then format the code around the ZF module structure.
I think by using this kind of approach you get all the benfits you listed, and pretty much none of the cons :)
As one additional idea, if you develop your architecture parts as "services", you could even keep them running as their own web service endpoints.