Hands-on PHP framework to learn more about MVC run process _php instance

Source: Internet
Author: User
Tags learn php php class php foreach php framework prepare rowcount sprintf create database

1 What is MVC

The MVC pattern (model-view-controller) is a software architecture model in software engineering, which divides the software system into three basic parts: model, view and controller (Controller).

The MVC pattern in PHP, also known as Web MVC, evolved from the late 70 's. The purpose of MVC is to implement a dynamic program design that facilitates subsequent modifications and extensions to the program, and makes it possible to reuse a part of the program. In addition, this model makes the program structure more intuitive by simplifying the complexity. The software system, by separating the basic parts of itself, also gives the functions that each basic part should have.

Functions of the various parts of the MVC:
• Model model– manages most of the business logic and all the database logic. The model provides an abstraction layer for connecting and manipulating databases.
• Controller Controller-responsible for responding to user requests, preparing data, and deciding how to present data.
• View view– is responsible for rendering the data and rendering it to the user in HTML format.

A typical web MVC process:
1.Controller intercept user's request;
2.Controller Call model completion state of Read and write operations;
3.Controller Pass the data to view;
4.View renders the final result and presents it to the user.

2 Why do you develop the MVC framework yourself

With a lot of good MVC frameworks available on the Web, this tutorial is not about developing a comprehensive, ultimate MVC framework solution, but rather as a good opportunity to learn PHP from within, and in the process, you will learn object-oriented programming and MVC design patterns, And to learn some of the development of considerations.

More importantly, you can take full control of your framework and incorporate your ideas into your development framework. Although not necessarily good, but you can follow your way to develop functions and modules.

3 start developing your own MVC framework

3.1 Directory Preparation

Before we start the development, let's build the project, assuming that the project we built is a TODO,MVC framework that can be named fastphp, so the next step is to set the directory structure first.

Although all of the above directories are not used in this tutorial, it is necessary to set up the program directory in the first place for future extensibility. Here's how each directory works:
application– Application code
config– Program configuration or database configuration
fastphp-Framework Core Catalogue
public– static file
Runtime-Temporary Data directory
scripts– command line tools

3.2 Code Specification

After the directory is set up, we'll go on to specify the code specification:
The table name for 1.MySQL should be lowercase, such as: Item,car
2. The module name (Models) needs to capitalize the first letter, and add "Model" after the name, such as: Itemmodel,carmodel
3. The controller (controllers) needs to capitalize the first letter, and add "Controller" to the name, such as: Itemcontroller,carcontroller
4. View (views) deployment structure is "controller name/behavior name", such as: item/view.php,car/buy.php

Some of the rules above are designed to make it easier to invoke each other in a program. The next step is to start real PHP MVC programming.

3.3 redirect

Redirect all data requests to the index.php file, and create a new. htaccess file in the Todo directory, with the following file:

<ifmodule mod_rewrite.c>
  rewriteengine on

  # Ensure that the request path is not a filename or directory
  rewritecond%{request_filename}!-f
  Rewritecond%{request_filename}!-d

  # Redirect all requests to Index.php?url=pathname
  rewriterule ^ (. *) $ index.php?url= $ [pt,l]
</IfModule>

The main reasons for doing so are:
1. The procedure has a single entrance;
2. In addition to static procedures, all other programs are redirected to the index.php;
3. Can be used to generate favorable URL for SEO, want better configuration URL, later may need URL routing, here first do not introduce.

3.4 Entry Files

After the above operation, you should know what we need to do, yes! Add the index.php file under the public directory, which reads:

 <?php

//application directory for the current directory
define (' App_path ', __dir__. ') /');

Open Debug Mode
define (' App_debug ', true);

Site Root URL
define (' App_url ', ' http://localhost/fastphp ');

Load frame
require './fastphp/fastphp.php ';

Note that the above PHP code does not add the PHP end symbol "?>", the main reason for this is that for only PHP code files, the end sign ("?>") is best not exist, PHP itself does not need to end the symbol, Not adding a closing symbol can largely prevent the end from adding additional injected content to make the program more secure.

3.5 Profiles and Master requests

In index.php, we made a request for the fastphp.php under the fastphp folder, so what exactly would the fastphp.php boot file contain?

<?php

//initialization constant
defined (' Frame_path ') or define (' Frame_path ', __dir__. ') /');
Defined (' App_path ') or define (' App_path ', dirname ($_server[' script_filename ')). ' /');
Defined (' App_debug ') or define (' App_debug ', false);
Defined (' Config_path ') or define (' Config_path ', App_path. ' config/');
Defined (' Runtime_path ') or define (' Runtime_path ', App_path. ' runtime/');

Contains the configuration file
require App_path. ' config/config.php ';

Contains the core framework class
require Frame_path. ' core.php ';

The $fast of the core class of instantiation is
new core;
$fast->run ();

All of the above files can actually be included directly in the index.php file, constants can also be defined directly in index.php, and the reason why we do this is to make it easier to manage and expand later, so that the programs that need to be loaded at the outset are referenced in a separate file.

First look at config file under the Config. php file, the main role of the file is to set some program configuration items and database connection, the main contents are:

 <?php
 
/** Variable configuration **/
 
define (' db_name ', ' todo ');
Define (' Db_user ', ' root ');
Define (' Db_password ', ' root ');
Define (' db_host ', ' localhost ');

It should be said that the config.php involved is not much, but some basic database settings, and then look at fastphp under the Common framework entry file core.php how to write.
 

<?php/** * fastphp Core Framework * */class Core {//Run program function run () {spl_autoload_register ($this, ' LOADC
    Lass '));
    $this->setreporting ();
    $this->removemagicquotes ();
    $this->unregisterglobals ();
  $this->route ();
    ///Routing processing function Route () {$controllerName = ' Index ';

    $action = ' index ';
      if (!empty ($_get[' url ')) {$url = $_get[' url '];
      
      $urlArray = explode ('/', $url);
      
      Gets the controller name $controllerName = Ucfirst ($urlArray [0]);
      Get Action name Array_shift ($urlArray); $action = Empty ($urlArray [0])?
      
      ' Index ': $urlArray [0];
      Gets the URL parameter array_shift ($urlArray); $queryString = Empty ($urlArray)?
    Array (): $urlArray; }//data is empty processing $queryString = Empty ($queryString)?

    Array (): $queryString; The $controller of the instantiation controller = $controllerName.
    ' Controller ';

    $dispatch = new $controller ($controllerName, $action); If the controller is stored and the action exists, this calls and passes in the URL parameter if ((int) MeThod_exists ($controller, $action)) {Call_user_func_array (Array ($dispatch, $action), $queryString); else {exit ($controller.
    "Controller does not exist");
      }//Detect development environment function setreporting () {if (App_debug = = True) {error_reporting (E_all);
    Ini_set (' display_errors ', ' on ');
      else {error_reporting (e_all);
      Ini_set (' display_errors ', ' off ');
      Ini_set (' log_errors ', ' on '); Ini_set (' Error_log ', Runtime_path.
    ' Logs/error.log '); }///Remove sensitive character function Stripslashesdeep ($value) {$value = Is_array ($value)? Array_map (' Stripslashesdeep ', $
    Value): Stripslashes ($value);
  return $value; //Detect sensitive characters and remove function removemagicquotes () {if (GET_MAGIC_QUOTES_GPC ()) {$_get = Stripslashesdeep ($_g
      ET);
      $_post = Stripslashesdeep ($_post);
      $_cookie = Stripslashesdeep ($_cookie);
    $_session = Stripslashesdeep ($_session); }///Detect custom global variable (register globals) and remove function unregisterglobals ()
  {if (Ini_get (' register_globals ')) {$array = array (' _session ', ' _post ', ' _get ', ' _cookie ', ' _request ', ' _ser ')
      VER ', ' _env ', ' _files '); foreach ($array as $value) {foreach ($GLOBALS [$value] as $key => $var) {if ($var = = $GLOBALS [$key]
          ) {unset ($GLOBALS [$key]); Auto Load controller and model class static function LoadClass ($class) {$frameworks = Frame_path. $c Lass.
    '. class.php '; $controllers = App_path. ' application/controllers/'. $class.
    '. class.php '; $models = App_path. ' application/models/'. $class.

    '. class.php ';
    if (file_exists ($frameworks)) {//Load Framework core class include $frameworks;
    } elseif (File_exists ($controllers)) {//Load Application controller class include $controllers;
    } elseif (File_exists ($models)) {//Load Application model class include $models;

 else {/* error code/}}}

The following focuses on the main request method Callhook (), first we would like to see our URL will be like this:
Yoursite.com/controllername/actionname/querystring

The function of Callhook () is to get the URL from the global variable G et[′url′] variable and split it into three parts: the get[′url′] variable to get the URL and split it into three parts: Controller, Action, and Action and QueryString.

For example, the URL link is: Todo.com/item/view/1/first-item, then
• $controller is: item
• $action is: view
• Query string: Array (1, First-item)

After the split is complete, a new controller is instantiated: $controller. ' Controller ' (where "." is a hyphen) and calls its method $action.

3.6 Controller/controller base class

The next step is to create the base class for the program in fastphp, including the controller, the model, and the base class for the view.

The new Controller base class is Controller.class.php, the main function of the controller is the general scheduling, the specific contents are as follows:

<?php 
/**
 * Controller base class
 *
/class Controller
{
  protected $_controller;
  protected $_action;
  protected $_view;
 
  Constructor, initializes the property, and instantiates the corresponding model
  function __construct ($controller, $action)
  {
    $this->_controller = $ Controller;
    $this->_action = $action;
    $this->_view = new View ($controller, $action);

  Assign variable
  function assign ($name, $value)
  {
    $this->_view->assign ($name, $value);

  Render View
  function __destruct ()
  {
    $this->_view->render ();
  }
}


The Controller class implements communication for all controllers, models, and Views (view classes). When the destructor is executed, we can call render () to display the view file.

3.7 Model base class

The new model base class is Model.class.php, and the model base class Model.class.php code is as follows:

 <?php

class Model extends Sql
{
  protected $_model;
  protected $_table;
 
  function __construct ()
  {
    //Connection Database
    $this->connect (Db_host, Db_user, Db_password, db_name);
    
    Gets the model name
    $this->_model = Get_class ($this);
    $this->_model = RTrim ($this->_model, ' model ');
    
    The database table name is consistent with the class name
    $this->_table = strtolower ($this->_model);
  }
 
  function __destruct ()
  {
  }
}

Considering that the model needs to be processed by the database, a database base class Sql.class.php is established, and the model base class inherits Sql.class.php, the code is as follows:

 <?php class Sql {protected $_dbhandle;

  protected $_result; Connect database Public Function connect ($host, $user, $pass, $dbname) {try {$dsn = sprintf ("Mysql:host=%s;dbname=
      %s;charset=utf8 ", $host, $dbname);
    $this->_dbhandle = new PDO ($DSN, $user, $pass, Array (pdo::attr_default_fetch_mode => pdo::fetch_assoc));
    catch (Pdoexception $e) {exit (' ERROR: '. $e->getmessage ());
    }//Query all public function SelectAll () {$sql = sprintf ("Select * from '%s '", $this->_table);
    $sth = $this->_dbhandle->prepare ($sql);

    $sth->execute ();
  return $sth->fetchall (); ////(ID) query public function Select ($id) {$sql = sprintf ("Select * from '%s ' where ' id ' = '%s '"), $this-&G
    T;_table, $id);
    $sth = $this->_dbhandle->prepare ($sql);
    
    $sth->execute ();
  return $sth->fetch (); The Public Function Delete ($id) {$sql = sprintf ("Delete from '%s ' where ' id ' = '%) is deleted by the condition (ID)S ' ", $this->_table, $id);
    $sth = $this->_dbhandle->prepare ($sql);

    $sth->execute ();
  return $sth->rowcount ();
    //Custom SQL query that returns the number of rows affected public Function query ($sql) {$sth = $this->_dbhandle->prepare ($sql);

    $sth->execute ();
  return $sth->rowcount (); //New Data Public Function add ($data) {$sql = sprintf ("INSERT INTO '%s '%s '), $this->_table, $this->format

    Insert ($data));
  return $this->query ($sql); }//Modify data Public Function update ($id, $data) {$sql = sprintf ("Update '%s ' set%s where ' id ' = '%s '"), $this

    ; _table, $this->formatupdate ($data), $id);
  return $this->query ($sql);
    ///convert array to SQL statement in INSERT format private function Formatinsert ($data) {$fields = array ();
    $values = Array ();
      foreach ($data as $key => $value) {$fields [] = sprintf ('%s ', $key);
    $values [] = sprintf ("'%s '", $value);
    $field = Implode (', ', $fields); $value = Implode (', ', $valUES);
  Return sprintf ("(%s) values (%s)", $field, $value);
    ///convert array to update format SQL statement private Function formatupdate ($data) {$fields = array ();
    foreach ($data as $key => $value) {$fields [] = sprintf ('%s ' = '%s ', $key, $value);
  Return implode (', ', $fields);

 }
}

It should be said that Sql.class.php is the core part of the framework. Why? Because of this, we create a SQL abstraction layer that can greatly reduce the programming of the database. Although the PDO interface is already concise, the flexibility of the framework after abstraction is higher.

3.8 Views View class

The view class View.class.php contents are as follows:

 <?php/** * View Graph Class View {protected $variables = array ();
  protected $_controller;

  protected $_action;
    function __construct ($controller, $action) {$this->_controller = $controller;
  $this->_action = $action;
  /** Assign variable **/function assign ($name, $value) {$this->variables[$name] = $value;
    /** rendering shows **/function render () {Extract ($this->variables); $defaultHeader = App_path.
    ' application/views/header.php '; $defaultFooter = App_path.
    ' application/views/footer.php '; $controllerHeader = App_path. ' application/views/'. $this->_controller.
    '/header.php '; $controllerFooter = App_path. ' application/views/'. $this->_controller.
    
    '/footer.php ';
    The page header file if (file_exists ($controllerHeader)) {include ($controllerHeader);
    else {include ($defaultHeader); }//page content file include (App_path. ' application/views/'. $this->_controller. '/' . $this->_action.
    
    '. php ');
    The footer file if (file_exists ($controllerFooter)) {include ($controllerFooter);
    else {include ($defaultFooter);

 }
  }
}

So our core PHP MVC framework was written, and we started writing applications to test the framework functionality.

4 Application

4.1 Database Deployment

Create a new TODO database in SQL, add the item datasheet and insert 2 records using the following statement:

CREATE DATABASE ' Todo ' DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
Use ' Todo ';

CREATE TABLE ' item ' (
  ' id ' int (one) not null auto_increment,
  ' item_name ' varchar (255) NOT NULL,
  PRIMARY KEY (' I d ')
) Engine=innodb auto_increment=1 DEFAULT Charset=utf8;
 
INSERT into the ' item ' VALUES (1, ' Hello World ');
INSERT into ' item ' VALUES (2, ' lets go! '); 

4.2 The Department model

Then, we also need to create a itemmodel.php model in the models directory, which reads as follows:

 <?php

class Itemmodel extends Model
{/
  * Business Logic Layer Implementation */
}

The model content is empty. Because the Item model inherits model, it has all the features of model.

4.3 Controller of the Department

Create a itemcontroller.php controller in the Controllers directory, which reads as follows:

 <?php class Itemcontroller extends Controller {//Home method, test framework custom DB Query Public Function index () {$items = (n

    EW Itemmodel)->selectall ();
    $this->assign (' title ', ' all entries ');
  $this->assign (' Items ', $items);
    ///Add record, test framework DB record creation (create) Public function add () {$data [' item_name '] = $_post[' value '];

    $count = (new Itemmodel)->add ($data);
    $this->assign (' title ', ' Add success ');
  $this->assign (' count ', $count);

    //View records, test framework DB record read (read) Public function view ($id = null) {$item = (new Itemmodel)->select ($id);
    $this->assign (' title ', ' Viewing '. $item [' item_name ']);
  $this->assign (' item ', $item); //Update records, test framework DB Records Update (update) Public Function Update () {$data = array (' ID ' => $_post[' id '), ' Item_name ' =& Gt
    $_post[' value ']);

    $count = (new Itemmodel)->update ($data [' id '], $data);
    $this->assign (' title ', ' Modify success ');
  $this->assign (' count ', $count);
///delete record, test frame DB record Delete (delete)  The Public function Delete ($id = null) {$count = (new Itemmodel)->delete ($id);
    $this->assign (' title ', ' delete success ');
  $this->assign (' count ', $count);

 }
}

4.4 Department View

Create a new header.php and footer.php two header footer template in the views directory below.

header.php, Content:

  

Then, create the following view files in Views/item.

index.php, browse all records of the item table in the database, content:

 <form action= "<?php echo app_url >/item/add" method= "POST" >
  <input type= "text" value= "click Add" onclick= "this.value=" "name=" value ">
  <input type=" Submit "value=" Add ">
</form>
<br/ ><br/>

<?php $number = 0?>
 
<?php foreach ($items as $item):?> <a class= "Big
  " href= " <?php echo App_url >/item/view/<?php echo $item [' id ']?> title= "click Modify" > <span class=
    "Item" >< c9/><?php echo + + $number?>
      <?php echo $item [' Item_name ']?>
    </span>
  </a>
  ----
  <a class= "Big" href= "<?php echo app_url? >/item/delete/<?php echo $item [' id ']?> ' > Delete </a>
<br/>
<?php Endforeach?>

add.php, add records, content:
<a class= "Big" href= "<?php echo app_url? >/item/index" > Successfully added <?php echo $count?> record, click Back to </a >

view.php, view a single record, content:

 <form action= "<?php echo app_url >/item/update" method= "POST" >
  <input type= "text" name= "value" Value= "<?php echo $item [' Item_name ']?>" > <input type= "hidden" name= "
  id" value= "<?php echo $item [' Id ']?> ' >
  <input type= "Submit" value= "Modify" >
</form>

<a class= "Big" href= "<?php" echo app_url? >/item/index > Return </a>

update.php, change the record, content:
<a class= "Big" href= "<?php echo app_url? >/item/index" > Successfully modified <?php echo $count?> entry, click Back to </a>< /c8>

delete.php, delete records, content:
<a href= "<?php echo app_url >/item/index" > successfully deleted <?php echo $count?> entry, click Back </a>

4.5 Application Testing

In this way, the TODO program is accessed in the browser: http://localhost/todo/item/index/, you can see the effect.

The above code has all been published to the GitHub, the key part of the added air annotation, warehouse address: https://github.com/yeszao/fastphp, Welcome to clone, submit.

To design better MVC, or to use more specification, see the responsibility Division principle of the MVC architecture.

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.