php model view controller edition 001 001

39
PHP MODEL VIEW CONTROLLER DINNER TIME HAND NOTE RZ RASEL

Upload: rz-rasel

Post on 07-Apr-2016

226 views

Category:

Documents


9 download

DESCRIPTION

Php model view controller 1st edition

TRANSCRIPT

Page 1: Php model view controller edition 001 001

PHPModel View Controller

dinner tiMe Hand note

rz rasel

Page 2: Php model view controller edition 001 001

Dinner Time Hand Note®PHP Model View Controller

Rz Rasel

Model View Controller (PHP)

Rz Rasel

Page 3: Php model view controller edition 001 001

Dinner Time Hand Note®PHP Model View ControllerDESIGN AND DEVELOPMENT

1st Edition

Rz Rasel

Model View Controller (PHP)

Rz Rasel

Page 4: Php model view controller edition 001 001

Copyright © by Rz Rasel

All rights reserved. No part of this book may be reproduced, distributed, or transmitted in any form or by any means, including photocopying, recording, or other electronic or mechani-cal methods, without the prior written permission of the writer, except in the case of brief quotations embodied in critical reviews and certain other noncommercial uses permitted by copyright law. For permission requests, write to the writer, addressed “Attention: Permissions Coordinator,” at the address below.

[email protected]

1st Edition: August 2014

Cover Illustration Copyright © by Rz Rasel ([email protected])Cover design by Rz Rasel.Book design by Rz RaselEditing by Rz RaselChapter opening illustrations © Rz Rasel

Model View Controller (PHP)

Rz Rasel

Page 5: Php model view controller edition 001 001

AuthorRz Rasel

OthersCallum Hopkins

Kasia Mikoluk

Tom Butler

Pablo Pastor

Rz Rasel (Rashed - Uz - Zaman) is a Software Engineer. Back-end and Front-end developer web experience. Also working in PHP, Android, Database like Sql, MySql, Sqlite. Web developer, Web designer, and blogger. Contact e-mail:- [email protected].

Callum Hopkins is a designer and front-end developer web expe-rience and a Bachelors degree in Design for Digital Media. With knowledge in both design and development, he is able to influ-ence both sides of the web building process.

Kasia Mikoluk is a web developer.

Tom Butler work as a Web Developer (Specialising mainly in PHP) for a web design agency. Also a part time lecturer. Tom Butler have an interest in programming since messing around with the code for various computer games since he was about twelve. He consider it an art more than a science and love to explore the cre-ative side more than the functional side of the subject.

Pablo Pastor is a web developer.

CREDITSI would like to thanks all of them.

I would like to thanks all of them.

Model View Controller (PHP)

Rz Rasel

Page 6: Php model view controller edition 001 001

Rz Rasel (Rashed - Uz - Zaman) Software Engineer. Software developer, Software designer, System designer, Database designer, Web developer, Web designer, and blogger born in Ban-gladesh, and now living in Bangladesh.

Rz Rasel unearthed the World Wide Web and started creating web sites many years. Working in software frim in bangladesh as android developer, web developer with system analysis and design, database design. Write blogs in google blogger, WordPress (https://arzrasel.word-press.com). A few years later, Rz Rasel created his first blog (https://arzrasel.wordpress.com).

In his spare time, he enjoys to write story, poem. You can visit his home page at https://arz-rasel.wordpress.com or e-mail him at [email protected].

Rz Rasel

ABOuT AuTHORModel View Controller (PHP)

Rz Rasel

Page 7: Php model view controller edition 001 001

When I am trying to learn about “Model View Controller (MVC)” I don’t get any proper or com-plete book for MVC. I get a lot of book about “Model View Controller (MVC)”, but that are not for pure “Model View Controller (MVC)”. That books are mixed with existing MVC framework. So it’s hard to me for properly learn about “Model View Controller (MVC)” and how “Model View Controller (MVC)” works and designed. But at last I can learn “Model View Controller (MVC)”. Personally I am trying to make a “hand note” whatever I learn about MVC. And now I put all together my “hand note” I am trying to help all of them who want/interested to learn about MVC.

Rz Rasel

AuTHOR’S NOTEModel View Controller (PHP)

Rz Rasel

Page 8: Php model view controller edition 001 001

Get in touch with writer

WordPress Blog:- https://arzrasel.wordpress.com Facebook:- https://www.facebook.com/rzprogrammingFacebook:- https://www.facebook.com/groups/merzrasel/Facebook:- https://www.facebook.com/groups/rzprogrammer/E-mail:- [email protected]

Rz Rasel

GET IN TOuCHModel View Controller (PHP)

Rz Rasel

Page 9: Php model view controller edition 001 001

3 MVC ARCHITECTuRE

The Model

The View

The Controller

[email protected] FREE TO ASK QuESTION YOu MAY HAVE

CONTENTSModel View Controller (PHP)

Rz Rasel

Page 10: Php model view controller edition 001 001

3 MVC ARCHITECTuRE

The Model

The View

The Controller

[email protected] FREE TO ASK QuESTION YOu MAY HAVE

CONTENTSModel View Controller (PHP)

Rz RaselChapter - 01Page - 10

Page 11: Php model view controller edition 001 001

MVC Basic Architecture

Model View Controller or MVC as it is popularly called, is a software design pattern for de-veloping web applications. A Model View Controller pattern is made up of the following three parts:

• Model - The lowest level of the pattern which is responsible for maintaining data.• View - This is responsible for displaying all or a portion of the data to the user.• Controller - Software Code that controls the interactions between the Model and View.

MVC is popular as it isolates the application logic from the user interface layer and supports separation of concerns. Here the Controller receives all requests for the application and then works with the Model to prepare any data needed by the View. The View then uses the data prepared by the to generate a final presentable response. The MVC abstraction can be graphi-cally represented as follows.

Model

View

Controller

user

The model

The model is responsible for managing the data of the application. It responds to the request from the view and it also responds to instructions from the controller to update itself.

The view

A presentation of data in a particular format, triggered by a controller’s decision to present the

Model View Controller (PHP)

Rz RaselChapter - 01Page - 11

Page 12: Php model view controller edition 001 001

data. They are script based templating systems like JSP, ASP, PHP and very easy to integrate with AJAX technology.

The controller

The controller is responsible for responding to user input and perform interactions on the data model objects. The controller receives the input, it validates the input and then performs the business operation that modifies the state of the data model.

[email protected] YOu’VE GOT SuGGESTIONS FOR IMPROVEMENTS I’D LOVE TO SEE. DON’T HESI-

TATE.IF IT’S HELP YOu PLEASE LEAVE A COMMENT AND LET ME KNOW. I’D LOVE TO

HEAR.FEEL FREE TO SEND MORE FEEDBACK OR QuESTION YOu MAY HAVE.

������������z������������

Model View Controller (PHP)

Rz RaselChapter - 01Page - 12

Page 13: Php model view controller edition 001 001

3 uNDERSTANDING MODEL VIEW CONTROLLER

Understanding the Model View Controller

A Brief History of Model View Controller

What Exactly is a Model View Controller

Model

View

Controller

MVC in PHP

[email protected] FREE TO ASK QuESTION YOu MAY HAVE

CONTENTSModel View Controller (PHP)

Rz RaselChapter - 02Page - 13

Page 14: Php model view controller edition 001 001

understanding the Model View Controller (MVC)

As a computer science student, one of the first things you’ll learn is the ‘model-view-control-ler’, or MVC. MVC is a widely used software architecture pattern that informs the design of some of your favorite software applications. Now we’ll take a look at the MVC pattern in some more detail, especially how it is used in PHP.

If you’d rather just dive in and start creating your own apps, consider this course on PHP.

A Brief History of Model View Controller (MVC)

Let’s go all the way back to the 70s. Man has been to the moon, the civil rights movement has been a huge success, and the counterculture revolution is in full swing. More importantly for us, computer science has now established itself as a legitimate field, not just the eccentric hobby of people with huge glasses and bigger beards. Some of the brightest minds in engi-neering and mathematics are collaborating in research labs at Stanford, Berkeley and the dozens of private companies like Xerox and HP in what would later become Silicon Valley.

It’s against this backdrop that a bunch of very talented programmers have gathered at the Learning Research Group (LRG) of Xerox PARC in Palo Alto, California (the current home of Apple). These programmers are Alan Kay, Dan Ingalls, Adele Goldberg, Ted Kaehler, and Scott Wallace, among others. Together, they help create a programming language they call ‘Small-talk’. It’s already been a few years since the development of the C language at Bell Labs; there are already some software design standards in place. However, the invention of the Smalltalk programming language would affect virtually all these standards, and set the tone for the fu-ture of programming.

It was from this language that the Model-View-Controller pattern first emerged. Ted Kaehler is usually given credit for its development in 1978 in a paper titled ‘A note on DynaBook require-ments’, though his first name for it was ‘Thing-Model-View-Set’. The aim of this MVC pattern was to bring the user ‘closer’ to the digital model that existed inside the computer program. In Kaehler’s own words, the “user was czar”, and the MVC helped mediate the way the user could interact with a software program.

If that sounds too abstract to you, don’t worry – you’ll have a firm understanding of MVC by the time we’re done.

What you should know for now is that MVC described the way a user could interact with a com-puter program. This would later go on to inform Graphical User Interfaces (GUIs), and thus, by proxy, pretty much all of computer science. If it wasn’t for Kaehler and his MVC pattern, you might still be typing commands into a terminal right now.

So What Exactly is a Model View Controller?

A Model-View-Controller is a pattern of software architecture. It controls how different applica-tions interact with a user.

This web page is a perfect example of the MVC structure. Here, the HTML structure of this web page is the model, the CSS stylesheets that control its appearance are the ‘View’, and the browser that you use to interact with the web page is the ‘controller’.

Model: The model is a representation of knowledge. That is, the model contains the actual data that has to be shown to the user. All data is held in a structured format. For example, the HTML on this web page holds the actual text that you see inside structured HTML <tags>.

View: The view is a visual representation of the model. The view informs the way data struc-

Model View Controller (PHP)

Rz RaselChapter - 02Page - 14

Page 15: Php model view controller edition 001 001

tured in the model will be made visible to the user. For example, the HTML may hold the text, but the colors, font size and font style information is actually held by independent CSS stylesheets – i.e. the view.

Controller: A controller is the environment that bridges the divide between the user and the system. This is the device that lets the user interact with the system. In the above examples, the browser is the controller that helps you interact with the web page.

One way of representing this is as follows:

uSER MODEL

CONTROLLER

VIEW

Here’s a crude analogy: the muscles, bones and organs in your body are the ‘model’ that holds everything vital. The skin, hair, etc. are the ‘view’ that controls the outward representation of the muscles and bones (the model). Your senses are the ‘controller’ that helps the ‘model’ interact with the world.

Want to make web applications? Learn dynamic web programming with PHP in this course.

MVC in PHP

As a programmer, you’ll most likely to encounter MVC in a Ruby on Rails or Django project. However, it is also used in some PHP web frameworks, though the implementation isn’t nearly always uniform or in strict accordance with the theoretical foundation of MVC as laid down by Ted Kaehler.

CakePHP, which is one of the most popular PHP frameworks, uses an interpretation of the Ruby on Rails MVC pattern. If you download a copy of the framework, you’ll see the following directory structure in/app/:

Model View Controller (PHP)

Rz RaselChapter - 02Page - 15

Page 16: Php model view controller edition 001 001

..ConfigConsoleControllerLibLocaleModelPluginTestTmpVendorViewWebroot.htaccessindex.php

Here, the model, view and controller are included in separate folders. This is what/view/ contains:

..ElementsEmailsErrorsHelperLayoutsPagesScaffolds

/Model/:

..

Behavior

DatasourceAppModel.php

And /Controller/:

Model View Controller (PHP)

Rz RaselChapter - 02Page - 16

Page 17: Php model view controller edition 001 001

..

Component

AppController.phpPagesController.php

Here’s the MVC in CodeIgniter, another very popular PHP framework:

..

cache

config

controllers

core

errors

helpers

hooks

language

libraries

logs

modesl

third_party

views.htaccessindex.php

However, CakePHP and CodeIgniter’s approach isn’t pure MVC, for here, the view and the model can interact with each other. In a pure MVC, all interactions must be handled by the controller alone. Most frameworks – CakePHP included – tend to treat the View as little more than a CSS template that controls the way the web page/app looks. The MVC approach is typi-cally muddled in most PHP frameworks, both because of a poor translation of the Ruby on Rails and other similar frameworks.

MVC is an abstract, theoretical topic that can be difficult to grasp for beginners. You can learn more about it in this course on PHP programming from scratch.

[email protected] YOu’VE GOT SuGGESTIONS FOR IMPROVEMENTS I’D LOVE TO SEE. DON’T HESI-

TATE.IF IT’S HELP YOu PLEASE LEAVE A COMMENT AND LET ME KNOW. I’D LOVE TO

HEAR.FEEL FREE TO SEND MORE FEEDBACK OR QuESTION YOu MAY HAVE.

������������z������������

Model View Controller (PHP)

Rz RaselChapter - 02Page - 17

Page 18: Php model view controller edition 001 001

3 THE VIEW GETS ITS OWN DATA FROM THE MODEL

Abstract

MVC - Model View Confusion

The view is more than a template

Example 1 PHP Code

Example 2 PHP Code

Binding logic is problematic

PHP Code

When the view really needs the model

PHP Code

PHP Code

Better reusability

PHP Code

PHP Code

PHP Code

PHP Code

PHP Code

PHP Code

PHP Code

Conclusion

[email protected] FREE TO ASK QuESTION YOu MAY HAVE

CONTENTSModel View Controller (PHP)

Rz RaselChapter - 03Page - 18

Page 19: Php model view controller edition 001 001

Abstract

MVC is a common subject in the PHP community at the moment. There are a large body of articles, tutorials and code examples on the subject. Most of which deviate from the traditional approach to MVC and subscribe to an approach closer to MVP. Very few of these follow the MVC standard of allowing the view access to the model. Yet this is what they ascribe to be. This article explains why the view should have access to the model and the problems which are created by taking the differing approach commonly used throughout the PHP community.

MVC - Model View Confusion

MVC is a very common architecture in PHP these days. Everyone seems to be writing their own MVC framework. It’s a great learning exercise. The problem however, is the information which is available to PHP developers. Much of it is poorly written, a great deal is fairly old fashioned and teaches bad practices. The majority of MVC related articles go off on tangents about such topics as the merits of DataMapper vs ActiveRecord, template systems, directory structures, how to do form processing and validation and other irrelevant implementation details. The big-gest problem, however, is that despite the inclusion of all this unrelated information they still almost all get the basics wrong.

In MVC the view should access the model directly. This something which I have to argue a lot and it’s one of the most overlooked facts about the architecture.

It is important to note that in order to correctly apply the MVC architecture, there must be no interaction between models and views: all the logic is handled by controllers.

This is wrong. It specifies this nowhere in MVC. In fact, it states the exact opposite. Lets take a step back and take a look at some explanations of MVC from outside the PHP world.

As a starting point, the wikipedia article on MVC states:

A view queries the model in order to generate an appropriate user interface (for example, the view lists the shopping cart’s contents). The view gets its own data from the model. The controller may (in some implementations) issue a general instruction to the view to render

itself. In others, the view is automatically notified by the model of changes in state (Observ-er) which require a screen update.

Of course wikipedia is not a credible source so here’s some more academic explanations:

The views know of the model and will interact with the model.

The view is more than a template

The catalyst for this error appears to be the idea that a “view is a template”. It contains the HTML, perhaps a few processing instructions for looping through arrays but they state that it gets passed its variables from the controller.

The result of this self-imposed restriction makes putting any logic at all in the MVC’s’ “view” seem wrong, harking back to the days of mixing HTML and PHP. Don’t get me wrong I’m not going to argue that mixing HTML and PHP is a good thing. Templates serve a valuable purpose. They just don’t constitute a view in MVC.

Of course, when the model is incorrect or even non-existent and the controller is doing the model’s job it presents yet another hurdle. When the controller is doing the job of a model

Model View Controller (PHP)

Rz RaselChapter - 03Page - 18 Rz RaselChapter - 03

Page - 19

Page 20: Php model view controller edition 001 001

anyway, as in most PHP “MVC” frameworks, there is no model for the view to access! This has to be done by the controller.

Because of these fundamental problems, the only solution is to make the controller act as a mediator. Generally by querying the model and passing the result to the view.

Example 1 PHP Code:

$user = $this->model->user->findById($id); $this->template->assign(‘firstname’, $user[‘firstName’]); $this->template->assign(‘surname’, $user[‘surname’]); $this->template->assign(‘address1’, $user[‘address1’]);

or pass a simple key-value array which has been retrieved from the model (which is just a data access layer) to the template:

Example 2 PHP Code:

$user = $this->model->user->findById($id); $this->template->assign(‘user’, $user);

While the latter is certainly an improvement, it merely makes the problem slightly less notice-able: binding logic.

This puts extra work into the controller: Binding variables to the template. Controllers are not designed to be reused. By putting this logic here the reusability has instantly been reduced. There are bigger issues than that though.

Binding logic is problematic

By including this binding logic, a large number of potential issues have been created in terms of reusability and maintainability. Views are intended to be reused. In the examples above I’m showing some basic user information. The template here may well (and, because the tem-plate is separated, can) be reused. This is a good thing and certainly something to strive for. However, when the binding logic is introduced, much of this reusability is lost.

The first problem, then, is repeated code. The binding logic needs to be written in each and every controller which uses the view. This will do nothing but slow down development.

There is a potential for inconsistent naming. For example, this is possible:

PHP Code:

$this->template->assign(‘lastname’, $user[‘surname’]));

This is something easily dismissed as “I wouldn’t do that” however, when working with a team, it’s easy for things like this to slip in unnoticed and cause bugs which are difficult to track down.

What if there are two users being represented in the view? Both of them have surnames and firstnames. The view now needs to reference “firstname1” and “firstname2” How can this be kept consistent across controllers and views? It can’t. This all causes confusion for anyone else looking at the code. Isn’t it better to prevent this in the first place?

Model View Controller (PHP)

Rz RaselChapter - 03Page - 20

Page 21: Php model view controller edition 001 001

In a similar vein, it’s possible for the controllers to be inconsistent. Because this logic even exists, it removes any contract between the view and the model. This means ‘address1’ in the view doesn’t really represent anything. It can be anything. There’s nothing to stop the control-ler sending the wrong data.

For example, in one job I worked on a site with a similar set up. The requirements changed along the lines of “can you remove the address from this page” rather than modify the view one of my colleagues decided it would be a good idea to change the controller to do $template->assign(‘address’, null); Of course when the view was reused elsewhere by another developer, he had to spend time working out why the address was showing on the new page and not on the old one. The controller now inadvertently contained display logic: it was telling the view not to show the address. Again, prevention here is better than cure.

Performance should be the final consideration. The binding logic creates more code. Although code cleanliness/reusability/maintainability shouldn’t be sacrificed for performance, in this case worse performance is a result of worse code.

When the view really needs the model

The above examples are trivial. As with most trivial examples, the bigger problems don’t be-come apparent until the scale and complexity are increased. A better example is pagination.

A pagination controller may look like this:

PHP Code:

$perPage = 10; $page = $_GET[‘page’]; $users = $this->model->user->find($perPage, $perPage * $page); $totalPages = $this->user->count() / $perPage; $this->view->assign(‘users’, $users); $this->view->assign(‘totalPages’, $totalPages); $this->view->assign(‘page’, $page);

Here is basic logic behind pagination in the controller. The big problem here is that none of this code is reusable. Even though it will be the same for any paginated data. The only thing that will change is the current page and number of records to show per page.

Just because the controller is calling a function on the model doesn’t mean the display and business logic have been moved out of the controller.

How else could this be done? A better solution would be to set the state in the model and have the view read it. This way the view is agnostic about the state of the model (which page it’s on) and all the pagination logic is contained (and reusable) within the view.

PHP Code:

$this->model->setPage($_GET[‘page’]);

This should be the entirity of the controller code.

This way, all the pagination logic: working out the total number of pages, working out the limit/offset (Details which are only relevant to how the data is going to be displayed when it’s paginated) can be moved to the view. The view will call $user->find() and $user->count() with the relevant parameters. The controller is doing less and the view is doing more. This

Model View Controller (PHP)

Rz RaselChapter - 03Page - 20 Rz RaselChapter - 03

Page - 21

Page 22: Php model view controller edition 001 001

inevitably leads to higher reusability.

It could be argued that the view should contain its own state: Which page it’s on. However, the reason that the model holds the state and not the view is that the model can be in use by multiple views. It may be useful for multiple views to use the same data. For example, having a second view which used the paginated data and created some aggregated statistics about the data displayed on the current page. This would need to be in sync with the first view and always use the same data set. By storing the state in the model rather than the view, the page can be changed and both views will reflect the changes. This reduces repeated code and adds flexibility while improving separation of concerns.

The View always has a contract with a model. Whether it’s a primitive array or a complex ob-ject, the view requires specific information. This is naturally unavoidable. By using the Model directly, this contract is immediately fulfilled. If primitives are passed to the view, it has no way of knowing whether this contract is fulfilled until it breaks. Even if the result is a set of objects, the view cannot know whether the set is correct (because it’s likely a primitive array containing objects) until it tries to use an object. By using the Model, the view can check this contract is fulfilled as the model is assigned to it, preferrably in its constructor.

Even ignoring this, and assuming your controller always passes a valid data set you still lose re-usability. The biggest issue with the “controller as a mediator” approach is that all the data fetching logic (the calls to the model) has to be done in every single controller using the view, causing repeated code and therefore reduced reusability. In the pagination example, all the calculations need to be repeated in each controller that uses the view. As an application developer, each time you want to use pagination, would you rather pass a single variable to the model which set’s the page and does everything for you or fetch the records, work out the total number of pages then pass the result to the view?

And pagination is a trivial example. In the real world, that controller logic is liable to change. If it’s repeated, it needs to be updated in every controller. By creating the reusability and separation of concerns suggested by MVC the code doesn’t need repeated and changes to the model will automatically be reflected in any view without changes to the code. This is a result of the reduction of binding logic and therefore increasing reusability.

The idea here (and the one suggested by MVC in general) is putting all the business logic in the model and all the display logic in the view. All the controller should be doing is getting these talking. The less the controller is doing the better. Less controller code means more reusable code.

Better reusability

With all this theorising, it would certainly be worthwhile to include a basic real world example of why views are more than templates. I believe templates are worthwhile but they do not constitute a “View”. Much in the same way the model layer is more than data access, the view is more than a template.

To demonstrate, here’s a simple scenario: Show a list of users which can be filtered by search-ing for their name.

Some example controller code. This will now be as minimal as possible.

PHP Code:

class UserListController

Model View Controller (PHP)

Rz RaselChapter - 03Page - 22

Page 23: Php model view controller edition 001 001

{ private $model; public function __construct(UserListModel $model) { $this->model = $model; } public function search($criteria) { $this->model->filterByName($critiera); } }

Clean, empty controller code. Absent of both the view’s display logic and the model’s domain logic. One thing to note here is that the controller does not require access to its view, only the model. This is because in MVC, the only reason a controller needs access to the view is for the observer pattern: to inform the view to refresh from the model. In PHP this is a non-issue because the view must have been refreshed anyway.

A simplistic model would look something like this:

PHP Code:

class UserListModel { private $searchName; private $db; public function __construct(Db $db) { $this->db = $db; } public function filterByName($name) { $this->searchName = $name; } public function getUsers() { //Find the selected users. return $this->db->query(‘SELECT * FROM users WHERE name like :name’, array(‘:name’, $this->searchName); } }

The important part to note here is that the model has a state, in this example, the name which has been searched for. In most pseudo-MVC frameworks the model has no state, the state is retained in the controller. This seemingly trivial fact is actually the core of the problem: the view needs to know about this state. This is why the erroneous “controller as a mediator” ar-chitecture has developed.

The view then fetches the data from its model. In this example the usage of a basic template system has been assumed:

PHP Code:

class UserListView

Model View Controller (PHP)

Rz RaselChapter - 03Page - 22 Rz RaselChapter - 03

Page - 23

Page 24: Php model view controller edition 001 001

{ private $model; private $template; public function __construct(UserListModel $model, Template $template) { $this->model = $model; $this->template = $template; } public function output() { $this->template->assign(‘users’, $this->model->getUsers()); return $template->output(); } }

The view has become reusable anywhere a list of users is required. Substitute the model, which can supply any dataset from any source, it doesn’t have to be a database. As long as the model supplies a list of users the controller is agnostic about where they come from or any knowledge about what them at all. This promotes robust code by making each component (the model, view and controller) entirely interchangeable. This is possible because it enforces the strict separation of concerns that MVC strives for. The controller has no knowledge of how the view works. From an OOP perspective this is ideal as there is complete encapsulation. The view can be substituted and it will never break the controller, the controller can be substituted and it will never break the view.

However, the goal here is reusability. Is the logic behind a listing a set of users any different to listing a set of blogs, albums, products, etc? No, so why can’t that logic be reused? A few simple amends and it can:

Firstly, some interfaces are defined in order to enforce an API:

PHP Code:

interface Listable { public function getData(); } interface Searchable { public function setCriteria($criteria); }

It’s now possible to create several models which use these interfaces:

PHP Code:

class UserModel implements Listable, Searchable { private $searchName; private $db; public function __construct(Db $db) { $this->db = $db; }

Model View Controller (PHP)

Rz RaselChapter - 03Page - 24

Page 25: Php model view controller edition 001 001

public function setCriteria($criteria) { $this->searchName = $criteria; } public function getData() { //Find the selected users. return $this->db->query(‘SELECT * FROM users WHERE name like :name’, array(‘:name’, $this->searchName); } } class BlogModel implements Listable, Searchable { private $searchTitle; private $db; public function __construct(Db $db) { $this->db = $db; } public function setCriteria($criteria) { $this->searchTitle = $title; } public function getData() { //Find the selected blogs. return $this->db->query(‘SELECT * FROM blogs WHERE title like :title’, array(‘:title’, $this->searchTitle); } }

The controller code looks like this:

PHP Code:

class SearchController { private $model; public function __construct(Searchable $model) { $this->model = $model; } public function search($criteria) { $this->model->setCritera($criteria); } }

Notice that it’s not tied to any specific model. Because of the very strict separation of concerns which is achieved by the view getting its own data from the model rather than being fed it by the controller, the controller code is reusable. And so is the view:

PHP Code:

Model View Controller (PHP)

Rz RaselChapter - 03Page - 24 Rz RaselChapter - 03

Page - 25

Page 26: Php model view controller edition 001 001

class ListView { private $model; private $template; public function __construct(Listable $model, Template $template) { $this->model = $model; $this->template = $template; } public function output() { $this->template->assign(‘data’, $this->model->getData()); return $template->output(); } }

Again, it’s not tied to a specific model. The view does not care where its data comes from or what the data is. But there’s more. Any of the three components can be substititued and re-used. The controller can be changed where needed. The view can be substituted for one which doesn’t use a template engine while reusing the controller and model. Another controller can be added to the system which uses $_POST and it can use the exact same model and view.

By enforcing the separation of concerns that MVC dictates, the real power of it shines through.

Conclusion

My main goal here is to show that just because an idea is widespread does not mean it is correct or best practice. Not everything you read is entirely accurate. Without valid reason-ing, a programming practice, regardless of its popularity is not always a good practice. Take singletons as a perfect example. Something many articles seem to miss. They tell you how but not why.

[email protected]

IF YOu’VE GOT SuGGESTIONS FOR IMPROVEMENTS I’D LOVE TO SEE. DON’T HESI-TATE.

IF IT’S HELP YOu PLEASE LEAVE A COMMENT AND LET ME KNOW. I’D LOVE TO HEAR.

FEEL FREE TO SEND MORE FEEDBACK OR QuESTION YOu MAY HAVE.

������������z������������

Model View Controller (PHP)

Rz RaselChapter - 03Page - 26

Page 27: Php model view controller edition 001 001

3 MVC MODELS ARE NOT DOMAIN MODELS

Flexibility vs Reusability

PHP Code

PHP Code

PHP Code

PHP Code

Terminology: ViewModels View Helpers, Models

What is a view helper?

An Implementation

The Template

The View

The ViewModel

PHP Code

PHP Code

PHP Code

PHP Code

PHP Code

PHP Code

PHP Code

Conclusion

A small disclaimer

CONTENTSModel View Controller (PHP)

Rz RaselChapter - 04Page - 27

Page 28: Php model view controller edition 001 001

Flexibility vs Reusability

To completely contradict part, while correct, it’s not the solution either. It is certainly an im-provement over fat controllers. However, was it much of an improvement? Isn’t reusability reduced by giving the view access to the model?

In any software design, there is always a trade off between flexibility and reusability. On one hand a very flexible system could be created where the client code has to specify pretty much everything. For example, in terms of views, passing a model object to the template and have the template do everything: query the model, process the data and generate the HTML. This is incredibly flexible: there are no limitations on what it can do. However, it’s not reusable at all. The template is tightly bound to the individual model and the logic is contained within it. To make an even slightly different version everything would need to be re-coded.

On the other hand, a lot of assumptions could be made about the nature of the model in the system the view, with minimal to no configuration could take any model which meets these assumptions. Of course things break when requirements change or it needs to do something even slightly different. It encourages a ‘copy, paste and modify slightly’ mentality, which is of course, not a good idea.

Finding the balance is the key. It will always differ based on the requirements of the software, how large the project is, whether it’s going to change often and whether it’s likely to grow beyond its initial scope.

The last point here is a hard one to judge. Would it be worthwhile to deploy a template engine or full MVC stack for a 5 page brochure site? how about 10 page? What if that 5 page site grew into a 30 page site within a year then the client wanted latest news added to each page. If the system was built on a template engine or CMS to begin with it would be easier.

But is this the right answer? Should developers deploy a full MVC stack just to write to a log file? Trying to be a soothsayer and second guess what clients (who are notoriously fickle be-ings) will ask for in a year isn’t the solution. However, spending a little extra time at the start of a project ensuring further developments are as simple as possible will undoubtedly make things easier in the long run.

It argues that in MVC the view should have direct access to the model. It contains some basic code examples to demonstrate the benefits. The solution is for demonstration only. As such it is neither complete, nor perfect. However, the general idea of the view calling functions on the model directly presents some new problems.

Problems created by the view accessing the model

The biggest problem is also one of its biggest strengths: it creates a firm contract between the model and the view. This reduces reusability of the view because the model now needs to have a very specific interface.

Reusable ListView class:

PHP Code:

class ListView { private $model; private $template;

Model View Controller (PHP)

Rz RaselChapter - 04Page - 28

Page 29: Php model view controller edition 001 001

public function __construct(Searchable $model, Template $template) { $this->model = $model; $this->template = $template; } public function output() { $this->template->assign(‘data’, $this->model->getData()); return $template->output(); } }

Firstly, the binding logic mentioned has simply been moved into the view. Secondly, and more importantly, the view requires the model to implement the Searchable interface . The result of this is that the view is only usable by certain models. But what about other views which may need other data sets from the same model?. What if a model doesn’t implement Searchable. The issue is one of Separation of Concerns. Should the model know how it is going to be used? No. The model should be dictating how it is used and the system should accommodate it.

Should arbitrary models model be modified to implement the Searchable interface? Ideally the model should be reusable without modification. Otherwise each model which can used be the view needs to be modified.

The problem arises because each view requires models to implement specific interfaces. In the real world, a model is going to be used by any number of views. The model should not be mod-ified in order to allow each potential view to use it. It causes clutter in the model and causes harm by meaning the model cannot easily be reused by the same view in two different ways.

The cause of confusion is the term “Model”. When people refer to Models they generally mean “Domain models”. That is, the model which encompasses the problem domain, dealing with real-world concepts. Blogs, users, products, etc. In MVC, while the Model does contain these things, the domain model is not the Model referred to in MVC.

Is the following code the solution?

PHP Code:

class ListView { private $model; private $template; public $filter; public function __construct(Searchable $model, Template $template) { $this->model = $model; $this->template = $template; } public function output() { $this->template->assign(‘data’, $this->model->getData($filter)); return $template->output(); } } //controller code

Model View Controller (PHP)

Rz RaselChapter - 04Page - 29

Page 30: Php model view controller edition 001 001

$this->view->filter = ‘firstname = “’ . $name . “’;

Here, the state has been moved into the view. The view contains the search criteria rather than the model. Is this the answer?

No, For a start, Display logic has been reintroduced into the controller. More importantly though, now any model which uses the view requires a very specific “getData” implementa-tion. This severely reduces reusability to only models which follow this specification.

Extending this idea into more complex views means more specific calls to a model, which means its less reusable views. To use a totally different model would be programmatically try-ing to put a square plug in a round hole.

Consider this: developer “A” develops a model and a view to work together:

PHP Code:

class ModelA { public function getData($order, $limit, $filter) { //... } } class ViewA { //... public function output() { $result = $this->model->getData($this->order, $this->limit, $this->filter); //... } }

Meanwhile, developer “B” develops a model and a view which work together:

PHP Code:

class ModelB { public function getData($firstname) { //... } } class ViewB { //... public function output() { $result = $this->model->getData(‘foo’); //... } }

Model View Controller (PHP)

Rz RaselChapter - 04Page - 30

Page 31: Php model view controller edition 001 001

Now there’s a situation where ModelB cannot be used with ViewA and ModelA cannot be used with ViewB even though the logic in each view may be relevant to the display of both models.

One solution is to add the relevant methods to the models but this is both messy and dan-gerous. This potentially introduces unrelated concepts into models (e.g. ModelA may not be anything to do with users).

Alternatively, the views could be modified, but again, there’s no clean way to do it. Either they need to extended and have the entire output() method re-written, or have some hacky logic in the view deciding which method to call in the model.

The ideal scenario is that both the model and view can be reused without modification. This allows for ultimate reusability and a very large amount of flexibility

The answer? Abstract the problem away.

Terminology: ViewModels View Helpers, Models

Padraic Brady wrote about this in his fantastic article “The M in MVC: Why Models are Mis-understood and Unappreciated”. Although he accurately points out the misunderstanding of Models, the problem is peoples preconceptions of model’s. He re-enforces this by discussing domain models in terms of MVC Models. They are not the same thing. The MVC Model does encapsulate domain models, but for the purpose of MVC, although you can write a MVC Model which does the job of a domain model, it’s impossible to use a domain model as an MVC Model.

One idea presented by Brady is to create a “View Helper” which contains all the interaction between the model and the view. This is actually what MVC refers to as “The model” and not a separate component. However, because the term “Model” has evolved to have a specific meaning I can see why he needed to coin a fresh term for the MVCs model.

What is a view helper?

Encapsulating business logic in a helper instead of a view makes our application more modular and facilitates component reuse. Multiple clients, such as controllers and views, may leverage the same helper to retrieve and adapt similar model state for presentation in multiple ways.

An Implementation

The main goal is that views can be as generic (and therefore reusable) as possible, while the ViewModel defines only how a model interacts with a specific view. This fixes the problem of either coding a view around a model, or coding a model to fit a view. It is considered part of the view layer, but the ViewModel can access any domain model.

The Template.

This contains the HTML. This has a contract with domain models (user objects, order objects, etc). A basic template system is used in code examples on this page for the purpsoe of dem-onstration. How this works is not relevant and is far beyond the scope of this article. Often the template itself will not be reused: It is tied directly to the domain model. For example, it knows what fields a “User” object has. It has direct access to its ViewModel, this allows it to read what it needs, eliminating the need for binding logic in the view.

The View

Model View Controller (PHP)

Rz RaselChapter - 04Page - 31

Page 32: Php model view controller edition 001 001

This contains all the display logic for interacting with the template and is the only place the template is interacted with directly. Most of the time it will simply assign the helper to the template. When a View is defined it should also define an interface for the helper which it is going to use. It does not interact with models directly. It uses a ViewModel to get any data it needs from the model.

The ViewModel

This implements the specific interface defined alongside the view. E.g. FormView will require a ViewModel which implements the interface FormViewModel. The ViewModel’s job is to link the model layer to the view layer and store the state of the application. For instance it will store things like sort options selected by the user and the ID of the record being edited/viewed.

This means that any part of the view layer can be substituted (and thus, the others reused). With the same model and view, the logic in the helper could be changed. The template could be changed.

PHP Code:

class ListView { private $model; private $template; public function __construct(Searchable $model, Template $template) { $this->model = $model; $this->template = $template; } public function output() { $this->template->assign(‘data’, $this->model->getData()); return $template->output(); } }

It requires a ViewModel as the first argument. In this case, the ViewModel must implement the Searchable interface as before. The also controller remains identical to what it was previously:

PHP Code:

class SearchController { private $model; public function __construct(Searchable $model) { $this->model = $model; } public function search($criteria) { $this->model->setCritera($criteria); } }

Model View Controller (PHP)

Rz RaselChapter - 04Page - 32

Page 33: Php model view controller edition 001 001

The important changes happen at the model layer. The old UserModel looked like this:

PHP Code:

class UserModel implements Listable, Searchable { private $searchName; private $db; public function __construct(Db $db) { $this->db = $db; } public function setCriteria($criteria) { $this->searchName = $name; } public function getData() { //Find the selected users. return $this->db->query(‘SELECT * FROM users WHERE name like :name’, array(‘:name’, $this->searchName); } }

The problem with this is that the domain model and ViewModel have been merged into one. This violates the Single Responsibility Principle and causes domain models to contain meth-ods which exist for the sole purpose of specific views accessing data. However this can be resolved:

PHP Code:

class UserListViewModel implements Listable, Searchable { private $searchName; private $model; public function __construct(UserModel $model) { $this->model = $model; } public function setCriteria($criteria) { $this->searchName = $name; } public function getData() { //Find the selected users. return $this->model->findByName($this->searchName); } } class UserModel { private $db; public function __construct(Db $db) {

Model View Controller (PHP)

Rz RaselChapter - 04Page - 33

Page 34: Php model view controller edition 001 001

$this->db = $db; } public function findByName($name) { //Find the selected users. return $this->db->query(‘SELECT * FROM users WHERE name like :name’, array(‘:name’, $name); } }

Here is a very clear distinction between a domain model and a ViewModel. This ViewModel will always be incredibly minimalist. It will never contain complex logic, database access, it’s a simple wrapper to enable view to access it’s data. The domain model now has a generic “findByName” method which can be used by any “ViewModel”. The application state (what has been searched for) remains in the ViewModel while the domain state (the data about users) is encapsulated in the domain model.

The view layer is now made up of 3 parts. For people used to “templates as views” this will likely seem daunting. However, take a look at the controller. It’s entirely minimalist and re-usable which is far superior to the mess of fat controllers which are required by the major frameworks. Minimal controllers are good controllers.

To test the reusability, the view could be reused with minimal configuration by another model with a totally different interface:

PHP Code:

class ProductListViewModel implements Listable, Searchable { private $searchCode; private $model; public function __construct(ProductModel $model) { $this->model = $model; } public function setCriteria($criteria) { $this->searchName = $name; } public function getData() { //Find the selected users. return $this->model->findByCodeNumber($this->searchCode); } } class ProductModel { private $db; public function __construct(Db $db) { $this->db = $db; } public function findByCodeNumber($code) {

Model View Controller (PHP)

Rz RaselChapter - 04Page - 34

Page 35: Php model view controller edition 001 001

//Find the selected users. return $this->db->query(‘SELECT * FROM products WHERE code like :code’, array(‘:name’, $code); } }

Neat and minimalist. All that’s changed is the ViewModel. The view and controller can be re-used. In this case, the template would still need to change too, of course.

PHP Code:

class BlogListViewModel implements Listable { private $model; public function __construct(BlogModel $model) { $this->model = $model; } public function getData() { return $this->model->findAll(); } }

In this case, a controller would not even be required! The view would get it’s data from the ViewModel and it wouldn’t even matter that the controller didn’t exist.

With minimal code, a lot different fairly substantial variations are possible due to having both high flexibility and high reusability.

Here’s one more example using something slightly more complex. Like part 1 pagination will be used again, it’s simple and commonplace enough that everyone understands it, yet it’s not-trivial enough to provide a worthwhile demonstration.

PHP Code:

interface Pageable { //Get the records using limit and offset public function find($limit, $offset); //The number of records which will be shown on each page public function getRecordsPerPage(); //The page currently being shown public function getCurrentPage(); //The total number of records being paged through. //Used to calculate the total number of pages. public function getTotalResults(); } class PaginationView { private $model; private $template; public function __construct(Pageable $model, Template $template) {

Model View Controller (PHP)

Rz RaselChapter - 04Page - 35

Page 36: Php model view controller edition 001 001

$this->model = $model; $this->template = $template; } public function output() { $perPage = $this->model->getRecordsPerPage(); $pageNo = $this->model->getCurrentPage(); if(empty($pageNo) || !is_numeric($pageNo) || $pageNo < 1) $pageNo = 1; $result = $this->viewModel->find($perPage, ($pageNo-1)*$perPage); $totalRecords = $this->model->getTotalResults(); $totalPages = ceil($totalRecords/$perPage); for($i = 1; $i <= $totalPages; $i++) $this->template->appendSection(‘page’, array(‘num’ => $i, ‘class’ => $i == $pageNo ? $this->currentClass : ‘’)); foreach($result as $record) $this->template->appendSection(‘record’, $record); return $this->template->output(); } }

The PaginationView uses any ViewModel which implements Pageable. The way the template system works is irrelevant. It is included for demonstration purposes only. The ViewModel is then defined in order to supply the view with the data it needs:

PHP Code:

class PagedUserListViewModel implements Pageable, Searchable { private $searchName; private $model; private $page = 1; public function __construct(UserModel $model) { $this->model = $model; } public function setCriteria($criteria) { $this->searchName = $name; } public function find($limit, $offset) { return $this->user->findByName($this->searchName, $limit, $offset); } public function getRecordsPerPage() { //Let’s show 20 users per page. return 20; } public function getCurrentPage() { return $this->page; } public function getTotalResults() {

Model View Controller (PHP)

Rz RaselChapter - 04Page - 36

Page 37: Php model view controller edition 001 001

//Simple example, in reality the model would have a count method for performance reasons return count($this->model->findByName($this->searchName)); } public function setPage($page) { $this->page = $page; } }

Of course the same could be done with a different model: Blogs, products, etc. The controller is simple, too:

PHP Code:

class PagedUserListController { private $viewModel; public function __construct(PagedUserListViewModel $viewModel) { $this->viewModel = $viewModel; } public function search($criteria) { $this->viewModel->setCritera($criteria); } public function setPage($page) { if(is_numeric($page)) { $this->viewModel->setPage($page); } } }

By separating everything out, any piece of the view layer can be substituted. The way the view interacts with the model is not affected by either changes to the view or changes to the model. If there are two different user lists with different requirements (e.g. different search criteria) only the View Helper needs to be changed. The view and the template would remain the same. The view is reusable for any model by supplying it with a different ViewModel:

Conclusion

This is, of course, noting but a single implementation of the idea, however, it demonstrates the benefits of separating the view elements well and should provide a solid base for anyone wishing to develop the idea further. This is of course, all open to criticism. There is plenty of room for improvement and some of the minor implementation details included here may not be done in the best way (Should the variables being replaced in the template be put in the helper instead of the view). However, using practical examples, I believe I’ve successfully argued the case for splitting views into 3 parts. It is more code to set up, but the power and reusability achieved by doing this makes it more than worthwhile.

A small disclaimer

Model View Controller (PHP)

Rz RaselChapter - 04Page - 37

Page 38: Php model view controller edition 001 001

All the code presented in this article is for information only, It uses things such as “$_POST”, the “new” keyword instead of factories/dependency injection, insecure code which is subject to SQL injection and things which are considered bad practice. All this is for the sake of sim-plicity: The article is teaching the idea of views/view helpers not other best practices. Because of this, please don’t take code which is outside the scope of the article and use it without un-derstanding the implications behind it.

[email protected]

IF YOu’VE GOT SuGGESTIONS FOR IMPROVEMENTS I’D LOVE TO SEE. DON’T HESI-TATE.

IF IT’S HELP YOu PLEASE LEAVE A COMMENT AND LET ME KNOW. I’D LOVE TO HEAR.

FEEL FREE TO SEND MORE FEEDBACK OR QuESTION YOu MAY HAVE.

������������z������������

Model View Controller (PHP)

Rz RaselChapter - 04Page - 38

Page 39: Php model view controller edition 001 001

Model View Controller (PHP)

Rz RaselChapter - 04Page - 39