What exactly should a Symfony2 bundle contain? - php

I know a Symfony2 bundle should contain a common set of features. However, how granular do you define that set of features? For example, I have a ContentBundle which deals with creating and editing content. Then I have a TaxonomyBundle which handles tagging and categories etc. Finally I have a PollsBundle, which deals with polls.
The trouble I'm having is that the doctrine entities rely on entities in other bundles. For example I have an entity 'Type' in TaxonomyBundle, and a 'Poll' in PollBundle belongs to 'Type'. Finally 'Type' belongs to 'Content' in the ContentBundle.
Am I being too granular when trying to separate concerns? Should things like content and taxonomy be a part of the same bundle?
tl;dr how wide a scope, in terms of features should a Symfony2 bundle be?

According to Symfony best practices :
But a bundle is meant to be something that can be reused as a
stand-alone piece of software. If UserBundle cannot be used "as is" in
other Symfony apps, then it shouldn't be its own bundle. Moreover
InvoiceBundle depends on ProductBundle, then there's no advantage to
having two separate bundles.
So it looks that in your case this rule applies:
Best Practice
Create only one bundle called AppBundle for your application logic

Related

Decoupling Symfony bundles and making coupling loose or configurable

The case I'm trying to solve is:
I got bundle taking care of orders called 'OrderBundle' and wrote additional budle taking care of complaints - 'ComplaintsBundle' - the bundle is not fully standalone - the
entity 'Complaint' is coupled with the entity 'Order' by the field 'order' inside 'Complaint' and - what I think is the
real coupling problem - by the Doctrine annotation pointing to "Order".
What I'm thinking of and would like to achieve is to write a bundle 'Complaints' which can be standalone or have additional, optional fields which can be configured to couple with different entity. For example - the bundle 'Complaints' can serve as a complaints bundle for any
entity which would eventually need complaints functionality.
The similiar situation I got with other bundles. Another example is 'User' entity from UserBundle which is related to 'Company' entity in CompanyBundle,
but the thing again is that I want the UserBundle to be standalone bundle which can be easily installed among different projects which not necessary need the CompanyBundle but
the User can be attached to another entity/entities. It goes futher because it is not only about doctrine annotations but views, created forms, validation, and many other
involved stuff.
What should be my approach to achieve that? Im quite new to symfony in fact and the idea of standalone reusable bundles is also quite new to me, before
I didn't any bundles but was developing applications as a whole. Also I would like to develop other, not related to my job, open-source bundles to share with others, so
I guess I need to apply to them this attitude of not being coupled to practically nothing else - how that can be achieved practically, can you share your experience, thoughts or point to explanatory articles?
Thank you very much for your guidelines and please take note it's a resonable question as there is a lack of know-how about decoupling bundles in Symfony community.
In your standalone bundles, you should declare your entities as abstract and set the doctrine annotation #MappedSuperclass on it.
Then, in your application, you will have to create your 'final' entities witch will be extend the mapped super class provided by your bundle.
Also, you will probably need to expose the FQCN of childs entities in your bundle configuration.
It can seem a little heavy, but unfortunatly Doctrine mapping is not overridable.
Here is some bundles implementing this solution :
Orbital/CmsBundle
FosUserBundle
To handle relations between your MappedSuperclass You have to use Interface in your relation annotation. Here is the official documentation about it.
Best regards

Symfony2 architecture

I am developing an app with Symfony2 that has 3 main parts called frontoffice, backoffice, admin. I was thinking to create three separate bundles: FrontOfficeBundle, BackOfficeBundle, AdminBundle but Symfony's docs says, each bundle should not have any relation with each other. Entity is already a shared property and probably some models. I could create a SharedBundle but it does not make sense. I remember when I created an app 2 years go when I had like 15 bundles and all connected each other and I know from experience that it's a nightmare.
Should I have just one bundle AppBundle and logic split in the folders, eg. Controller/Admin; Controller/FrontOffice, Controller/BackOffice?
What's the best approach?
It's all about SRP and DRY
It doesn't hurt to create a bundle, so make a separate bundle for stuff you need in multiple bundles, e.g. I tend to create an EntityBundle which contains entities and their repositories (as service).
Of course you can just use a single AppBundle too but please don't put your logic into the controllers -> create reusable services! Inject the services you need into your controller (which should themselves be services too).
Alternatives to base Controller Methods
No such thing as best approach.
However, instead of grouping by class type (Controller,Command,Form,Templates) within a directory, I like to create a single "component" directory for each request action. So I would have
Action
FrontOffice
BackOffics
Admin
User
UserController.php
UserFormType.php
UserTemplate.html.twig
Grouping files in this fashion really cuts down on figuring out where the various files live. Is it the "best" approach? Nope. But it works for me.

Symfony 2 Bundle Responsibilities and Structure

I am confused at when to create a new bundle or when just to create a new controller and CRUD in Symfony 2. If I have an entity that has joining tables to other entities should that all be in the same bundle.
An example would be I have a user bundle and I wanted users to be able to like videos in the system. There for the user and a video will be linked in a joining table.
Before I started the project I would have said that I would need to create a video bundle and a user bundle, but if they both need to reference each other should they be in the same bundle?
And if the answer is that they should be in separate bundles what is the best practice to reference them in either of their views and controllers?
I'll go for packing common features in the same bundle. It's quite hard to understand when you start learning Symfony 2, I know. Consider, for example, FOSUserBundle: it defines common and reusable code for CRUD operations on users, groups, authentication and so on.
As a starting point you should learn How to Define Relationships with Abstract Classes and Interfaces and Doctrine Inheritance Mapping (mapped superclasses are very useful for extending your bundle, with some limitations).

Symfony2 application structure best practices

For the past two months, I've been developing a Symfony2 web application. Now I've been going back through and trying to fix some issues with it, because it's gotten a little out of control and I want to make it easy to maintain.
My application is structured into a series of bundles like this:
src/AppName/HelpBundle
src/Appname/InterfaceBundle
src/AppName/ProductBundle
src/AppName/UserBundle
InterfaceBundle just contains several twig templates for the main layout, and each of the other bundles just extend that, e.g.:
{% extends 'AppNameInterfaceBundle::layout.html.twig' %}
For controllers, each controller directory has two sub directories: User and Admin, for example:
src/AppName/ProductBundle/Controller/Admin/ProductCategoryController.php
src/AppName/ProductBundle/Controller/User/ProductCategoryController.php
Is this the appropriate way to structure a Symfony application, or should it be done differently?
The problem is not very detailed but for what I see I think that what you could do is organize things in a way that AdminBundle and a UserBundle contain a set of generic services that allow you to build controllers reusing them.
Then you could have a series of bundles like ProductBundle that reuse/interact with these services. Use dependency injection in your controllers rather than extending the Symfony's Controller class; this way you can leverage service inheritance and build abstract controllers in your AdminBundle and UserBundle and use them to derive your specific controllers.
More in general I like to structure Symfony applications in a way that for each concern that is cross-cutting the application's domain (e.g. indexing of entities in a search engine, logging, generation of URLs and so on) I like to create a bundle that provides some abstractions to handle it; for each area of the domain (e.g. product management, user management etc.) then I like having a bundle that implements interfaces provided in the abstraction ones and that registers specific services to be used in the provided abstractions. Interfacing can be done in this case through the container's configuration and tagging systems.
The question was pretty generic and so my answer is too, if you want more details feel free to provide more details to your question.

How do I define an entity which is commonly used several bundles?

I want to create a blogging system in order to practice symfony2,
but currently I get a bit confused when creating entities such as user or blog.
The reason is the following :
User( or Blog) is commonly used in frontend and backend(admin)
(currently I have considered creating FrontendBundle and AdminBundle)
Entity must belong to one bundle.
Currently I have considered the following methods, but what is the best way
in this case, or please tell me if there is another way.
Create bundle named 'BlogCommonBundle' and define User entity as "BlogCommonBundle:User".
Define all controllers under 1 bundle, such as 'BlogBundle', so
frontend/backend(admin) controllers belong to same bundle.
I think creating a BlogBundle and having multiple controllers for frontend and admin functionality is a good way to handle this. Both controllers would make use of the same entities and repositories, and you can easily firewall your admin actions in the security settings of your application. By keeping everything blog related to one bundle, you maintain good code organization.
The same goes for a UserBundle. It's helpful to remind yourself that a bundle should represent a set of like functionality for an application. So if you have code that fetches blog posts, and allows you to create and manage them, they naturally group together in a single bundle.
I asked a similar question here:
How to share a Symfony2 model with several projects
I went with the 'ModelBundle' approach that contains all the entities, forms, repositories, etc. These are all shared with the FrontendBundle and BackendBundle.
So far I'm very happy with this solution.

Categories