An introduction to the MVC Framework for Understanding MVC programming in PHP

Source: Internet
Author: User
Keywords An introduction to the MVC Framework for Understanding MVC programming in PHP
Tags joe stump ldap pear ruby on rails

"What is MVC?" 】

MVC is a concept that allows you to reconcile the "three-part (that is, MVC's full name, Model, View, Controller)" to form a complex application. A car is a very good example of MVC in real life. We look at all two view (display) Parts: internal and external. And these two are inseparable from a controller (Controller): the driver. braking systems, steering wheels and other control systems represent models: they take control from the driver (Controller) and apply it to the interior and exterior (View).

"MVC on the Network"

The concepts covered by the MVC framework are fairly simple and extremely flexible. The basic concept is that you have a separate controller (such as index.php) that controls all the applications built into the framework based on the parameter request. This controller usually contains (to a minimum) a parameter that defines the model, an event, and a get parameter. This allows the controller to confirm all requests and then run the corresponding events. For example, a/index.php?module=foo&event=bar request like this would probably be used to load a class called Foo and then run Foo::bar () [which is the bar () function]. The benefits of doing this are:

An interface that corresponds to all applications

It is cumbersome to maintain countless code within an application because each piece of code has its own relative path, database links, validation, and so on. Doing so will relieve you of your annoyance in this area, allowing you to merge and reuse the code

"Why create the author's own MVC framework?" 】

So far, I haven't seen too many MVC frameworks written in PHP. In fact, I only know a-solar, which is completely written in PHP5. The other one is cake, a ror that tries to be PHP (Ruby on rails-a ruby-language open-source network framework). I myself have some dissatisfaction with both frameworks: they do not take advantage of the existing code contained in Pear,smarty and so on, and now the cake is still more disordered; Finally, Solar is a work of the vast majority of one person (I don't mean to say that the author Paul is not a good person or programmer). These questions may not make you deny them, and it is likely that you do not care about them at all. But that is why I ask you to look at them as much as possible.

"The Old Way"

If you go back to 2001 to see your own code, the author may find a file called Template.txt, it looks like this: www.phpv.net reprint please indicate the source

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 ');
? >

God, just looking at the code will give me the urge to retreat. The concept of this code is to make sure that every application is suitable for this process, such as I can simply copy the template.txt into the myapp.php, change some variables, and see, it will work. Nonetheless, there are some serious drawbacks to this tightly organized approach:

What if my boss wants the author to use myapp.php to output PDFs in some cases, output HTML in some cases, and some cases (XML requests that are submitted directly) SOAP?

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

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

How do I handle multi-level Authentication (admin vs. non-admin)?
How do I enable output caching? Www.phpv.net Reprint please indicate the source

"New Way"

Throw everything into this MVC framework and you'll find that life is so simple. Please compare the following code:

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, to determine whether a user has logged in, or to output any other information. The controller has mastered everything.

If I want to verify LDAP, I can build Fr_auth_ldap. The controller can identify certain output methods (such as $_get[' output ') and can be converted to PDF or soap at any time. Event handling Delete, which is only responsible for the deletion, the rest of it does not matter. Because this module has an instance of the Fr_user class, it can simply determine if a user has logged in and so on. Smarty, controlling caching as a template engine is a matter of course, but a controller can also control a subset of caches.

The old way from the front to the MVC approach may be a new and unfamiliar concept for many people, but once you switch to such a concept, it can be quite difficult to turn back.

"Building the ground Floor"

I am a pear, especially a pear_error class enthusiast. PHP5 introduced a new built-in class "Exception" instead of pear_error. But Pear_error has some features that are more practical than exception. Therefore, the MVC framework instance in this series will use it for error handling. Anyway, I'm going to use the exception to get the errors from the constructor, because they can't pass back the errors themselves.

The purpose of designing these basic classes is as follows:

Quickly add functionality to the base class with Pear

Create small, reusable abstract classes that allow users to quickly develop applications in this framework

Generate documents for all base classes with Phpdocumentor

The hierarchy of classes will look like this:

-fr_object will provide basic functionality for use by all other objects (including logging, General Setfrom (), ToArray ())

-FR_OBJECT_DB is a small level that provides a database link to a subclass, among other functions

-fr_module is the underlying class for all applications (also known as modules, models, etc.)

-fr_auth is the underlying class for all validation mechanisms

Fr_auth_user is a validation class used to validate all modules that need to verify that a user is logged in

Fr_auth_no is a "Fake validation class" for all modules that do not need to be validated

-fr_presenter is the underlying class used to handle loading and display applications

The-fr_presenter_smarty is a display layer that contains the ability to load different drives. Smarty is a very good template class, it has built-in caching mechanism and an active development community (translator Note: This is clearly to advertise it ~)

Fr_presenter_debug is the display layer of the debug section. Relying on it, developers can debug the application and give them the wrong

Fr_presenter_rest is a rest display layer that allows developers to output applications in XML

From the underlying class structure above, you should be able to see the different parts of this MVC framework. Fr_module provides everything the module needs, while Fr_presenter provides a different display method. In the next article in this series, I'll create a controller that combines all the underlying classes above.

"Code Standard"

Before you formally write your code, you should sit down and discuss (or think about) the code standard with your partner (or yourself). The whole idea of MVC programming revolves around two points: the reusable nature of code (reduced coupling) and the standardization of code. I recommend that at least the following points should be considered:

The first thing to consider is the variable naming and abbreviation criteria. Don't make a big fuss about this with your partner, but once you've set the standard, you'll have to follow it all the way, especially when writing the underlying code (the underlying class).

Customize a standard prefix that is used on all functions, classes, and global variables. Unfortunately, PHP does not support the "namespace (namespace)". So to avoid confusing variable names and conflicts, it's wise to use a prefix. I'll use "fr_" as a prefix for this whole article.

"Writing the underlying"

File hierarchy planning is important. Basic hierarchy planning is simple and, to some extent, strictly defined:

/
config.php
index.php
includes/
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 might think such a file hierarchy 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 be simpler and the speed of development will be greatly improved.

At the file level, all base classes are within the includes folder. Each function module uses a configuration file, at least one module file and one template file. All modules are contained within the Modules folder. I'm used to it. Place the template file in a separate external folder, which is the TPL folder.

config.php-Hub configuration file that contains all the global configuration variables.

The index.php-controller is described in detail in a subsequent article.

object.php-the underlying classes of all underlying classes, providing the functionality required by most classes. FR_OBJECT_DB inherits this class and provides a database link.

The basic concept of architecture is to have all subclasses inherit a central class so that they all share some common features. You can put the functionality of a linked database into Fr_object, but not all classes need it, so fr_object_db has a reason to exist, and the author will discuss it later.

Require_once (' log.php ');

/**
* Fr_object
*
* The Base object class for the very most of the classes, we use with our framework.
* Provides basic logging and set/get functionality.
*
* @author Joe Stump
* @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 Joe Stump
* @access Public
*/

Public Function __construct ()
{
$this->log = log::factory (' file ', fr_log_file);
$this->me = new Reflectionclass ($this);
}

/**
* Setfrom
*
* @author Joe Stump
* @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 Joe Stump
* @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 Joe Stump
* @access Public
* @return void
*/

Public Function __destruct ()
{
if ($this->log instanceof log) {
$this->log->close ();
}
}
}

? >

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

As with Fr_module, some classes do not need to be linked to a database, so the fr_auth_no can be created to be applied to classes that do not require validation functionality.

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

Abstract class Fr_module extends Fr_object_web
{
{{{properties
/**
* $presenter
*
* Used in fr_presenter::factory () to determine which presentation (view)
* Class should is used for the module.
*
* @author Joe Stump
* @var String $presenter
* @see Fr_presenter, Fr_presenter_common, Fr_presenter_smarty
*/
Public $presenter = ' smarty ';
/**
* $data
*
* Data set by the module, that would eventually be passed to the view.
*
* @author Joe Stump
* @var mixed $data Module data
* @see Fr_module::set (), Fr_module::getdata ()
*/

Protected $data = Array ();

/**
* $name
*
* @author Joe Stump
* @var string $name name of module class
*/

Public $name;

/**
* $tplFile
*
* @author Joe Stump
* @var string $tplFile Name of the template file
* @see Fr_presenter_smarty
*/

Public $tplFile;

/**
* $moduleName
*
* @author Joe Stump
* @var string $moduleName Name of requested module
* @see Fr_presenter_smarty
*/

public $moduleName = null;
/**
* $pageTemplateFile
*
* @author Joe Stump
* @var string $pageTemplateFile Name of Outer page template
*/

public $pageTemplateFile = null;
// }}}

{{{__construct ()}
/**
* __construct
*
* @author Joe Stump
*/

Public Function __construct ()
{
Parent::__construct ();
$this->name = $this->me->getname ();
$this->tplfile = $this->name. TPL ';
}

// }}}
{{{__default ()}

/**
* __default
*
* This function was ran by the controller if a event is not specified
* In the user ' s request.
*
* @author Joe Stump
*/

Abstract public Function __default ();
// }}}
{{{set ($var, $val)

/**
* Set
*
* Set data for your module. This would eventually be passed toe the
* Presenter class via Fr_module::getdata ().
*
* @author Joe Stump
* @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 Joe Stump
* @return Mixed
* @see Fr_presenter_common
*/

Public Function GetData ()
{
return $this->data;
}
// }}}
{{{isValid ($module)

/**
* IsValid
*
* Determines if $module is a valid framework module. This was used by
* 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 should be
* Good to run.
*
* @author Joe Stump
* @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-the core of the presentation layer.

Class Fr_presenter
{
{{{factory ($type, Fr_module $module)
/**
* Factory
*
* @author Joe Stump
* @access Public
* @param string $type Presentation type (our view)
* @param mixed $module Our module, which the presenter would 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'll introduce the structure of the controller (the controllers in MVC, the index.php of this article). In the third chapter, I'll introduce the presentation layer (the view in MVC). In the fourth chapter, I will use a concrete module as an example to build an application (the module or model in MVC).

  • Related Article

    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.