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.
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 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.
After reading a fair few posts on Stack, and also some material recommended to me on line, the MVC pattern is quite open to interpretation, so please don't answer with another explanation. Thanks!
I'm reaching the end of designing my own PHP MVC now, and have two possible ways to move forward with the views.
But first, my controllers are currently quite dumb, not containing any classes and simply call public methods from the suitable models, and render the appropriate view.
Views are included as necessary, so naturally the objects are available to them via the constructors, along with all the methods (inc delete/update etc).
My first option is to get data using something like this in the view
foreach($object->fetchData() as $data)
and then looping through the results. However some people do not agree with this, and have suggested that such methods should be excluded from the view. Instead it has been recommended that I assign this to a variable in the constructor, and then use this variable in the view
//constructor
$fetched_data = $object->fetchData()
// view
foreach($featched_data as $data)
I don't like this very much, as it seams messy and unnecessary.
With all my critical methods being made available to the view, could this be considered a problem?
So here's the question. Do I keep it how it is, and create new methods in the MODEL for rendering data (as above) OR can I create a class in the constructor, extend the model into it, protect the critical functions in the model, and then create my read only public methods in the CONSTRCUTOR?
Thanks!
I would create a class in the constructor. Not only would extending the model be a much safer approach, but it'd also minimize the calling of functions in the views. Am assuming you'll have several views, it's much easier to get access the constructor data than calling method functions each time in each view.
You can add classes to your controllers that will call the method functions and pass the data directly into the views, instead of clustering your constructor or bootstrap.
I want to access a controller, which is located in application/controller/example.php, from a model - located in application/model/users.php
class Users extends CI_Model {
//access the example.php controller
}
Who could i accomplish this ?
You don't want to ever do that, hence why CodeIgniter cannot do it. You should be accessing everything else from your Controller, not the other way around.
A good old resource from CodeIgniter :)
http://codeigniter.com/user_guide/overview/mvc.html
You dont have to access an controller from a model. Models (Views, helpers, libraries ect) should all be accessed from controllers. ( Model are used from manipulating data ( usually in database ) )
The idea behind the MVC is to have a Model, Viewer and Controller.
In other words the Controller handles the request, the Model gets the data and the Viewer displays something to the user.
The Model is used ONLY to manipulate the data - doesn't matter if it's a database connection or other data resource.
Model is where you store your bussines logic. Controller is where you call things and operate with data. Views are for creating output.
Bassically you can do everything from withing controller, but that is wrong, since it does not gain you any clarity. Try to offload as much as possible to models and views and keep controllers small and readable, well commented.
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