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
Related
This is a general question about MVC, but the context is CakePHP.
The Cake documentation largely avoids discussing optimal placement of model-related code, such as queries. Perhaps for simplicity's sake, or to avoid imposing any ideas on how the developer wants to structure their app, they simply always document queries as being in the controller. Essentially, a Fat Controller pattern.
e.g.
The page requires 4 large queries to show different areas of data in the view "XYZ". The end result of the queries is a very specific set of data just for view XYZ.
Fat Controller
Controller handles request
Controller runs query on model 1
Controller runs query on model 2
Controller runs query on model 3
Controller runs query on model 4
Controller performs additional logic on data
Controller sends data to view XYZ
In this situation, the controller is doing all the work and is simply leveraging Cake's built-in model framework features to query the correct tables. The model layer itself contains no custom code.
So the alternative is to use a Fat Model pattern, but then I don't feel that's correct either, particularly where the model is determining which data will be sent to the view.
Fat Model
Controller handles request
Controller calls on model 1 to retrieve data
Model 1 queries and performs additional logic on data, sends back to Controller
Controller calls on model 2 to retrieve data
Model 2 queries and performs additional logic on data, sends back to Controller
Controller calls on model 3 ...
Controller calls on model 4 ...
Controller sends data to view XYZ
This keeps the controller nice and clean, and it only serves to handle the request, delegate the retrieval of the data it needs and then forward it to the view.
The problem with this, for me, is that the model layer (probably in table classes) now contains very specific queries which retrieve data specifically formatted for view XYZ. If I want to change the data shown in view XYZ I make those changes in the model layer by modifying the methods which return the fields the view needs.
This seems wrong, and leads to large models which are bloated with tons of very specific functionality.
Question
Which approach is better?
Is there a third solution to this which allows the following separation of concerns:
Controller
Handles the request
Decides which data the view will need, but delegates the job to the model
Forwards the data from the model to the view
Stays thin
Model
Handles all business logic and database querying
Database query logic is ignorant of what the view requires
Is not bloated with specific one-use functionality for specific views
Is there another layer which can bridge the gap between the controller and the model tables, or is it pointless? What would it be in a Cake context? Custom classes outside of Tables or Entities? I fully understand that the model layer does not just mean active records or database querying.
The Cake documentation largely avoids discussing optimal placement of model-related code, such as queries.
This is not required nor the duty of the framework to educate people about design patters - IMHO. The layers and their duties are explained here. For further information use Google or read Martin Fowlers publications about design patterns.
Perhaps for simplicity's sake, or to avoid imposing any ideas on how the developer wants to structure their app,
Yes. You're free to do whatever you want but it is expected that people are at least familiar with the basics of MVC, OOP and design patterns in general. It is not the job of the frameworks documentation to teach these topics.
they simply always document queries as being in the controller. Essentially, a Fat Controller pattern.
Who are "they"? I'm sure the documentation does't encourage bad practice or anti patterns.
The problem with this, for me, is that the model layer (probably in table classes) now contains very specific queries which retrieve data specifically formatted for view XYZ. If I want to change the data shown in view XYZ I make those changes in the model layer by modifying the methods which return the fields the view needs.
Your methods are very likely to fat then and to specific. You won't be able avoid specific methods (there is always something that can't be made generic) but you should compose what they do using many smaller methods that are generic. A method should always do just one thing and do it well and the best not longer than ~80 lines.
Custom finders in Cake3 are a great way to compose queries:
public function findIndex(Query $query, array $options = [])
return $query->find('active')->find('index')->find('somethingElse');
}
We have a lot "active" checks in our app so I put the active finder into a trait and use it where I need it. The other two finders add additional stuff to the query. I'm combining three finds that can be used alone or combined differently for whatever is needed.
In your controller then just call $query = $this->Articles->find('index'); and pass it to your paginator.
Also never forget that "model" describes a complete layer and not just table objects. Cake2 probably caused that less experienced developers might have gotten the impression that model == table. We have several namespaces in App\Model that aren't related to DB actions at all or use table objects for something to get their task done.
Also there are Components for collaborating controller codes in classes and helpers to collaborate view codes in classes. So to make your controller slim you can add components for each job and use them in controller instead of doing all the stuff in the controller actions.
It has another advantage. If you put repeatable code in components then you don't need to duplicate them in each view and you stay observing the DRY (don't repeat yourself) principle.
I'm trying to understand the MVC pattern in Phalcon.
In my current application I only need ONE template file for each table. The template contains the datagrid, the SQL statement for the SELECT, the form, add/edit/delete-buttons, a search box and all things necessary to interact with the database, like connection information (of course using includes as much as possible to prevent duplicate code). (I wrote my own complex framework, which converts xml-templates into a complete HTML-page, including all generated Javascript-code and CSS, without any PHP needed for the business logic. Instead of having specific PHP classes for each table in the database, I only use standard operation-scripts and database-classes that can do everything). I'm trying to comply more with web standards though, so I'm investigating alternatives.
I tried the INVO example of Phalcon and noticed that the Companies-page needs a Companies model, a CompaniesController, a CompaniesForm and 4 different views. To me, compared to my single file template now, having so many different files is too confusing.
I agree that separating the presentation from the business logic makes sense, but I can't really understand why the model and controller need to be in separate classes. This only seems to make things more complicated. And it seems many people already are having trouble deciding what should be in the model and what should be in the controller anyway. For example validation sometimes is put in the model if it requires business logic, but otherwise in the controller, which seems quite complex.
I work in a small team only, so 'separation of concerns' (apart from the presentation and business logic) is not really the most important thing for us.
If I decide not to use separate model and controller classes,
what problems could I expect?
Phalcon's Phalcon\Mvc\Model class, which your models are supposed to extend, is designed to provide an object-oriented way of interacting with the database. For example, if your table is Shopping_Cart then you'd name your class ShoppingCart. If your table has a column "id" then you'd define a property in your class public $id;.
Phalcon also gives you methods like initialize() and beforeValidationOnCreate(). I will admit these methods can be very confusing regarding how they work and when they're ran and why you'd ever want to call it in the first place.
The initialize() is quite self-explanatory and is called whenever your class is initiated. Here you can do things like setSource if your table is named differently than your class or call methods like belongsTo and hasMany to define its relationship with other tables.
Relationship are useful since it makes it easy to do something like search for a product in a user's cart, then using the id, you'd get a reference to the Accounts table and finally grab the username of the seller of the item in the buyer's cart.
I mean, sure, you could do separate queries for this kind of stuff, but if you define the table relationships in the very beginning, why not?
In terms of what's the point of defining a dedicated model for each table in the database, you can define your own custom methods for managing the model. For example you might want to define a public function updateItemsInCart($productId,$quantity) method in your ShoppingCart class. Then the idea is whenever you need to interact with the ShoppingCart, you simply call this method and let the Model worry about the business logic. This is instead of writing some complex update query which would also work.
Yes, you can put this kind of stuff in your controller. But there's also a DRY (Don't Repeat Yourself) principle. The purpose of MVC is separation of concerns. So why follow MVC in the first place if you don't want a dedicated Models section? Well, perhaps you don't need one. Not every application requires a model. For example this code doesn't use any: https://github.com/phalcon/blog
Personally, after using Phalcon's Model structure for a while, I've started disliking their 1-tier approach to Models. I prefer multi-tier models more in the direction of entities, services, and repositories. You can find such code over here:
https://github.com/phalcon/mvc/tree/master/multiple-service-layer-model/apps/models
But such can become overkill very quickly and hard to manage due to using too much abstraction. A solution somewhere between the two is usually feasible.
But honestly, there's nothing wrong with using Phalcon's built-in database adapter for your queries. If you come across a query very difficult to write, nobody said that every one of your models needs to extend Phalcon\Mvc\Model. It's still perfectly sound logic to write something like:
$pdo = \Phalcon\DI::getDefault()->getDb()->prepare($sql);
foreach($params as $key => &$val)
{
$pdo->bindParam($key,$val);
}
$pdo->setFetchMode(PDO::FETCH_OBJ);
$pdo->execute();
$results=$pdo->fetchAll();
The models are very flexible, there's no "best" way to arrange them. The "whatever works" approach is fine. As well as the "I want my models to have a method for each operation I could possibly ever want".
I will admit that the invo and vokuro half-functional examples (built for demo purposes only) aren't so great for picking up good model designing habits. I'd advise finding a piece of software which is actually used in a serious manner, like the code for the forums: https://github.com/phalcon/forum/tree/master/app/models
Phalcon is still rather new of a framework to find good role models out there.
As you mention, regarding having all the models in one file, this is perfectly fine. Do note, as mentioned before, using setSource within initialize, you can name your classes differently than the table they're working on. You can also take advantage of namespaces and have the classes match the table names. You can take this a step further and create a single class for creating all your tables dynamically using setSource. That's assuming you want to use Phalcon's database adapter. There's nothing wrong with writing your own code on top of PDO or using another framework's database adapter out there.
As you say, separation of concerns isn't so important to you on a small team, so you can get away without a models directory. If it's any help, you could use something like what I wrote for your database adapter: http://pastie.org/10631358
then you'd toss that in your app/library directory. Load the component in your config like so:
$di->set('easySQL', function(){
return new EasySQL();
});
Then in your Basemodel you'd put:
public function easyQuery($sql,$params=array())
{
return $this->di->getEasySQL()->prepare($sql,$params)->execute()->fetchAll();
}
Finally, from a model, you can do something as simple as:
$this->easyQuery($sqlString,array(':id'=>$id));
Or define the function globally so your controllers can also use it, etc.
There's other ways to do it. Hopefully my "EasySQL" component brings you closer to your goal. Depending on your needs, maybe my "EasySQL" component is just the long way of writing:
$query = new \Phalcon\Mvc\Model\Query($sql, $di);
$matches=$query->execute($params);
If not, perhaps you're looking for something more in the direction of
$matches=MyModel::query()->where(...)->orderBy(...)->limit(...)->execute();
Which is perfectly fine.
Model, View and Controller were designed to separate each process.
Not just Phalcon uses this kind of approach, almost PHP Frameworks today uses that approach.
The Model should be the place where you're saving or updating things, it should not rely on other components but the database table itself (ONLY!), and you're just passing some boolean(if CRUD is done) or a database record query.
You could do that using your Controller, however if you'll be creating multiple controllers and you're doing the same process, it is much better to use 1 function from your model to call and to pass-in your data.
Also, Controllers supposed to be the script in the middle, it should be the one to dispatch every request, when saving records, when you need to use Model, if you need things to queue, you need to call some events, and lastly to respond using json response or showing your template adapter (volt).
We've shorten the word M-V-C, but in reality, we're processing these:
HTTP Request -> Services Loaded (including error handlers) -> The Router -> (Route Parser) -> (Dispatch to specified Controller) -> The Controller -> (Respond using JSON or Template Adapter | Call a Model | Call ACL | Call Event | Queue | API Request | etc....) -> end.
I've got a question regarding a conflict / conundrum I've run into with my application.
I want to make some common "stuff" available to all of my models and controllers, such as data from a cache, or session information, as well as the methods of my PDO wrapper.
Currently each individual feature controller and feature model extends a base controller and base model, which in turn extend a single object that does all of that common stuff.
A controller will get called by a router/dispatcher, and the controller will then call on a model to get some data. The problem with this is it means the main Object gets constructed twice: once when the feature controller is called, and again when the feature controller calls the feature model.
See the diagram below:
Obviously I'm doing something wrong, so I was wondering if there's some kind of best practice solution to this issue.
What I dont want is to have to pass the stuff the object loads, through the controller, to the model. That means any time I have to add a new common element to Object, I have to pass it through to the Model.
It's far simpler and easier for $this->cache or $this->db or $this->session to always be universally available in both controllers and models (as well as future helpers and misc classes).
How would I go about solving this issue?
Thanks :)
I think you are going in a wrong path about solving this issue.
If you are building an MVC application, you should separate concerns, thats why we use MVC. To separate Models, Controllers and Views.
You should define what do you need Model to do, what will Controller do, and use View only for presentation logic.
In proper MVC, Model is a layer that deals with business logic, database access, validation etc. So Model is not a one class. And you can use many models in one controller. And Controller is just... connection between Models and Views. Models should be fat, and Controllers should be light.
The way you are doing this is in my opinion wrong, since you can do the same stuff in both model and controller and that is not what MVC is for. Controller should not do any logic, thats why we use Models, controller only tells models what to do, and based on their reaction we tell other Models to do something else, or render View with success or error message or with posts from database etc.
The way you can do this is to once you have invoked appropriate controller, use it to get models you need. And again, model is composed of lots of classes, so your model folder can be fat. From Controller you should have only methods to access models so that models can do some actions, and report back to Controller what they did. And based on that returned value you do some more actions or call View to render.
So you should not have one object that can be extended by both models and controllers.
Your model folder can look like this:
Models
- Entities
- Forms
- Validators
- Services
...
And then you call any of them in your controller to do some action, and report back.
If you really need to have the same functionality in both controllers and models then this didnt answer your question, but I think its wrong to do it like you started.
Hope this helps you, interesting question Il try to help some more if I can.
I get a feeling, that the root of your problems is bad architecture.
The main thing you have to understand about MVC and MVC-inspired design patterns is that the pattern is made from two layers: presentation later and model layer. Those layers should not share common functionality. Controllers (as well as views and templates) are part of presentation layer.
When you have variables like $this->cache, $this->db or $this->session in the controller, it means that you have a severe leak of abstraction. These are storage structures, which should be hidden fairly deep in the model layer. If your controller is interaction with them directly, you do not have a controller.
Next problem is your base class (the one you call Object for some reason .. while objects kinda are instances of a class). It seems to be responsible for quite a lot, especially the instantiation of different abstraction for interaction with storage. If you controller needs a PDO instance (for some exceptionally bizarre reason), then it should be injected in the constructor. Same goes for cache and session management.
And then there is that small thing that model is not an object or a class. It is a layer. And just like presentation layer it is composed from different kinds of structures. Usually the recommendation is to have:
structures that deal with logical entities, which is usually what domain objects are for
one or more types of storage abstractions: data mapper, repository, unit of work, dao and/or some similar structures.
something, that controls the interaction between the above mentioned structures so that they do not leak in the presentation layer, commonly referred as services
And yes, you are correct assuming that using controller to pass along structures is a bad practice. It violates LoD. Instead you should be providing your controller with a factory, that instantiates your model layer structures and provides them with necessary dependencies .. this post might help.
my two cents on the subject .. for a more precise advice you would have to show some code
Shouldn't models just describe data that will be passed from a controller to a view? Doesn't that make models unnecessary in weakly typed languages? In PHP, they are doing DB work in models, but isn't that wrong? As I see it, models are just unnecessary in weakly typed languages...
There are some misconceptions about the term model. Microsoft's MVC3 framework has the concept of a view-model, which is simply the data you use to render your views. This isn't however what the M stands for exactly in MVC. The model includes your business entities. We have thin controllers and fat models, but very thin view models. Our controllers make calls to services that perform business logic, and the controllers never do this logic themselves. We then translate our business entities (our data models) and convert them into a lightweight view model, which can be used for rendering a view.
So to answer your question
Shouldn't model just describe data that will be passed from controller to view?
Then perhaps what you are really asking is aren't view-models unnecessary? I'm not sure why you think this. View model + view makes the result. In PHP it can be helpful to define a class with easily accessible properties on it. This is just sensible for clarifying your expectations and prevents you from calling methods with hideously long sets or arguments. In JavaScript there is no need to define a view model as such, you just push the properties onto a new object and pass it along with your view to your view rendering logic. This is more a reflection of the OO pattern these languages use and not the fact that they are weakly typed.
If you are asking if model is unnecessary, then you have missed the purpose of the MVC architecture. A big part of MVC is that you separate your concerns. Why apply any architecture to your code? I am sure you can find a better explanation of the motivation behind MVC than I can give you.
A model is a useful conceptual tool, even if it's not strictly necessary in PHP to separate it from the DB code e.g. you can have a data object associated with each table that encapsulates some business logic, or define a set of business entities that aggregate the data across tables into domain-specific objects that the controllers can then use, or just have one monster DB object that has all the access functions and returns the entities. This has definite advantages over having DB code directly in use by the controllers:
If you are defining complex data structures that run across DB tables, you don't want to do that in controller code due to the risk of duplication - far better to have a single definition that enforces consistency across the system. Although this can introduce dependencies, having one function/object that defines that data makes it easy to find out where the data is used so you can fix things.
Third party maintenance is far easier if there's one place to go to where all the data structure definitions are found.
It makes unit testing easier if you can swap out the whole model or parts of it and replace it with mock object(s) that will provide test data
It makes controllers lighter and therefore more readable and maintainable
So you could argue that it's not necessary, but it helps a lot.
I've always seen models as a tool to provide data. That means that your controller doesn't ever have to worry about the data source, and if you want to switch from using a database to XML files then you only have to swap out your model.
So long as you have some data provider abstraction. Some Models will do low level validation (tightly coupled to the storage engine - null checks etc) but the controller "should" do all of the business logic/validation.
I personally have a thin struct like class that is mapped to each table (all implementing IDataStruct). This struct, or a collection thereof, is the only thing that moves between the DomainObject and the DataProvider. I can then enforce via my interface what datastruct I should be receiving. This is not a silver bullet but I have found it to work well (Makes things like caching and unit testing quite easy)
I hope this hasn't confused the issue.
I am using Zend framework and doctrine in this app
In my web application i have various individual modules like events, conferences, case studies.. so i am making controller design at this moment. In the below image regulatory document is the controller and its sub are its actions. So regulatory doc, videos, podcasts all are having almost the same kind of functionality. so is this design appropriate...?
In mvc for each action i will be having a separate view. And on user type i may have to put access levels on this modules. so i have kept separate controller so that i can easily control the module for each user type. But this is resulting in duplicate code.
Now i am thinking to make one parent class and in that i will have all the common methods. eg. I will have common class Resources and in that i will keep list, search, suggest, addFavorite etc. And that will be the parent to the above given controllers.
So than how will i manage my view for all these different modules if i go with this approach..? if i go with this than my code will be bit messy..?
I would suggest to keep all the controllers to have nice URLs and clear structure in the modules, however keep the controllers thin. Put your domain logic into Services or Entities, hence no (or just less) code duplication is required.
More in:
Is MVC + Service Layer common in zend or PHP?
How to implement service layer in Zend Framework?
From DDD:
http://domaindrivendesign.org/node/118
controllers belong to application layer / domain logic belongs to domain layer
If I understand you correctly you have a set of common behaviors among your regulatory documents, videos and podcasts.
In this case you should probably try to abstract the commonalities out into a parent class from which these three areas inherit.
As an example, I have my own MVC framework where I define a superclass tnh_controller from which my other controllers (eg: venue_controller, group_controller) inherit. In the parent controller I define the header() and footer() and delete() methods. I can then use those unchanged in the child classes and save myself some effort.
You can likewise do some of the common work for your models (CRUD) in a model superclass, only overriding it as needed. Most of the logic for different models comes from class variables (table names, column names, etc).
I wouldn't worry too much about being "strict" MVC. Instead try to work out what will save you time and keep your code organized. It sounds like you're on the right track putting similar behaviors at a parent level.
You can still have a separate controller to contain suggest, addFavorite actions without having to make it the parent class for all the controllers. Basically the UI elements related to these you can render as partial views and call on to the actions in the relevant controller. That way you can get rid of the problem with the views.
MVC designing means that for each view, you have a controller and a model. However, the models don't need to be classes at all, nor having a different model for each MVC. Usually you will share a model between some MVCs, or your model might just be an integer value which you define in the own controller. Usually, you might even want to share data between them, then you will have a singleton mode:
http://www.galloway.me.uk/tutorials/singleton-classes/