In a Symfony/Doctrine/PHP-project, a client is complaining that we've broken software development best practices. The complaint is about improper layering of the source code, and the lack of unit tests.
This is a sub $50k-project.
I believe that the client has an expert from the Java world, perhaps Spring Framework, looking at the source code.
We've been using proper MVC, as we see it.
View-logic is handled entirely by TWIG.
Database is handled entirely by Doctrine.
We're using Symfony Security for access control ($this->get('security.context')->isGranted('ROLE_ADMIN') and $this->get('security.context')->getToken()->getUser().
Beware that Symfony has changed the model a bit, since we started this project - but remains backward compatible.
In the controller the customer is specifically saying that it's wrong for the controller to handle:
Access Control (via Symfony Security)
Database Queries (via Doctrine)
"Parsing and other logic" for sending back responses (return $this->render('some_template.html.twig');)
The question
The client is saying that best practices is for the controller to simply pass on requests to another layer further down in the system.
Further he's saying that user-admin is based on a "custom model" where all users and roles are stored in the database - which makes plugging in a different access control system difficult. Specifically because role names seems to be hard coded such as via commands such as ($this->get('security.context')->isGranted('ROLE_ADMIN').
So; is there a definitive best practice on this field? What belongs in the controller, and is Doctrine, Twig, Symfony Security "sufficiently" a separate layer "below the controller".
Should there be yet another layer between the controller and Doctrine for example?
Source: http://fabien.potencier.org/what-is-symfony2.html
First, what is Symfony2?
First, Symfony2 is a reusable set of standalone, decoupled, and cohesive PHP components that solve common web development problems.
Then, based on these components, Symfony2 is also a full-stack web framework.
Depending on your project and depending on your needs, you can either pick and choose some of the Symfony2 components and start your project with them, or you can use the full-stack framework and benefit from the tight integration it provides out of the box. And choosing between the two different approaches is really up to you.
Is Symfony2 an MVC framework?
Symfony2 is really about providing the tools for the Controller part, the View part, but not the Model part. It's up to you to create your model by hand or use any other tool, like an ORM. Of course, tight integration exists for the most well known ORMs like Doctrine2 and Propel; but they are optional dependencies. The Symfony2 core features do not and will never rely on any ORM.
Symfony2 is an HTTP framework; it is a Request/Response framework. That's the big deal. The fundamental principles of Symfony2 are centered around the HTTP specification.
Symfony about best practices: https://symfony.com/doc/current/best_practices.html
You should rly read this about controller best practices:
https://symfony.com/doc/current/best_practices.html#controllers
You can read this answer https://stackoverflow.com/a/21701890/2160958
Related
Problem:
I’m unsure how to set up multi client application for Symfony so that we would not violate Symfony's best practices and work against the framework.
I would like to have one main Core namespace which would contain all the base model classes. Right next to the core I would like to set up client specific namespaces which would be used, based on client regional setting. For example LocalUS for US market, LocalUK, for UK market etc.
The Local* namespaces should take first priority for including twig templates, and as a fallback use core common shared views (as I understand, this is solvable via twig namespaces). Same goes for controllers and models - these are probably solvable via extending the Core namespaced classes? Is this all solvable via routing and providing paths for these Local* controllers?
I was looking up on github to see if there are any project that have similar setup but I couldn’t find anything.
A little background:
We have an older legacy PHP Application which was built in-house from ground up using plain PHP. As the application has grown over time, it has become hard to maintain good code quality and standards. It’s also very time consuming to teach new developers our application logic, since the application basically follows no standard design patterns and just does it’s own thing. A lot of the underlying code which handles routes, controllers etc seems to work like “magic” that nobody really dares to touch.
It is because of that we would like to migrate our application to Symfony3 framework. I’ve read some articles about the overall process of migrating legacy applications to symfony, and managed to do it with silex pretty well. Silex, however is a bit too lightweight, I found that the assetic service provider had a lot of functionality missing (twig namespacing etc), and decided it would be best if we could move to a full stack symfony framework instead.
Look into Symfony bundles - they do exactly what you need. You create a "base" bundle, than extend it with other bundles. That's how FOSUserBundle works - it provides everything you need, than you extend it and overwrite it.
I'm wondering if ZF2 is based entierly on MOVE instead of the classic MVC.
Somewhere I read that is really bases on MOVE (http://cirw.in/blog/time-to-move-on) but e.g. in the "getting started tutorial" (http://zf2.readthedocs.org/en/latest/user-guide/overview.html) they are saying "creating a simple database driven application using the Model-View-Controller paradigm".
So, what is it now based on? Does it support both?
I'm a bit confused. What are the difference at MVC between ZF1 and ZF2?
Thanks
MOVE (Models, Operations, Views and Events)
MVC (Models, Views, Controllers)
The problem with MVC is that you end up stuffing too much code into controllers,
to overcome this problem MOVE is another possible option to choose in zf2 projects,
Because in this architecture you can split your controller into Events and Operations.
Question: Is ZF2 based entirely on the MOVE architecture?
I don't think ZF2 is designed entirely on MOVE architecture.
ZF2 follows the SOLID object oriented design principle with loosely coupled MVC architecture which provide more flexibility in terms of usability.
Question: Can I develop my projects using the MOVE architecture in ZF2?
Yes ZF2 provides you with everything to support both architectures (MOVE, MVC).
It provides Models, Views, Controllers(Operations), Events.
It is up to the developer which architecture he would like to use.
ZF1 and ZF2 is compared in another thread.
MVC or MOVE
SOLID Object Oriented Programing
I am still a beginner in zf2, I am writing here since I had ported my zf1 code entirely to new zf2 framework. I could only say the new framework have lot of advantages and once you get certain new concepts and feature. you can save lot of time developing new project by reusing of modules/components etc.
In zf2 most of the library components are designed to be standalone, i.e loosely coupled, as said it gives more flexibility and a task can be done in many ways (just like PHP is). The main advantage I see is modules, I can split my project to many modules with ease and test individually and integrate very easily without any additional codes. Even I had all my resources like images, css and JavaScript files inside my module folders and access it without any problem (off course with a small code in index.php)
for me ZF1 has fixed rules, flows, etc, and zf2 have liberated flow and rules with new addition of events namespace, configuration and lazy loading, assemble objects, inject dependencies with servicemanger. in zf1 routes are automatic(programmatic), where as in zf2 we need route definition, in zf1 controllers are automatically choosen, where as in zf2 we need to define controllers as invokables, this are few things that take some time to get in once you get the idea you will feel the comfort of using the new zf2 framework
to start with you can do this steps
Learn Service Manager
How Configuration works
How events work
Components wise more or less it works the same as in zf1 (at least in my case)
below are the following advantage I had benefited
Full feel of OOP
Modular application development
Design and then develop to PHP application
Web Application(RIA) platform
I'm wondering if ZF2 is based entierly on MOVE instead of the classic MVC.
Somewhere I read that is really bases on MOVE (http://cirw.in/blog/time-to-move-on) but e.g. in the "getting started tutorial" (http://zf2.readthedocs.org/en/latest/user-guide/overview.html) they are saying "creating a simple database driven application using the Model-View-Controller paradigm".
So, what is it now based on? Does it support both?
I'm a bit confused. What are the difference at MVC between ZF1 and ZF2?
Thanks
MOVE (Models, Operations, Views and Events)
MVC (Models, Views, Controllers)
The problem with MVC is that you end up stuffing too much code into controllers,
to overcome this problem MOVE is another possible option to choose in zf2 projects,
Because in this architecture you can split your controller into Events and Operations.
Question: Is ZF2 based entirely on the MOVE architecture?
I don't think ZF2 is designed entirely on MOVE architecture.
ZF2 follows the SOLID object oriented design principle with loosely coupled MVC architecture which provide more flexibility in terms of usability.
Question: Can I develop my projects using the MOVE architecture in ZF2?
Yes ZF2 provides you with everything to support both architectures (MOVE, MVC).
It provides Models, Views, Controllers(Operations), Events.
It is up to the developer which architecture he would like to use.
ZF1 and ZF2 is compared in another thread.
MVC or MOVE
SOLID Object Oriented Programing
I am still a beginner in zf2, I am writing here since I had ported my zf1 code entirely to new zf2 framework. I could only say the new framework have lot of advantages and once you get certain new concepts and feature. you can save lot of time developing new project by reusing of modules/components etc.
In zf2 most of the library components are designed to be standalone, i.e loosely coupled, as said it gives more flexibility and a task can be done in many ways (just like PHP is). The main advantage I see is modules, I can split my project to many modules with ease and test individually and integrate very easily without any additional codes. Even I had all my resources like images, css and JavaScript files inside my module folders and access it without any problem (off course with a small code in index.php)
for me ZF1 has fixed rules, flows, etc, and zf2 have liberated flow and rules with new addition of events namespace, configuration and lazy loading, assemble objects, inject dependencies with servicemanger. in zf1 routes are automatic(programmatic), where as in zf2 we need route definition, in zf1 controllers are automatically choosen, where as in zf2 we need to define controllers as invokables, this are few things that take some time to get in once you get the idea you will feel the comfort of using the new zf2 framework
to start with you can do this steps
Learn Service Manager
How Configuration works
How events work
Components wise more or less it works the same as in zf1 (at least in my case)
below are the following advantage I had benefited
Full feel of OOP
Modular application development
Design and then develop to PHP application
Web Application(RIA) platform
I have an application which is developed in Symfony2. Now the structure for it is as follows:
FrontBundle - includes everything related to the application's view and UI.
PersistanceBundle - includes everything related to the persistence layer of the application.
DomainBundle - includes everything related to the entities of the application and the services.
Is this structure ok? Or bundles are used like forum feature - ForumBundle - which includes every layer (controllers, services, domain logic and persistence) related to the forum.
There are no hard and fast rules on how to structure your app using bundles, but here's what I came to after developing on Symfony2 for close to a year.
Use one app specific bundle. At first, I started with multiple bundles like CommonBundle, UserBundle, MainBundle, BlogBundle, ContactBundle, etc. That proved to be not so convenient in the end, so I switched to just one app specific bundle — AppBundle.
You can organize your code neatly using subnamespaces. For example, the backend controllers would go to the AppBundle\Controller\Backend subnamespace.
Note that I'm talking about one app specific bundle — that stuff that's unique to the concrete app and won't make sense to reuse elsewhere. You can still develop separate bundles for reusable stuff and put them into the vendors infrastructure.
Keep non Symfony specific stuff out of bundles. There is no need to have a bundle for the model and the Service Layer classes in a bundle if they are not Symfony2 specific. See this question and my answer for further details.
Like Elnur said, use one AppBundle is a good practice.
A single bundle implements the MVC pattern himself so i think it's not a good idea to use bundles to separate your layers.
I think the best way to use bundles is to think "open source". If the feature you are developping is enough generic to be released for everyone, or to be reused in a future project, place this feature in a bundle.
This way will force you to build the feature without any business rule which belong in your AppBundle.
Bundles are bricks
There are different ways to organise application structure for your projects. But if you want to distribute your bundles and follow symfony best practices, then bundles are more features than separation of UI. More about bundles read in documentation.
I have two projects with the following structures, both valid I think:
making a bundle for each feature: BlogBundle, StoreBundle and so on,
and AppBundle that contains general stuff. No Backend/Frontend
separation. It's SaaS where backend is frontend in most cases.
One bundle for frontend, one for backend. They share only entities
and domain specific stuff. The application has two different ends.
You've probably heard of the Fat Model/Thin Controller vs. Thin Model/Fat Controller distinction. I recently heard that you can have something in between where some of the logic from the model goes into a service layer. How common is this? and do you know of (or can think of) any real examples that illustrate it?
Martin Fowler describes the Service Layer pattern of his great book Patterns of Enterprise Application Architecture. If you care about questions like the one you asked, you should read this book.
One use that comes to my mind is managing database transactions. Some people try to encapsulate starting and committing transactions in their domain models. But then they get confused when domain models invoke other domain models that also try to start and commit db transactions. So which model really gets to decide if a transaction is committed or rolled back? And what do you do if a given model is used in different ways by different clients?
The Service Layer is a solution for this, because this is the layer in which you can start and commit work that involves multiple domain models.
As for how common this is, I don't think it's common at all. Most people using Zend Framework (or any other PHP or Ruby framework) have just barely moved from "Active Record solves everything" to the new shiny, "Data Mapper solves everything." It seems this community learns only one new pattern every five years. They won't get to Service Layer for a while.
Re comment from #ktutnik:
No, the Service Layer pattern is different from Repository pattern. Repository is about abstracting database access so you can use a database like a Collection. Service Layer is about encapsulating complex application operations.
Another way of thinking about them is their relationship to the Domain Model. The Repository is used between the Domain Model and the database. Whereas the Service Layer uses one or more Domain Models.
Service Layer ---> Domain Model(s) ---> Repository ---> DBAL
Service layer advocacy is relatively new and still subject to a variety of interpretations. I think it means having a layer that leverages multiple domain models which the controllers call (I may be simplifying it too much though). I recently developed a website making use of this and practical advantages I've encountered are:
Features as a service helps with scalability. If you have an image service that initially uses the local service to do it's work it becomes easier to have that service point to another server or some 3rd party without having to make sweeping updates
Flexibility. Half way through the project I decided to change a core piece of functionality and was able to do so painlessly; allowing me to quickly weigh the pros and cons of the update. This flexibility is useful when rapid prototyping and instills a certain confidence because if you need to revisit something it's not going to be a nightmare.
Extensibility. I have already identified services in my application what I can forsee opening to other developers or other widgets, mobile apps in the future. Doing so in theory is just a matter of adding authentication and authorization to the service (because the features are already in it's own layer and I don't have to spend time trying to decouple what I want to expose from the rest of the code base).
Services are easy to add and drop (maybe this belongs with one of the earlier points). I have services that a specific to a specific stage in the project (e.g. invite only stage) that I can drop once that phase is over.
I think it has practical advantages and a key to success in implementation is having a good way to manage the services in the application. I use symfony's dependency injection component
See ZFEngine it's cmf on ZF with service layer realisation