about MVC application - php

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

Related

PHP MVC - One view class for all controllers vs a view class for each controller

I am creating an MVC inspired PHP framework, mainly for learning purposes.
I basically have the framework created and am building an app on it and improving the framework as i go along.
I am still confused/not sure about certain aspects of this sort of architecture, and at the moment i am questioning my implementation of the View part.
How i have set up my framework:
Its a very simple set up, for example: you go to the url /post/post_id, this will load index.php which will instantiate the router. The router will then check the url and instantiate the correct controller and method based on the url. In this case it would be PostController, and the method would be a default method that would use the post_id to get the posts data from the relevant model. Next the controller would set up a "data" variable that will hold the data to pass on to the View, and this is where i am confused - should it send to its own View object (a view class file dedicated to the PostController), or to a generally used View class that is used by all controllers to load an html file?
At the moment my controller is sending data to the View class, this data includes what template file should be included/shown, and the actual data for the page (what we got from the Model through the controller).
My question is this:
Should this type of system have one View object that renders all of the views (html files) based on what data is given to the "render" method, or, should each controller that eventually sends data to the View have its own View object/class?
Meaning, should PostController send a request to the general view class, the same one that is used by all controllers to renders pages, or should the PostController send to a dedicated View Class (call it PostView if it makes it clearer), and this class will then render the specific html file?
Basically if it should be one View class for all controllers that will render what ever html file the controller tells it to, or if there should be many View classes, one for each page load.
NOTE:
I know a lot of questions have already been asked about MVC in PHP, but i could not find an answer to my question in any of the answers.
A bit about MVC:
In the original MVC pattern (presented by Trygve Reenskaug in 1979), the controller updates the model, the model notifies the view about the changes, and the view pulls its data from it. Though the pattern was thought for desktop applications - each M-V-C "triad" beeing related to a single control in a window (a button, a textbox, a checkbox, etc). So, each control on the screen had an MVC "attached" to it.
Since, in web applications, the model-to-view notification step is not (or can not be) present, the original pattern can not be applied as is to them.
But a most similar approach can still be relatively easily implemented: the controller updates the model, the view pulls data from it (irrespective of the controller). I think it's called "Web MVC Model 2".
There is a multitude of web MVC variations. You are using one in which the controller takes the role of an intermediary between the model and the view.
So the controller is the only one component communicating with the model.
The view's responsibility:
The responsibility of the view component is the presentation logic - which should not be assumed by the controller at all. Beside loading and rendering template files, this kind of logic involves the preparation of the data fetched from the model for displaying purposes. The result of the preparation should, preferably, be a list of values of primitive types (strings, booleans, integers, arrays, etc) which can be easily "injected" into the template files during the load-and-render process.
Examples of presentation logic:
Example #1: If you would fetch the value 123.45 (from the column amount of a table revenues) from the model, the presentation logic would consist of formatting it to the string 123.45 USD, in order to be displayed in a template file.
Example #2: Formatting a fetched date value of 28/05/2019 to 2019-05-28 by using a code snippet like this:
$fetchedDateFromModel = '28/05/2019';
$time = strtotime($fetchedDateFromModel);
$formattedDate = date('Y-m-d', $time);
The value of $formattedDate would then be "injected" into a template file.
Example #3: Setting a boolean value based on some model data, in order to be used in a template file for deciding if a button ("Get Bonus") should be active or not.
$paidAmount = 512.79; /* model data */
$isActiveGetBonusButton = false;
if ($paidAmount > 500) {
$isActiveGetBonusButton = true;
}
The answer (in respect of your chosen MVC approach):
By using a View instance in all controllers, you would be forced to perform specific presentation logic in each controller - before passing its result (e.g. the list of the prepared values) to the used View instance, in order to further just be "injected" in a specific template file.
Whereas, if you are implementing a dedicated view class (like PostView - which, preferably, inherit a base class View containing the render() method) for a controller class (like PostController) - so a 1:1 relationship, but see it as a loose one! - you can pass the data fetched from the model, in an unprepared form, from the controller to the view. The view class would then correctly take the responsibility of preparing the data for displaying prior to actually load and render a specific template file. E.g. of performing the whole specific presentation logic.
Note: In "Web MVC Model 2" - where, ideally, the controller has no knowledge of the view component - the above argument is more obvious:
the PostController just updates the model (when an update step is required);
the PostView fetches data from model, prepares it for display, and displays it (by loading & rendering a template file like posts.html.twig, for example). In other words, the view component performs the whole presentation logic by itself.
The best way, IMO, is to have this View or Template class do all the work related to views with just one simple method: render(string $templateName, array $context = []).
This allows for easy extension or creation of adapters. You should make your controllers use this method. If you use a DI Container in your framework, you could do a TemplatingAwareInterface and implement that with a trait that allows setter injection. That will inject the templating service on fetching from the service container. That way, you can use $this->templating->render() in your controller, without having to either make it global, nor constructing the templating service inside the controller, nor injecting the container into the controller.
Having one view class for each type of controller is cumbersome, harder to maintain and I don't really see a reason for it.

MVC concept - who's responsabillity is to load a model?

OK I now basics of the MVC concept, and I know there are similar questions asked but still didn't find clear answer on this. Reading about MVC I found some contradictory examples, so I wanted to find out which concept is better.
Should I use my controller to load data from the model and than pass that data to the view or should I let the view to load data from the model and use controller just to select the appropriate view.
The more natural(right) way to me is that controller should load the model, but than again if I have require the same content that has 2 different views, for example:
view displays simple article text
view displays same article text but also displays box with article author info.
The thing that confuses me is I have single request, show me article with ID 33. In the first case everything is clear, but now my second view renders using different template that shows additional data (about the author), so should I let the view to request data from the model (about author) or that entire logic should be done by controller?
It's confusing because now the controller should request appropriate data from the model based on template the view should render.
Hope I make sense :)
Short answer: Pass the model to the controller and the view.
Long answer: In MVC, the controller does not "load data from the model then pass that data to the view". The view has a direct relationship with the model and requests data from it. See: How is MVC supposed to work in CodeIgniter and http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller : "A view requests from the model the information that it needs to generate an output representation."
As such, to enable loose coupling, initiate the model view and controller completely independently and pass them in to eachother.
This allows the strict separation of concerns MVC advocates and allows you to reuse any component with any other as nothing is hardcoded.
Something like:
$model = new Model;
$controller = new Controller($model);
$view = new View($model, $controller);
echo $view->output();
The controller should not select the view, nor should it select the model. By putting this responsibility in the controller, the controller is not reusable with other views or models.
Edit: I've updated this to answer tresko's comment about why the view needs to know about its controller.
The view needs the controller in order to avoid hardcoding controllers into views. This is so that a view knows which controller it's paired with in the current context and can post back to it.
Events (user actions) are fired in the view and need to be handled by controllers.
There are 3 ways of doing it:
1) Hardcode the view:controller relationship, on the web this is achieved by using <a href="/some/hardcoded/route"; or <a href="' . $this->router->create('someController, 'action') . '>' This removes the possibility to use the view with any other controller which isn't desirable.
2) Pass the controller to the view and let the view know which controller its events will be fired to. On the web, using this approach the view will also need a Router which will convert a controller action into a route. e.g. <a href="' . $this->router->getRoute($this->controller, 'action') . '>'
3) Pass the view to the controller and have the controller set actions on the view: (controller code) $this->view->setEvent('buttonClick', $this->router->getRoute($this, 'action'))... (view code) <a href="' . $this->getEvent('buttonClick') . '>'
Of these,
1) Is the least desirable as it heavily impacts flexibility. The view can only ever call actions on a very specific controller.
2) is the least amount of work for the developer but each controller needs a specific interface.
3) This offers the most technical flexibility but there's more work for the developer and the controller needs to know a lot about its view, beyond the API it must know what events are available in the view. If a view is updated and has a new action, each controller will need to be updated to account for it. This applies to 2) as well, but because 2 can easily be handled using interfaces it's far easier to track down every class which uses it.
In my opinion, 2 and 3 are both good approaches but 2 is superior because it allows for a much more robust system and allows the most re-use, the downside is that controllers must implement a specific interface. 3 allows the controller to have any interface but it must know quite a lot about its view.
CakePHP and other popular frameworks tend to hardcode the relationship (e.g. http://book.cakephp.org/2.0/en/views.html ) here in their example, echo $this->Html->link('edit', array( 'action' => 'edit', $post['Post']['id'])); ?> the link can only go to the "Edit" controller. This severely impacts reuse.
My suggestion is that the logic for combining data sources with views should happen entirely in the controller. Views should not be bound to specific data sources.
For example, if you had a view that used the Smarty syntax (or similar) with named placeholders, then you could use any data source, text, model, etc to provide information to render into the template. If the view is tied to a model, you'd need to modify the model and view with an awareness of the impact on the other.
Tight coupling like that leads to more problems by accidentally overlooking something than looser coupling, which gives you fewer chances of breaking something by accident.
EXAMPLE:
class Page_Controller extends Controller {
// __construct/__destruct/__callStatic/__call/etc, whatever you need in your implementation
// -------------------------------------------------------
// Adjust to suit your situation for passing data
// This controller doesn't care where objSource comes from
// -------------------------------------------------------
private function pageSpecificImplementation($objSource = null){
// using a factory class - but assume a view is created in whatever way works for you
// the key thing here is that the view could be anything that can be returned as a string - but use whatever works for you
$tplMain = make::view( 'template-url-or-path' )->assign(array(
'placeholder1' => $objSource->value1,
'placeholder2' => $objSource->value2
));
$tplSub = make::view( 'template-url-or-path' )->assign( $objSource );
$tplMain->assign('sub',$tplSub->render())->render();
// $tpl is some form of html? csv?, who knows - not relevant at THIS stage
// okay - now I know what I want to do!
// decide what to do with it here - output headers for html
// save to a file
// output and cache the output, whatever works for you here
// output to pdf?
// send as an email?
output::html( $tplMain, $cacheable, $cachetime... );
// output::email( $tplMain, $extra_params );
// output::pdf( $tplMain, $extra_params );
}
}
Here, you're using a view, without tightly coupling it to the output. Your controller can modify the output based on whatever business rules are in play when it's run, but the data source is not tied to the view and the output isn't tied to the view.
I'd suggest 'some' implementation that separates in a way that follows similar principles. YMMV depending on what you're doing and how you want to implement it, but try to keep each element separated in MVC.
In some implementations you'll see the logic for 'replacing' things in views done without mentioning 'what' view. This is commonly done in Smarty. The view can then be determined by the Controller's flow. Data can be pulled from multiple models or other sources, which may, or may not, affect which View is appropriate.
So, you should definitely separate loading of data from the view. Keep it in the controller, which is where decisions should be made. Views shouldn't connect with models unless you have a specific use case in mind, such as a theme model with a tightly coupled theme view where there's no additional business logic involved (unlikely but possible?).

Basic MVC (PHP) Structure

I have the following data flow for a simple login form.
User access controller PHP file. Controller includes model.php and view.php
User submits form, controller sends POST data to model methods, and gets a result back.
User is logged in, and forwarded to a different view (login success message) by the controller.
Currently my views are static HTML (no PHP), so here is my question. What is the correct way to then pass the user a welcome message, e.g "Hello, Craig!"?
Is the view allowed PHP snippets, e.g
<?php echo $username; ?>
since the model is loaded before it in the controller file?
Thanks!
Edit: Is it better practice then to allow the view to access specific class methods e.g
<?php $user->getUsername(); ?>
as opposed to just variables?
Based on other answers, I have found a very useful article, which you may also be interested in.
http://www.nathandavison.com/posts/view/7/custom-php-mvc-tutorial-part-5-views
Here are few things you must consider:
You cannot do classical MVC in PHP. Instead we have MVC-inspired patterns
There exists 1:1 relation between view and controller instances, when implemented for web
Model in MVC is not a class. It is a layer, that contains a lot of different classes
View is not a dumb template, but an instance of class, which deals with presentation logic
View in Web-based MVC
As stated above, views in MVC and MVC-inspired patterns are responsible for presentation logic. That encompass things like showing error messages and pagination. To do this, each view can handle several templates.
View receives information from the model layer, and acts accordingly. The way how the information from model layer ends up in views is one of most significant differences in MVC-ish patterns:
classical MVC pattern
Structures from model layer send the information to view, when state of model has been altered. This is done via observer pattern.
Model2 MVC and HMVC patterns
View has direct access to the model layer and is able to request information from it. This is the closest to the original pattern.
MVVM and MVP patterns
View receives information through controller, which has in turn requested it from model layer. The further difference in patterns stems from what the do with data before passing it to view.
What you seem to have now is actually just a template. Similar to one, that is described in this article. You end up with a structure, that has no place to contain the presentation logic. In long-run this will cause the presentation logic to be pushed into controller.
So what about that "welcome" message ?
To show the welcome message, your view should request from model layer the name of current user. If the model layer returns some sort of error state, view pick the error message template and inserts into the layout.
In case if name of the user was retrieved from model layer without problems, view pick the template which would contain the greeting, sets the value in the template and renders it.
In what order parts should be loaded ?
The idea, that controller should initialize model and view, comes from very primitive interpretation of MVC for web. Pattern know as page controller, which tried to graft MVC directly on static web pages.
In my opinion, this should be the order:
Model
You initialize the structure, through which you will deal with model layer. It most likely would be some sort of service factory, which would let you build things like Authentication service for logins and Library service for handling documents. Things like that. I wrote a bit long'ish comment on model layer's structure earlier. You might find it useful.
View
You create a view instance based on information, that you collected from routing mechanism. If you are implementing Model2 or HMVC, then your view will require an instance of Service Factory in the constructor.
If you are implementing MVVM or MVP, then view's constructor has no special requirements.
Controller
This is the last structure, which you create, because controller is responsible for sending commands to both view and model layer, which then change then change the state of both. Therefore controller should expect to receive both view and service factory in the constructor.
After basic elements of MVC have been initialized, you call a method on the controller, and render current view.
Just keep in mind that this is very simplified description.
You can really put anything in a view that you'd like, but to better adhere to the MVC way of doing things you should restrict PHP in the view to simple echos or prints (possibly really small loops as well, although even those can be pre-calculated in the controller/model). Since that is the only way to get dynamic content, it would be a little silly to say that they are not allowed.
The idea of the view is to let it have a more HTML look-and-feel, so that front-end developers or people who don't know PHP can easily be able to work with the file without getting confused.
Update
To learn more about MVC in general, you can see any of these (there's a ton of tutorials out there):
http://blog.iandavis.com/2008/12/09/what-are-the-benefits-of-mvc/
http://php-html.net/tutorials/model-view-controller-in-php/
http://www.tonymarston.net/php-mysql/model-view-controller.html
To see concrete examples of PHP using MVC, I suggest downloading some of the more prevelant frameworks (such as CodeIgniter, Symfony or Drupal) and just looking through the code. Try to figure out how it works and then recreate the functionality for a simple article-based system.

Implementing MVP in Web Applications

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.

How do MVC components fit together?

I've seen a number of examples of ways MVC components fit together on the web.
The Controller retrives data from the Model and passes it to the View
This seems a bit verbose and messy.
$model = new Model;
$view = new View;
$view->set('foo', $model->getFoo());
$view->display();
The Controller passes the Model to the View
What if the View needs data from multiple Models?
$model = new Model;
$view = new View($model);
$view->display(); //View takes what is needed from the Model
The Controller passes the View to the Model
$view = new View;
$model = new Model($view);
$view->display(); //Model has told the View what is needed
Which of these is the "best" way to go about things? If none, what is?
The Controller retrives data from the Model and passes it to the View
As you said it's verbose and messy. But that's the most appropriate solution with the philosophy of MVC.
The Controller passes the Model to the View
Seems valid too. However it'll require for the view to ask for some model method. Which is not really in the spirit of MVC. Your view should only render the datas that are provided to it, without caring about the context.
The Controller passes the View to the Model
Forget that one. Here it is messy.
The answer is self evident if you consider that the 'model' is the central artifact (potentially used across applications), and that a 'view' may (or may not) be aware of the specific model but it is (by definition) a 'view' of a (potentially abstract) model and again, potentially usable across applications. The 'controller' is managing interactions and is the most application specific element of the pattern, so it definitively needs to know about model and view details.
If the view is specific to a given model, you can use option 2.
If the view is for an abstract model (and you can use it to display info from a set of models), you use option 1.
Option 3 is simply wrong.
The answer to the original question is:
The Controller retrives data from the Model and passes it to the View
MVC is actually very neat and clean. Remember what it is addressing:
Code reuse (Models do not rely on controllers or views. Views do not rely on controllers or models. Controllers are app specific.)
Separation of Logic (For instance changing an authentication backend from MySQL to LDAP require 0 change to a view. Changing a view's layout requires 0 change to model. Changing the database table structure requires 0 change to the controller or view).
Now IF you want your forms to be automatically generated from a table structure - the views are now tied to the table (tightly coupled). A change in the table require a change in the view (albeit potentially automatically). This may take less code - but the view is no longer dependable from a code-reuse stand point.
Similarly your views (in MVC) should be nothing more than templates. There should be no logic - just variables. All the "logic", aka business rules, reside in the controller. The models know how to get data and keep it normalized. The views know how to display data. The controller knows when to use the data and which views to apply the data to.
MVC is a strict 3-tier architecture. A two tiered architecture is valid for some applications. For quick mashups and "getting crap done" a one tied architecture can be appropriate (but you don't get style points).
Hope this helps.
IMHO, option 2 (the Controller passes the model to the view) best maintains the proper decoupling and separation of concerns. If the view needs multiple models, the model passed in should be a composite data type that contains each model needed by the view. "Each model needed by the view" is usually different from your entity model in that it is flattened and streamlined for display, often called a ViewModel.
Option 1 (the Controller retrives data from the Model and passes it to the View) is quite similar to option 2, but I contend option 2 is preferable because it places less logic in the controller. In MVC, as much logic as possible should be in the model, leaving your controllers and views as simple as possible.
I tend to agree with the second one. MVC on the web can't really be implemented as it can in more stateful applications. Most web MVC implementations have you put your logic in your controllers and use the model for raw data access. I think the more correct way is to put your logic in your model. There is almost an implied 4th layer in that raw data access is done within the model, however the model is also responsible for giving that data meaning and updating the view.
The wikipedia article explains it pretty good.

Categories