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

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.

Related

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.

What exactly should a Symfony2 bundle contain?

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

Application structure in Symfony 2

I am quiet new to the symfony framework and took some lessons and purchased the 'Starting in Symfony2' tutorial from knpuniverse. I want to be sure that I use the correct setup for my application. My question is, How do you call your first central bundle? eg. FrontendBundle? I want to make the next structure in my application:
FrontendBundle
The front where people get a landing site where they can also login
from there, when they login, they get into the next bundle:
CustomerBundle
Backend app where customers get their invoices and pay them and edit their information we stored in the database
And at least:
AdminBundle
Another backend app where I can edit customers, make invoices for customers and edit the app information
Is this the correct way and is FOSUserBundle a good bundle for this kind of application?
Bundles have sense only if they can be used in "multiple projects". I mean: if you write code, make it as a bundle and you can't reuse that bundle (for example because bundles, as you described above, are strictly and logically connected to your project) this three bundle separations is totally useless.
So, final answer (that is also a question) is:
Could you reuse FrontendBundle in other projects?
Could you reuse CustomBundle in other projects?
Could you reuse AdminBundle in other porjects?
If you notice that you can't use any or all of these bundles for other project, maybe this separations isn't good.
Why I say that?
Because if they can't be used in separated ways is likely that they should be used togheter so you should keep them togheter.
So I advice to keep them into a single bundle (YourNameYourBundleNameBundle (in that notation, for example)) and to separate the single "areas":
FrontEnd controllers/entities/views
Custom controllers/entities/views
Admin controllers/entities/views
This problem has been discussed at length already. For application specific code either do a single AppBundle or don't use bundles at all.

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).

Row level permissions and Laravel app structuring

I'd like to ask other opinions about code structuring of business logic on Laravel applications, mainly regarding permissions at the row level.
For those that don't know it, Laravel is a MVC framework for PHP, much like Rails.
For the sake of understanding, let's suppose a multi-tenant application where each user has his own albums and pictures, so far so good.
Now, each user can invite others to collaborate (by uploading photos) into his album.
Both, the album's owner and collaborator that uploaded the picture may be able to delete or update information about that picture.
Only the owner may edit the album and invite new collaborators.
Collaborators can remove themselves of the album if they want so.
Pinterest should be a nice example of something similar, but our application is probably 3 or 4 times more complex.
The question is: where should I handle that kind of logic?
Laravel proposes the approach of having repositories, entities and services, which I don't fully understand, probably because of the lack of good examples. So the obvious first choice to meet those deadlines was to put it all on controllers (ew!). Now, digging into refactoring, there are many possible ways to un'spaghettize our code:
I've seen people implement ACL at row level (looks kinda dumb and overkill)
It would be possible to turn models into behavior aware objects and not only data containers, something like $album->add_photo($photo) and check permissions at that function
It would also be possible to override model's save method and do there those checks
Or, follow the Laravel proposed road of having separate layers of concern
I suppose that having methods like $album->can_be_edited_by($user) may simplify the displaying of 404 erros on routes not allowed, hiding view's links as well as validating before saving the models
Which would you recommend, and does anyone know any simple, but understandable, example of repositories, entities and services not using .NET?
Thanks!
Edit: I guess that a full ACL system would cause excessive overhead, since there may be thousands of resources associated with each user, but only one role per kind of association. For instance, pictures will have an uploader_id and albums will have an owner_id.
I could be wrong but I think ACLs are OBJECT based permissions (i.e., a user can or can't delete photos in GENERAL). What you want is more custom MODEL based permissions (row level like you said), i.e., a user can delete photos that they themselves created (SPECIFIC ones).
Most Laravel packages are designed for object based permissions I think, but not https://github.com/deefour/authorizer - this one is a great hidden gem. We don't use it in our project but I found that it really covers all the bases we'd need.
We have really advanced model permissions on our app, I have them scattered throughout my models, but I take a very model centric approach, which isn't necessarily very "laravel-esque". In your example with delete, I would override the delete method in your model or listen for the eloquent event and prevent it there. If you have to prevent read/write on certain attributes you could even do that by extending your validator or using custom mutators/getters, serializers or listening on events. More on where to add business logic in my question/answer here: https://stackoverflow.com/a/27804817/796437
I'm still trying to find the best approach, if I do I'll update this - but thought I'd post.
In Laravel you can use Policies or use solutions, like Symfony Voters.
For Laravel exists same package - Laravel Simple Voters.
Using this, you can check access to custom objects, looks like this:
Access::isGranted('edit', $post) // current user can edit this post?
You can put this logic, to example, into middleware, if you wish check requests to controllers.

Categories