Recently I began to study SF2 but there are some doubts which I'd like to solve:
Let's say that I have a lot (more than 100) of Models which extend one generic model(Entity). Each model has unique functions (rules for parsing content from model source), what is the best way to organize it?
In ZF1 I would create Model/ModelType/ModelName.php file for every model which need customization, in SF2 I'm not sure what kind of entity should I use: One service container which calls entities and call their custom functions (implemented through interface), or maybe one huge Service which has different functions for every single model?
Thanks in advance.
If parsing functions based only on current entity state (use only entity property) it's better to use entity method. Entity aslo can implement some interface, e.g. ParsableInterface.
If paring function need to use another entities it's better to use standalone services handle parsing
Related
I'm learning Symfony and I'm trying to figure out where to put custom actions over an Entity...
For example, if I have an entity Order, where to put $order->complete()? Or $order->sendToProduction(), $order->queueForDelivery()?
Those are just examples, I have complex entities and I must perform on them many actions.
In the Controller?
No, because the same action may be called from different controllers
In the Entity?
That would be the more appropriate way in a MVC model, but here I can't find an easy way to perform custom mysql query (doctrine/em is not available) from inside the Entity class, which I find strange since db operations should be perfomed at the Entity level, I believe...
In the EntityController?
It doesn't seem appropriate, and it's not easy to call repository methods from a listener, for example, and call them directly on the object...
What else? Do I have to create services? Utility classes?
If the work can be done inside a signle entity (and it's relations of course) then it should be placed there. I mean, if the operation is about changing entity's internal state.
Otherwise, if this job need to use other parts of application like database, or is performed on multiple not related entites, then I would suggest using services.
That's what where are for. Service is basically a class that can do anything. Using Service container, you can pass any dependencies to it so it's very flexible and easy to use.
For example $order->queueForDelivery(). That may mean a few different things:
changing internal state like change status to queued_for_delivery - then it should be in Order entity class
$order should be put in the Queue that is other entity class, then it should be in Queue class like $queue->addOrder($order)
this queue is an external service like RabbitMQ or anything else. Then you should use a service class.
I am interested in learning about best practices for persistence code in Symfony2 when not using an ORM and not having objects represent my table rows.
One way would be to create a model / dao directory and store classes with wrapper methods (e.g. getPost($id), addPost($title, $content) for a blog post). Then access these methods inside the service class which has similarly named methods as getPost($id) etc. which might just be calling the wrapper methods in the model / dao classes or doing a bit more work (preprocessing data to send to db, postprocessing data received from db).
Do you think this is a reasonable approach or is there something better you can think of? Thanks.
I'm currently developing a simple web application with Symfony 2 that process orders with products and lines of orders. Actually I have three Doctrine entities (Product, Line and Order). I will work with the data of these models and I need filter by date, add, delete, list, and make some administrative things with all the data.
As far I know this will be Service territory and is best practice to keep the controller away from doing this.
My question really is if I need to create ONE class with the methods that I need for all operations and then call them from the Controller, or create one Service class for each Doctrine Model (OrderManager, LineManager...) or orient more to task specific (RecountTotal, FilterDate...) But with the last method I think that each Service will have only one method inside.
Which is the best practice for this?
You are totally correct in stating this is NOT a job for controller.
It's totally fine to use only one manager to contain all your data access methods.
class BaseManager { // Name it as you like
...
}
If you find yourself having very similar methods for different entities, you may want to split into different managers (OrderManager, LineManager, ProductManager) and have them extend a common BaseManager to reduce code duplication.
Additional classes for filters and counting should not be necessary unless you have some advanced requirements.
I am new to Symfony2 and I am not sure where I should save a class that updated multiple tables(entities).
From reading documentation and tutorials it says I should not put any other tables reference within the entity class; I could put it within the controller class, but again many people have said this class should be as simple as possible and not include business logic; Not in repositories, because these are used for query data and not for update or inserting.
Is there a standard folder structure where another type of class for working with multiple entities(tables) should be saved? Should the business logic really be stored in the controller classes?
Symfony2 is very flexible in this regard.
You're right, entities are for one "table" only.
I would suggest you look into Services, as they are a good way to move your code from a controller to a separate class. You basically call your service and use the functions it provides. This will slim your controller down.
My understanding of the MVC is as follows (incase it's horribly wrong, I am afterall new to it)
Models are the things that interface with the database
Views are the design/layout of the page
Controllers are where everything starts and are essentially the page logic
I'm using CodeIgniter but I would hazard a guess it's not just limited to that or possibly even just to PHP frameworks.
Where do I put global classes?
I may have a model for Products and I then run a query that collects 20 products from the database. Do I now make 20 models or should I have a separate class for it, if the latter, where do I put this class (other controllers will need to use it too)
Model is the wrong word to use when discussing what to do with products: each product is a value object (VO) (or data transfer objet/DTO, whatever fits in your mouth better). Value objects generally have the same fields that a table contains. In your case ProductVO should have the fields that are in Products table.
Model is a Data Access Object (DAO) that has methods like
findByPk --> returns a single value object
findAll --> returns a collection of value objects (0-n)
etc.
In your case you would have a ProductDAO that has something like the above methods. This ProductDAO would then return ProductVO's and collections of them.
Data Access Objects can also return Business Objects (BO) which may contain multiple VO's and additional methods that are business case specific.
Addendum:
In your controller you call a ProductDAO to find the products you want.
The returned ProductVO(s) are then passed to the view (as request attributes in Java). The view then loops through/displays the data from the productVO's.
Model is part of your application where business logic happens. Model represents real life relations and dependencies between objects, like: Employee reports to a Manager, Manager supervises many Employees, Manager can assign Task to Employee, Task sends out notification when overdue. Model CAN and most often DO interface with database, but this is not a requirement.
View is basically everything that can be displayed or help in displaying. View contains templates, template objects, handles template composition and nesting, wraps with headers and footers, and produces output in one of well known formats (X/HTML, but also XML, RSS/Atom, CSV).
Controller is a translation layer that translates user actions to model operations. In other words, it tells model what to do and returns a response. Controller methods should be as small as possible and all business processing should be done in Model, and view logic processing should take place in View.
Now, back to your question. It really depends if you need separate class for each product. In most cases, one class will suffice and 20 instances of it should be created. As products represent business logic it should belong to Model part of your application.
In CakePHP there are 3 more "parts" :
Behaviors
Components
Helpers
Logic that are used by many models should be made as a behavior. I do not know if CodeIgniter have this logic or not, but if it doesnt, I would try to implement it as such. You can read about behaviors here.
(Components helps controller share logic and helpers help views in the same way).
The simplest way is to:
Have a model class per database table. In this case it would be an object that held all the Product details.
Put these classes into a package/namespace, e.g., com.company.model (Java / C#)
Put the DAO classes into a package like com.company.model.dao
Your view will consume data from the session/request/controller In this case I would have a List<Product>.
Oh, you're using PHP. Dunno how that changes things, but I imagine it has a Collections framework like any modern language.
#Alexander mentions CakePHPs Behaviors, Components and Helpers. These are excellent for abstracting out common functionality. I find the Behaviors particularly useful as of course the bulk of the business logic is carried in the models. I am currently working on a project where we have behaviors like:
Lockable
Publishable
Tagable
Rateable
Commentable
etc.
For code that transcends even the MVC framework i.e. code libraries that you use for various things that are not tied in to the particular framework you are using - in our case things like video encoding classes etc. CakePHP has the vendors folder.
Anything that effectively has nothing to do with CakePHP goes in there.
I suspect CodeIgniter doesn't have quite as flexible a structure, it's smaller and lighter than CakePHP, but a quick look at the CakePHP Manual to see how Behaviors, Components, Helpers, and the Vendors folder may be helpful.
It should be an easy matter to just include some common helper classes from your models keep nice and DRY