I have searched on SO about this question, but I basically haven't found one concerning this particular scenario; hence, my reason for asking.
I have a basic, abstract understanding of the MVC pattern: Controller calls the right Model based on the action needed; the Model contains the actual business/data logic, and the View displays the result. What I am having trouble understanding is the actual implementation.
Originally, my assumption was this: Controller calls Model; Model processes information, and returns the data back to Controller; Controller call the View, passing this
data to the View, which simply displays it. After reading more articles on MVC, I discovered that the Model doesn't really pass the data back to the Controller; rather, it fires an event, which allows the Controller to call the proper View.
My question centers on this event firing part:
Q.1: Must an event really be fired? Once the Model completes its processing, and returns control to the Controller, can't the Controller simply call the View?
Q.2: In an actual implementation, a Model object is injected into a Controller class. So, Model object basically has no idea what Controller called it. How does it know what Controller to fire an event to? And how do we know what Controller is expecting that notification?
Q.3: The Controller calls the View, injecting it with the current Model object, so the View can use it to obtain the needed data. Is this correct or wrong? If wrong, why is it wrong, and what is the proper way to do it?
I have read my questions on MVC on here and other sites, viewed MVC diagrams, but I haven't been able to really connect the dots the way it's supposed to be connected.
Thanks.
There are many way's on how the different components on MVC are linked together. I think there is no 'Golden Rule'.
I use it the way shown in this picture:
The creation of objects is then like this:
the app object creates a controller, depending on the route. The router is injected into the controller.
The controller creates a model, depending on the route. The model is created by a IoC container.
The controller creates a view, and injects the model into the view.
In my situation I can answer your questions like this:
Q1: No, I do not use events. There is no need. The controller calls the model, and when done the model has state, and can be used by the view.
Q2: I do it just the other way, the controller creates the model. The model has no knowledge about the controller, or view.
Q3: this is the way I implement it.
Related
By trying to follow single responsibility principle, I decided that rendering form view I could move to another class. Also to render form I already am planning to use 5 dependencies. So the main controller which injects form will have less dependencies which is good.
I never injected controller classes into a controller class. What I usually do is I create the library. I have libraries folder made as sibling to controllers folder.
But now thinking - maybe better idea would be to have another controller injected into a controller?
Tried to search for this, but did not find any examples. But at the same time tried creating controller with just constructor function and echo a string. Then inject this controller into another. And string gets displayed.
So this means it is possible to inject controller into controller. So is it good? Or maybe this would be a must?
By default laravel do not even have libraries folder which is interesting, maybe creators assumes that it is not needed.
Yes it's bad. Controllers not only must have one single responsibility, but they are also a different kind of class that should have only one job: A controller is a proxy between the HTTP request and your application (models, repositories, views). So basically it should receive an HTTP request, get some data from your models and pass it away to a view.
Everything else should be done by your support classes (models, repositories, helpers, composers, etc.).
If you are in need to call a second controller class, it's probably because you need methods on that controller that should not be in that controller, because your controllers are doing more than what their job is.
This is one of my controllers:
class Connect extends BaseController {
public function index()
{
$connections = $this->execute(GetConnectionsCommand::class);
return View::make('connections.index')->with('connections', $connections);
}
}
There's a lot happening behind the scenes in that GetConnectionsCommand to get the information to show all connections, and my controller should not know any about it all.
There are some subviews on that ´connections.index´ view, but calling subviews are a view responsibility, my controller doesn't have to know that a particular view needs subviews to be rendered. I can have a master view and some #ifs inside it to render them all properly.
A controller returns data (a rendered view, rendered by another class) back to the response object (behind scenes in Laravel), which is the guy responsible for effectively rendering the data which will be passed back to your browser. So a controller is right in the middle of something, doing very little orquestration, because, the more it knows about your business logic, the more you'll feel it needs to ´talk´ to another controller. You can think of it as MVP if you like, but this is pure MVP using the Single Responsibility Principle as it should be. But in this case the Controller is not decoupled from the view, because there is no Interface between them, so it's not really MVP.
I have a function called getThumbnail() in model.
How do I call this function in the view file.
Currently what I have to use is:
<?php
$tmp = new Model();
echo $tmp->getThumbnail(1);
?>
Is there any other way to accomplish this, because calling to Model directly from View doesn't look right.
How to do this correctly is quite a broad topic, there's no one correct answer. However, one thing I would definitely point out is that instantiating a model class inside the view is definitely wrong. Instead, you should either:
pass an instance of Model from the controller to the view, or
pass a "dispatcher" object from the controller to the view which allows the view to call any or some model functions indirectly, e.g.:
echo $dispatcher->dispatch('Model', 'getThumbnail', 1);
It makes a lot of sense if the model methods this dispatcher allows are restricted, to enforce decent separation of concerns. For example, the view should never make any calls that modify state in the model, like User::createNewUser or some such. The view should only be allowed to call "passive" model methods to get data.
The main point being here that you want to inject dependencies into the view, instead of hardcoding specific model calls directly. This pretty much goes for any dependency, not just view-model relations.
It's not a good idea to call to Model from the View.
Views are the minions of the controller. Model should be communicated only from the controller.
Okay so this is a bit complicated but I will try to explain it as simple as possible.
I have a Model class which does all the activity and stores information in arrays.
I have a Controller class which makes a new Model class and calls required action from Model class to perform the activity.
But all that has to happen from a View file. So I submit a form from my View file, refresh the page and upon refresh, my Controller class checks if the form has been submitted or not, if true then it starts creating an object from my Model class.
Now, here's the part I am having problem. I again need to redirect the page within the Controller class, basically what it is doing is upon refresh it is actually calling the action within the Controller class itself according to data being sent by the Model class. e.g
In my Controller class there is a constructor that creates a new Model object calls Model action and has if and else statement to check for the data being sent by Model class.
Now, based on the value it calls/redirects to my two other action in Controller class. But as I redirect using
header("model/controller/");
my arrays are lost and there is no way I can pass my arrays from Controller to the View.
I have tried
header("model/controller/".$array);
and passing it through urls. But I would rather not pass it through urls.
So is it even possible to achieve what I am trying to accomplish?
Also, sorry if this might be a naive question or a very bad programming practice, I'm just learning. Critiques are very much welcome.
What you're asking is How to persist data between two HTTP requests, and the answer is usually to use sessions. It has nothing to do with MVC.
I think the only way to pass it like that is to use
$data = implode('/',$array);
header("model/controller/".$data);
and when receiving them, in your model use this code:
$data = explode('/',fun_get_args());
// OR
$data = explode('/',$requestURL);
// $requestURL to be replaced with a function depending on your MVC
Hope this may help you
I have seen all types of tutorials:
View running controller, controller passing model to the view, controller setting setter of view.
An example: MVC for a reading of a news.
The controller loads the Model. If the result of the model is 'false' I can call another method from another model containing different block.
The View class must be relevant to, View_found View_not_found?
if (model-> news === true) {
$ comment = model-> comment ()
}
Would this code snippet be the responsibility of the controller or is it a rule that such logic should belong to business model?
in my experience, i tend to program the model and view as "blind". the model and view only receives parameters needed and then spits out what is needed. they should do minimal to no logic at all.
for the model it performs minor checks, like parameter type and validity and returns either a result or false. the controller does not know how the data is stored, where, why etc.
for the view, it should receive a string preferably through only one entry point, a function which will do the escape and echo. other than that, the controller should never echo to a page.
everything else is for the controller to digest like validation, calling what's needed, determine what is what. the controller sees everything:
//get from model, pass parameter - that's it
if (model-> news ('all')) {
//manipulate data for result
//get appropriate view
view->parse(html); //pass html to view, that's it
} else {
//manipulate data for no result
//get appropriate view
view->parse(html); //pass html to view, that's it
}
If you want to find model News comment, you need to create Comment model and get it from your dataProvider and render to view.
Here is a part of controller action code :-). All logic must be in controller. Views is only render content parts.
UPDATED I recommend using here dataProvider. Model method (getter) can return DP object for model.
It depends which framework you're using.
Like said Rasmus Lerdorf
MVC is the current buzz in web application architectures. It comes from4event-driven desktop application design and doesn't fit into web application5design very well. But luckily nobody really knows what MVC means, so we can6call our presentation layer separation mechanism MVC and move on.
As a matter of fact, in web application, it is common to use "action oriented MVC" instead of "event MVC".
You've got a controller that knows his model, and the view to apply.
To display news, You must have a News class which is your model, a NewsProvider which deals with your database.
Your controller compute the datas given by the database and the user and call the proper view.
The best practice is to keep business logic in Models
see below links for reference
http://www.yiiframework.com/doc/guide/1.1/en/basics.best-practices
ASP.NET MVC - Should business logic exist in controllers?
http://blogs.msdn.com/b/aspnetue/archive/2010/09/17/second_2d00_post.aspx
As I understand it, MVP is a derivative of MVC where the Model and the View are loosely or completely decoupled, and the Presenter replaces the Controller and acts as the bridge between the View and the Model. This pattern seems more appropriate than traditional MVC in web applications (whether or not that is true is not the subject of this question, so please refrain from going down that direction).
My problem is in implementing the various MVP pieces in PHP, using a passive view. Here is my current flow of things:
The PHP script sets up an autoloader and a router. To me, this means whatever view was in existence send an event of some kind to the server.
The router then determines which presenter should be used based on the request.
Here be dragons. The Presenter acts as the bridge between the View and the Model and should take a View and a Model as dependencies so it can easily be tested. That means I need to know what model and view I should be using before the presenter is created.
The presenter seems to be the class that knows what Model and what View it needs, so how can I move that logic out of the presenter? I understand that the generic pattern to use is a factory, I just can't seem to understand how to implement it in this case.
Perhaps I am doing this all wrong. Maybe I've been coding for too long of a stretch and am experiencing mind warp. Regardless of why I can't seem to understand how to solve this problem, I'll accept any guidance.
Not 100% sure I know what you're asking. You are right that you load the appropriate controller based on the request. That controller is typically associated with a model and a view.
Let's say you have a URL that looks like: http://www.example.com/test/view/1
It would be fairly standard to load the Test controller, call the method view pass it the argument 1. So let's assume you have:
TestController.php
TestModel.php
test.php (view)
When the TestController loads it includes the model, TestModel, where your "data stuff" goes (I think you understand that). So for this example, let's say view wants to load the last 5 posts from the user with id 1. So in TestController.php:
function view($arg)
{
$userID = $arg;
$posts = $this->model->loadPosts($userID);
$this->render('test', $posts); // outputs the HTML in test.php
}
And in test.php, you can loop through $posts and output it however you choose.
It seems like you already know how this stuff works though, which is why I am confused as to what you're asking. Does this clear up anything?
I find it useful to think of Web Apps in terms of states and state transitions. the application is in a particular state, it's "at" a View, some HTML was with the aid of the associated Presenter from data in the Model and rendered to the browser . The user takes an action and this is going to move our app to a new state. So we are moving from one View/Presenter pair to another. In my mind the Model is a longer lived, evolving thing, I don't see us getting a new Model for each transition.
So you have PresenterA, responsible for responding to events in ViewA.
PresenterA receives some event, performs some work that may result in Model changes, and then decides which View to go to, say ViewB. ViewB can create its Presenter. As per the Wikipedia example (not PHP I realize, but the principle is clear):
public class DomainView: IDomainView
{
private IDomainPresenter domainPresenter;
public DomainView() // Constructor
{
this.domainPresenter = new ConcreteDomainPresenter(this);
}
}
In effect the Presenter is the creator of the next View/Presenter pair. If you have more complex logic replace the explicit constructor
new ConcreteDomainPresenter(this);
with a factory, working with View and Model information.