Introduction to MVC framework in PHP

Source: Internet
Author: User
[What is MVC ?] MVC is a concept that allows you to combine the "three parts (the full name of MVC, Model, View, Controller)" into a complex application. A car is a very good example of MVC in real life. We can View both the internal View and the external View. The two cannot be separated from one Controller: the driver. The brake system, steering wheel, and other control systems represent the Model. [What is MVC ?]

MVC is a concept that allows you to combine the "three parts (the full name of MVC, Model, View, Controller)" into a complex application. A car is a very good example of MVC in real life. We can View both the internal View and the external View. The two cannot be separated from one Controller: the driver. The brake system, steering wheel, and other control systems represent the Model: they obtain control methods from the driver (Controller) and apply them to the internal and external View ).

[MVC on the network]

The MVC framework covers a simple and extremely flexible concept. The basic concept is that you have a separate controller (such as index. php) to control all the applications built on the parameter request framework. This controller usually contains (to a minimum) a parameter defining the model, an event, and a GET parameter. In this way, the controller can confirm all requests and then run corresponding events. For example, what is/index. php like this? Module = foo & event = bar is probably used to load a class named foo, and then run foo: bar () [is the bar () function]. The benefits of doing so are:

An interface corresponding to all applications

At the same time, it is very troublesome to maintain countless codes in an application, because each piece of code has its own relative path, database link, verification, and so on. In this way, you will be relieved of your troubles in this regard, allowing you to merge and reuse the code.

[Why create the author's own MVC framework ?]

So far, I have never seen many MVC frameworks written in PHP. In fact, I only know one-Solar, which is completely written in PHP5. The other is Cake, a RoR that tries to become a PHP (Ruby on Rails-a Ruby open-source network framework ). I myself have some dissatisfaction with these two frameworks: they have not used the existing code contained in PEAR, Smarty, and so on; the current Cake is still disordered; finally, solar is a vast majority of works written by one person (I have no intention to say that Paul is not a good person or a good programmer ). These problems may not allow you to deny them, and you may not care about them at all. But because of this, I ask you to review them as much as possible.

[Old mode]

If you go back to the code written in, you can find a file named template.txt. it looks like this: www.phpv.net reprinted, please indicate the source

<? Php
Require_once ('config. php'); // Other requires, DB info, etc.

$ APP_DB = 'mydb ';
$ APP_REQUIRE_LOGIN = false; // Set to true if script requires login
$ APP_TEMPLATE_FILE = 'foo. php'; // Smarty template
$ APP_TITLE = 'My application ';

If ($ APP_REQUIRE_LOGIN = true ){
If (! Isset ($ _ session ['userid']) {
Header ("Location:/path/to/login. php ");
Exit ();
}
}

$ Db = DB: connect ('MySQL: // '. $ DB_USER.': '. $ DB_PASS.' @ localhost/'. $ APP_DB );
If (! PEAR: isError ($ db )){
$ Db-> setFetchMode (DB_FETCHMODE_ASSOC );
} Else {
Die ($ db-> getMessage ());
}

// Put your logic here
// Output the template

Include_once (APP_TEMPLATE_PATH. '/header. php ');
Include_once (APP_TEMPLATE_PATH. '/'. $ APP_TEMPLATE_FILE );
Include_once (APP_TEMPLATE_PATH. '/footer. php ');
?>

My God, it's just that reading these codes will make me have a desire to retreat. The concept of this code ensures that every application can use this processing tool. for example, you can simply copy template.txt to myapp. php and change some variables. you can see that it can run. However, this well-organized solution has some serious disadvantages:

What should I do if my boss wants the author to use myapp. php to output PDF files, HTML files in some cases, and SOAP files in some cases (directly submitted xml requests?

What should I do if this application requires IMAP or LDAP authentication?

How can I handle various codes (including editing, upgrading, and deleting )?

How can I handle multi-level authentication (administrator vs. non-administrator )?
How can I enable the output cache? For reprinted on www.phpv.net, please indicate the source

[New method]

By throwing everything into this MVC framework, you will find that life is so simple. Compare the following code:

<? Php
Class myapp extends FR_Auth_User
{
Public function _ construct ()
{
Parent: :__ construct ();
}

Public function _ default ()
{
// Do something here
}

Public function delete ()
{}

Public function _ destruct ()
{
Parent: :__ destruct ();
}
}

?>

Note that this code is clearly not used to link to a database, determine whether a user has logged in, or output any other information. The controller knows everything.

If I want to verify LDAP, I can establish FR_Auth_LDAP. The controller can identify some output methods (such as $ _ GET ['output']) and convert them to PDF or SOAP at any time. Delete is only responsible for event processing, and does not care about others. This module has an instance of the FR_User class, which can easily determine whether a user has logged in. Smarty is taken for granted as a template engine to control the cache, but the controller can also control a portion of the cache.

From the old method mentioned above to the MVC method, it may be a brand new and unfamiliar concept for many people, but once you switch to this concept, it will be quite difficult to switch back.

[Underlying layer]

I am a PEAR, especially a fan of the PEAR_Error class. PHP5 introduces a new built-in class "Exception" to replace PEAR_Error. However, PEAR_Error has some more practical features than Exception. Therefore, the MVC framework instance in this series of articles will use it for error handling. In any case, I still need to use Exception to get errors from the constructor, because they cannot return errors themselves.

The purpose of designing these basic classes is as follows:

Use PEAR to quickly add features to basic classes

Create a small, reusable abstract class so that users can quickly develop applications in this framework

Use phpDocumentor to generate documents for all basic classes

The class hierarchy looks like this:

-FR_Object provides basic functions for all other objects (including logging, General setFrom (), toArray ())

-FR_Object_DB is a small layer that provides database links and other functions for sub-classes.

-FR_Module is the underlying class of all applications (such as modules and models ).

-FR_Auth is the underlying class of all authentication mechanisms.

· FR _ Auth_User is a verification class used to verify all modules that require user login verification

· FR _ Auth_No is a "false verification class" for all modules that do not require verification"

-FR_PResenter is the underlying class used to process loading and display applications.

-FR_Presenter_Smarty is a display layer that contains the ability to load different drives. Smarty is a very good template class. it has a built-in Cache mechanism and an active development group ~)

· FR _ Presenter_debug is the display layer of the debugging part. Relying on it, developers can debug applications and correct them

· FR _ Presenter_rest is a REST display layer that allows developers to output applications in XML format.

From the above basic class structure, you should be able to see different parts of the MVC framework. FR_Module provides what all modules need, while FR_Presenter provides different display methods. In the next article in this series, I will create a controller to combine all the above base classes.

[Code Standard]

Before writing the code, you should sit down and discuss (or think about) the code standards with your partner (or yourself. The overall idea of MVC programming is centered around two points: code reuse (reduce coupling) and code standardization. I recommend taking into account at least the following points:

The first thing to consider is the variable naming and abbreviations. Do not argue with your partners, but once the standards are set, they must follow them from beginning to end, especially when writing the underlying code (basic class.

Customizes a standard prefix for all functions, classes, and global variables. Unfortunately, PHP does not support "namespace )". Therefore, it is wise to use a prefix to avoid confusion between variable names and conflicts. Throughout the article, I will use "FR _" as the prefix.

[Bottom layer]

Hierarchical File planning is very important. Basic hierarchical planning is simple and strictly defined to a certain extent:

/
Config. php
Index. php
Except des/
Auth. php
Auth/
No. php
User. php
Module. php
Object. php
Object/
DB. php
Presenter. php
Presenter/
Common. php
Debug. php
Smarty. php
Smarty/
Modules/
Example/
Config. php
Example. php
Tpl/
Example. tpl
Tpl/
Default/
Cache/
Config/
Templates/
Templates_c/

You may think that such a file level definitely represents a lot of code! Yes, but you can do it. After the end of the series, you will find that your programming will become simpler and the development speed will be greatly improved.

At the file level, all the basic classes are in the supported des folder. Each function module uses a configuration file, at least one module file and one template file. All modules are included in the modules folder. I am used to placing template files in a separate external folder, that is, the tpl folder.

Config. php-central configuration file, which contains all global configuration variables.

Index. php-controller, which will be detailed in the next article.

Object. php-underlying classes of all basic classes provide the functions required by most classes. FR_Object_DB inherits this class and provides database links.

The basic concept of the structure is to let all subclasses inherit a central class so that they share some common features. You can put the function of connecting to the database into FR_Object, but not all classes need this function, so FR_Object_DB has a reason for its existence. The author will discuss it later.

<? Php
Require_once ('log. php ');

/**
* FR_Object
*
* The base object class for most of the classes that we use in our framework.
* Provides basic logging and set/get functionality.
*
* @ Author jostump <joe@joestump.net>
* @ Package Framework
*/

Abstract class FR_Object
{
/**
* $ Log
*
* @ Var mixed $ log Instance of PEAR Log
*/

Protected $ log;
/**
* $ Me
*
* @ Var mixed $ me Instance of ReflectionClass
*/

Protected $ me;
/**
* _ Construct
*
* @ Author jostump <joe@joestump.net>
* @ Access public
*/

Public function _ construct ()
{
$ This-> log = Log: factory ('file', FR_LOG_FILE );
$ This-> me = new ReflectionClass ($ this );
}

/**
* SetFrom
*
* @ Author jostump <joe@joestump.net>
* @ Access public
* @ Param mixed $ data Array of variables to assign to instance
* @ Return void
*/

Public function setFrom ($ data)
{
If (is_array ($ data) & count ($ data )){
$ Valid = get_class_vars (get_class ($ this ));
Foreach ($ valid as $ var => $ val ){
If (isset ($ data [$ var]) {
$ This-> $ var = $ data [$ var];
}
}
}
}

/**
* ToArray
*
* @ Author jostump <joe@joestump.net>
* @ Access public
* @ Return mixed Array of member variables keyed by variable name
*/

Public function toArray ()
{
$ Defaults = $ this-> me-> getDefaultProperties ();
$ Return = array ();
Foreach ($ defaults as $ var => $ val ){
If ($ this-> $ var instanceof FR_Object ){
$ Return [$ var] = $ this-> $ var-> toArray ();
} Else {
$ Return [$ var] = $ this-> $ var;
}
}

Return $ return;
}

/**
* _ Destruct
*
* @ Author jostump <joe@joestump.net>
* @ Access public
* @ Return void
*/

Public function _ destruct ()
{
If ($ this-> log instanceof Log ){
$ This-> log-> close ();
}
}
}

?>

Auth. php-this is the underlying class for all verification functions. It is extended from FR_Module and its main function is to define how a basic verification class works.

Like FR_Module, some classes do not need to be linked to the database. Similarly, FR_Auth_No can be created and applied to classes that do not require verification.

<? Php
Abstract class FR_Auth extends FR_Module
{
// {_ Construct ()
Function _ construct ()
{
Parent: :__ construct ();
}
//}}}
// {Authenticate ()
Abstract function authenticate ();
//}}}

// {_ Destruct ()

Function _ destruct ()
{
Parent: :__ destruct ();
}
//}}}
}

?>

Module. php-heart of all modules

<? Php
Abstract class FR_Module extends FR_Object_Web
{
// {Properties
/**
* $ Presenter
*
* Used in FR_Presenter: factory () to determine which presentation (view)
* Class shoshould be used for the module.
*
* @ Author jostump <joe@joestump.net>
* @ Var string $ presenter
* @ See FR_Presenter, FR_Presenter_common, FR_Presenter_smarty
*/
Public $ presenter = 'smarty ';
/**
* $ Data
*
* Data set by the module that will eventually be passed to the view.
*
* @ Author jostump <joe@joestump.net>
* @ Var mixed $ data Module data
* @ See FR_Module: set (), FR_Module: getData ()
*/

Protected $ data = array ();

/**
* $ Name
*
* @ Author jostump <joe@joestump.net>
* @ Var string $ name Name of module class
*/

Public $ name;

/**
* $ TplFile
*
* @ Author jostump <joe@joestump.net>
* @ Var string $ tplFile Name of template file
* @ See FR_Presenter_smarty
*/

Public $ tplFile;

/**
* $ ModuleName
*
* @ Author jostump <joe@joestump.net>
* @ Var string $ moduleName Name of requested module
* @ See FR_Presenter_smarty
*/

Public $ moduleName = null;
/**
* $ PageTemplateFile
*
* @ Author jostump <joe@joestump.net>
* @ Var string $ pageTemplateFile Name of outer page template
*/

Public $ pageTemplateFile = null;
//}}}

// {_ Construct ()
/**
* _ Construct
*
* @ Author jostump <joe@joestump.net>
*/

Public function _ construct ()
{
Parent: :__ construct ();
$ This-> name = $ this-> me-> getName ();
$ This-> tplFile = $ this-> name. '. tpl ';
}

//}}}
// {_ Default ()

/**
* _ Default
*
* This function is ran by the controller if an event is not specified
* In the user's request.
*
* @ Author jostump <joe@joestump.net>
*/

Abstract public function _ default ();
//}}}
// {Set ($ var, $ val)

/**
* Set
*
* Set data for your module. This will eventually be passed toe
* Presenter class via FR_Module: getData ().
*
* @ Author jostump <joe@joestump.net>
* @ Param string $ var Name of variable
* @ Param mixed $ val Value of variable
* @ Return void
* @ See FR_Module: getData ()
*/

Protected function set ($ var, $ val ){
$ This-> data [$ var] = $ val;
}
//}}}
// {GetData ()

/**
* GetData
*
* Returns module's data.
*
* @ Author jostump <joe@joestump.net>
* @ Return mixed
* @ See FR_Presenter_common
*/

Public function getData ()
{
Return $ this-> data;
}
//}}}
// {IsValid ($ module)

/**
* IsValid
*
* Determines if $ module is a valid framework module. This is used
* The controller to determine if the module fits into our framework's
* Mold. If it extends from both FR_Module and FR_Auth then it shoshould be
* Good to run.
*
* @ Author jostump <joe@joestump.net>
* @ Static
* @ Param mixed $ module
* @ Return bool
*/

Public static function isValid ($ module)
{
Return (is_object ($ module )&&
$ Module instanceof FR_Module &&
$ Module instanceof FR_Auth );
}
//}}}
// {_ Destruct ()

Public function _ destruct ()
{
Parent: :__ destruct ();
}
//}}}
}
?>

Presenter. php-core of the presentation layer.

<? Php
Class FR_Presenter
{
// {Factory ($ type, FR_Module $ module)
/**
* Factory
*
* @ Author jostump <joe@joestump.net>
* @ Access public
* @ Param string $ type Presentation type (our view)
* @ Param mixed $ module Our module, which the presenter will display
* @ Return mixed PEAR_Error on failure or a valid presenter
* @ Static
*/

Static public function factory ($ type, FR_Module $ module)
{
$ File = FR_BASE_PATH. '/includes/Presenter/'. $ type. '. php ';
If (include ($ file )){
$ Class = 'Fr _ Presenter _ '. $ type;
If (class_exists ($ class )){
$ Presenter = new $ class ($ module );
If ($ presenter instanceof FR_Presenter_common ){
Return $ presenter;
}
Return PEAR: raiseError ('invalid presentation class: '. $ type );
}
Return PEAR: raiseError ('presentation class not found: '. $ type );
}
Return PEAR: raiseError ('Presenter file not found: '. $ type );
}
//}}}
}

?>

In the next article, I will introduce the structure of the Controller (Controller in MVC, index. php in this article. In Article 3, I will introduce the presentation layer (View in MVC ). In article 4, I will use a specific Module as an example to create an application (Module or Model in MVC ).

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.