Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

PHP & the MVC Pattern


Published on

Presentation done on June the 24th on the MVC pattern at the PHPBelgium event in Mons.
How to refactor a simple spaghetti application into a well structured, MVC-aware (and framework-free) application with nice URL just using regular PHP and Apache's configuration.
Vote and comment it on:

Published in: Technology
  • Thanks Stefan for your comment.

    Before I comment, note that those slides have been used as an introduction to MVC with an audience that might be new to PHP and/or programming.

    I fully agree with you on the fact that 'model' is not equal to 'data access'. But not that it is in 'no way' related. Quoting Wikipedia again:
    'MVC does not specifically mention the data access layer because it is understood to be underneath or encapsulated by the model. Models are not data access objects although in very simple apps, with little domain logic, there is no real distinction to be made.'

    In some very simple case you may simplify the domain logic of an application to an ActiveRecord pattern merging domain logic and data access.

    Separating business logic and data access is certainly a good practice I would recommend too, but as with any application design, there is no such thing as 'One Theory to Fit them All'. In some more complex case you might even want to have a three-tier architecture where the PHP application is only used as the presentation tier.
    Are you sure you want to  Yes  No
    Your message goes here

PHP & the MVC Pattern

  1. 1. PHPBelgium event 2009-06-24 PHP & the MVC Pattern Patrick Allaert PHPBelgium – Belgian PHP community
  2. 2. About Me Started developping using PHP 3 Ten years of FOSS evangelism Contribute to different FOSS: Tabellio (Open Source Collaboration for assemblies) Xoo°f (eXtensible Open Object Oriented Framework) KDESvn (Subversion frontend for KDE) PHP (ext/ldap) APM lead developer (Alternative PHP Monitor) Working @ AUSY PHPBelgium staff member Blog: Twitter: PHPBelgium – Belgian PHP community
  3. 3. Model-View-Controller (1) “… is an architectural pattern used in software engineering. Successful use of the pattern isolates business logic from user interface considerations, resulting in an application where it is easier to modify either the visual appearance of the application or the underlying business rules without affecting the other.” Wikipedia PHPBelgium – Belgian PHP community
  4. 4. Model-View-Controller (2) Model DB Requests Controller (X)HTML View XML PHPBelgium – Belgian PHP community
  5. 5. Design of some PHP applications PHPBelgium – Belgian PHP community
  6. 6. Managing this is sometimes... very difficult... PHPBelgium – Belgian PHP community
  7. 7. Demo application /index.php /team.php?id=<TeamID> PHPBelgium – Belgian PHP community
  8. 8. Spaghetti code <?php <table id="ranking"> $db = new mysqli("localhost", "foot", "footpw", "foot");   <tr> $result = $db->query(     <th>Name</th>Presentation     <th>Points</th> "SELECT name, won, lost, draw, coach,   </tr> Business Logic won * 3 + draw AS points <?php FROM team WHERE id = " . (int) $_GET['id']); Business Logic $result = $db->query("SELECT * FROM ranking"); while ($row = $result->fetch_assoc()) { $team = $result->fetch_assoc(); ?> ?>   <tr> <html>     <td class="name"> <head>       <a href="team.php?id=<?= $row['id'] ?>">   <title>Team - <?= $team['name'] ?></title>         <?= $row['name'] ?> </head>       </a> <body id="team">     </td> <h1>Team: <?= $team['name'] ?></h1>     <td class="points"> <table id="info"> <?= $row['points'] ?> Presentation   <tr><th>Won:</th>   <td><?= $team['won'] ?></td></tr> </td> Presentation   <tr><th>Lost:</th>  <td><?= $team['lost'] ?></td></tr>   </tr>   <tr><th>Draw:</th>  <td><?= $team['draw'] ?></td></tr> <?php   <tr><th>Points:</th><td><?= $team['points'] ? } ></td></tr> ?>   <tr><th>Coach:</th> <td><?= $team['coach'] ?></td></tr> </table> </table> <a href="/">Ranking</a> </body> </html> PHPBelgium – Belgian PHP community
  9. 9. Taking the Business Logic apart (1) PHPBelgium – Belgian PHP community
  10. 10. Taking the Business Logic apart (2) class Team {   public static function getInformationById($id) {     return Database::getInstance() ->query(       "SELECT name, won, lost, draw, coach, won*3+draw AS points " .       "FROM team WHERE id = " . (int) $id) ->fetch_assoc();   } } class Ranking {   public static function generate() {     return Database::getInstance() ->query("SELECT * FROM ranking") ->fetch_all();   } } class Database {   public static function getInstance() {     static $connection = null;     if ($connection === null) {       $connection = new mysqli("localhost", "foot", "footpw", "foot");     }     return $connection;   } } PHPBelgium – Belgian PHP community
  11. 11. Taking the Business Logic apart (3) $position = 1; foreach (Ranking::generate() as $team) { ?>     <tr>         <td class="position"><?= $position++ ?></td>         <td class="name"><a href="team.php?id=<?= $team['id'] ?>"><?= $team['name'] ?></a></td>         <td class="played"><?= $team['played'] ?></td>         <td class="won"><?= $team['won'] ?></td>         <td class="lost"><?= $team['lost'] ?></td>         <td class="draw"><?= $team['draw'] ?></td>         <td class="points"><?= $team['points'] ?></td>     </tr> <?php } <?php require 'Team.php'; require 'Ranking.php'; $team = Team::getInformationById($_GET['id']); ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> foreach (Ranking::generate() as $row) { ?>     <tr<?php if ($row['id'] === $_GET['id']) { ?> class="selected"<?php } ?>>         <td class="name"><a href="team.php?id=<?= $row['id'] ?>"><?= $row['name'] ?></a></td>         <td class="points"><?= $row['points'] ?></td>     </tr> <?php } PHPBelgium – Belgian PHP community
  12. 12. Evaluating the situation Model is reusable Views tightly linked to Changes to the the model business logic does Views impacted if the not require inspecting API of the model all files change Calls to the model may be difficult to find: spread everywhere in views PHPBelgium – Belgian PHP community
  13. 13. On the path to MVC (1) <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head>   <title>Team - <?= $GLOBALS['team']['name'] ?></title> </head> <body id="team"> <h1>Team: <?= $GLOBALS['team']['name'] ?></h1> <table id="info">   <tr><th>Won:</th>   <td><?= $GLOBALS['team']['won'] ?></td></tr>   <tr><th>Lost:</th>  <td><?= $GLOBALS['team']['lost'] ?></td></tr>   <tr><th>Draw:</th>  <td><?= $GLOBALS['team']['draw'] ?></td></tr>   <tr><th>Points:</th><td><?= $GLOBALS['team']['points'] ?></td></tr>   <tr><th>Coach:</th> <td><?= $GLOBALS['team']['coach'] ?></td></tr> </table> <table id="ranking">   <tr> <?php     <th>Name</th><th>Points</th> require 'Ranking.php';   </tr> <?php // View variables foreach ($GLOBALS['ranking'] as $row) { $ranking = Ranking::generate(); ?>   <tr> require 'home.tpl';     <td class="name"> <a href="team.php?id=<?= $row['id'] ?>"><?= $row['name'] ?></a> <?php </td> require 'Team.php';     <td class="points"><?= $row['points'] ?></td> require 'Ranking.php';   </tr> <?php // View variables } $teamId = $_GET['id']; ?> $team = Team::getInformationById($teamId); </table> $ranking = Ranking::generate(); </body> </html> require 'team.tpl'; PHPBelgium – Belgian PHP community
  14. 14. On the path to MVC (2) View parameters are passed using global variables Hint: $variableName may also be written: $GLOBALS['variableName'] The latest form may be used to differentiate variables defined by the controller file from the local view variables “htdocs” could be renamed “controllers” PHPBelgium – Belgian PHP community
  15. 15. Howto: Clean URL Clean URL: Transforming into: Enables better search engine indexing URIs are not supposed to change (Cool URIs don't change) Doesn't expose the server-side language Most MVC Frameworks provide clean URL mechanism, how to setup one with our structure? PHPBelgium – Belgian PHP community
  16. 16. Clean URL: method #1 Using Apache's mod_rewrite: RewriteEngine On RewriteRule ^/team/([0-9]*)$ /team.php?id=$1 [L] Ability to transform URLs on the fly and mapping part of the URL directly to a $_GET variable PHPBelgium – Belgian PHP community
  17. 17. Clean URL: method #2 Dropping the “.php” extension and forcing the mime-type/handler used in the Apache configuration <FilesMatch "^(index|team)$"> ForceType application/x-httpd-php </FilesMatch> or: <FilesMatch "^(index|team)$"> SetHandler application/x-httpd-php </FilesMatch> PHPBelgium – Belgian PHP community
  18. 18. Performance impact (index page) Concurrency 1 15 “spaghetti” 1776.65 3545.77 Model-View 1615.43 3137.52 MVC 1602.57 3091.74 Clean URL #1 1554.86 3032.25 Clean URL #2 1686.85 3294.60 Zend Framework 246.36 421.15 In requests/second, higher = better PHPBelgium – Belgian PHP community
  19. 19. Performance impact (team page) Concurrency 1 15 “spaghetti” 1778.89 3507.61 Model-View 1580.92 3065.41 MVC 1546.32 3032.64 Clean URL #1 1519.59 2986.12 Clean URL #2 1465.43 2896.54 Zend Framework 233.94 402.54 In requests/second, higher = better PHPBelgium – Belgian PHP community
  20. 20. Questions ? PHPBelgium – Belgian PHP community
  21. 21. Thanks :-) These slides will be available through: You can vote for this talk on: PHPBelgium – Belgian PHP community
  22. 22. License This presentation material is published under the Creative Commons Attribution-Share Alike 3.0 Unported license. You are free: to Share — to copy, distribute and transmit the work to Remix — to adapt the work Under the following conditions: Attribution — You must attribute the work in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the work). Share Alike — If you alter, transform, or build upon this work, you may distribute the resulting work only under the same, similar or a compatible license. With the understanding that: Waiver — Any of the above conditions can be waived if you get permission from the copyright holder. Other Rights — In no way are any of the following rights affected by the license: Your fair dealing or fair use rights; The author's moral rights; Rights other persons may have either in the work itself or in how the work is used, such as publicity or privacy rights. Notice — For any reuse or distribution, you must make clear to others the license terms of this work. PHPBelgium – Belgian PHP community