1. what is the MVCMVC Model (Model-View-Controller) is a software architecture Model in software engineering. the software system is divided into three basic parts: Model) view and Controller ). The purpose of the MVC pattern is to implement a dynamic program design, simplify the subsequent modification and extension of the program, and make reuse of a part of the program possible.
1. what is MVC?
MVCModeModel-View-Controller is a software architecture Model in software engineering. the software system is divided into three basic parts: Model and View) and Controller ).
MVCModeThe purpose is to implement a dynamic program design, simplify subsequent modifications and extensions of the program, and make reuse of a part of the program possible. In addition, this mode simplifies the complexity to make the program structure more intuitive. The software system also gives the functions of each basic part through the separation of its basic parts. Professionals can use their own expertise groups:
- (Controller)-responsible for forwarding requests and processing requests.
- (View)-graphic interface design by the interface designer.
- (Model)-programmers compile the functions (implementing algorithms and so on) of the program, database experts conduct data management and database design (can implement specific functions ).
Model)? The data Model is used to encapsulate data related to the application's business logic and to process the data. The "model" has the right to directly access data, such as accessing databases. "Model" does not depend on "View" and "controller", that is, the model does not care about how it is displayed or operated. However, data changes in the model are generally published through a refresh mechanism. To implement this mechanism, the views used to monitor this model must be registered on this model in advance, so that the views can understand the changes in the data model.
View)? The view layer can display data purposefully (theoretically, this is not necessary ). Generally, there is no program logic in the view. To refresh a view, the view needs to access the data Model it monitors. Therefore, you should register the data that it monitors in advance.
Controller)? The controller acts as an organizational unit between different layers and is used to control application processes. It processes events and responds. "Events" include user behaviors and changes in data models.
II. why should I develop the MVC framework myself?
There are a large number of excellent MVC frameworks available on the network. this tutorial is not intended to develop a comprehensive and ultimate MVC framework solution, instead, you can think of it as a good opportunity to learn PHP from the inside. in this process, you will learn object-oriented programming and design patterns, and learn some precautions in the open.
More importantly, you can have full control over your framework and integrate your ideas into your development framework. Although not always done well, you can develop functions and modules in your way.
3. start to develop your own MVC framework
Before starting development, let's first set up the project. assume that the project we created is todo, then the first step is to set the directory structure first.
Although none of the above directories will be used in this tutorial, it is necessary to set the program directory at the beginning to make the program more extensible in the future. The role of each directory is described as follows:
- Application-store program code
- Config-store program configuration or database configuration
- Db-used to store database backup content
- Library-store framework code
- Public-store static files
- Scripts-store command line tools
- Tmp-store temporary data
After the directory is set, we will discuss some code specifications:
- MySQL table names must be in the complex format in lower case, such as items and cars.
- The module name (Models) must start with an uppercase letter and adopt the singular mode, such as Item and Car.
- The Controller (Controllers) must start with an uppercase letter. it must be in the plural form and add "Controller" to the name, such as ItemsController and CarsController.
- View (Views) adopts the plural form and adds behavior as a file later, such as: items/view. php, cars/buy. php
Some of the above rules are designed to better call each other in the program clock. Next we will start the real encoding.
The first step is to redirect all requests to the public directory. the solution is to add a. htaccesss file under the todo file with the following content:
RewriteEngine onRewriteRule ^$ public/ [L]RewriteRule (.*) public/$1 [L]
After we redirect all requests to the public directory, we need to redirect all data requests to the public index. php file, so you need to create a new one in the public folder. htaccess file with the following content:
RewriteEngine On # if the file exists, access the directory directly without RewriteRuleRewriteCond % {REQUEST_FILENAME }! -F # if the directory exists, directly access the directory without RewriteRuleRewriteCond % {REQUEST_FILENAME }! -D # rewrite all other URLs to index. php/URLRewriteRule ^ (. *) $ index. php? Url = $1 [PT, L]
The main reasons for doing so are:
- This allows the program to have a single entry, redirecting all programs except static programs to index. php;
- It can be used to generate SEO-friendly URLs. if you want to better configure the URLs, you may need URL routing later. we will not introduce it here.
After completing the above operations, you should know what we need to do. that's right! Add the index. php file to the public directory. the file content is:
Note that the PHP end symbol "?>" is not added to the above PHP code ", The main reason for this is: for files that only contain PHP code, the end mark ("?> ") It is better not to exist. PHP does not need an ending symbol. if you do not add an ending symbol, you can avoid adding additional injected content to the end to make the program safer.
In index. php, we initiate a request to bootstrap. php in the library folder. what does the bootstrap. php startup file contain?
The above files can be directly stored in index. php file reference. the reason we do this is to make it easier to manage and expand in the future, therefore, the program that needs to be loaded and run at the beginning should be put into a separate file for reference.
Let's take a look at the config. php file in the config file. The main function of this file is to set some program configuration items and database connections. The main content is:
It should be said that config. php involves not much content, but some basic data settings. let's take a look at how to write shared files shared. php in the library.
$ Var) {if ($ var ===$ GLOBALS [$ key]) {unset ($ GLOBALS [$ key]) ;}}}/ * main request method, main purpose: split the URL request */function callHook () {global $ url; $ urlArray = array (); $ urlArray = explode ("/", $ url ); $ controller = $ urlArray [0]; array_shift ($ urlArray); $ action = $ urlArray [0]; array_shift ($ urlArray); $ queryString = $ urlArray; $ controllerName = $ controller; $ controller = ucwords ($ controller); $ model = rtrim ($ controller,'s '); $ controller. = 'controller'; $ dispatch = new $ Controller ($ model, $ controllerName, $ action); if (int) method_exists ($ controller, $ action )) {call_user_func_array (array ($ dispatch, $ action), $ queryString );} else {/* generate error code */}/* automatically load controller and model */function _ autoload ($ className) {if (file_exists (ROOT. DS. 'library '. DS. strtolower ($ className ). '. class. php ') {require_once (ROOT. DS. 'library '. DS. strtolower ($ className ). '. class. php ');} else if (file_exists (ROOT. DS. 'application '. DS. 'controllers '. DS. strtolower ($ className ). '. php ') {require_once (ROOT. DS. 'application '. DS. 'controllers '. DS. strtolower ($ className ). '. php ');} else if (file_exists (ROOT. DS. 'application '. DS. 'models '. DS. strtolower ($ className ). '. php ') {require_once (ROOT. DS. 'application '. DS. 'models '. DS. strtolower ($ className ). '. php ');} else {/* generate error code */} setReporting (); removeMagicQuotes (); unregisterGlobals (); callHook ();
The next operation is to create the base class required by the program in the library, including the base class of the controller, model, and view.
The new controller base class is controller. class. php. The main function of the controller is General scheduling. the specific content is as follows:
_controller = $controller; $this->_action = $action; $this->_model = $model; $this->$model =& new $model; $this->_template =& new Template($controller,$action); } function set($name,$value) { $this->_template->set($name,$value); } function __destruct() { $this->_template->render(); } }
Create a controller base class as model. class. php. considering that the model needs to process the database, you can create a database base class sqlquery. class. php: The model inherits sqlquery. class. php.
Create sqlquery. class. php with the following code:
_ DbHandle = @ mysql_connect ($ address, $ account, $ pwd); if ($ this-> _ dbHandle! = 0) {if (mysql_select_db ($ name, $ this-> _ dbHandle) {return 1 ;}else {return 0 ;}} else {return 0 ;}} /** interrupt database connection **/function disconnect () {if (@ mysql_close ($ this-> _ dbHandle )! = 0) {return 1;} else {return 0;}/** query all data table content **/function selectAll () {$ query = 'select * from ''. $ this-> _ table. '''; return $ this-> query ($ query) ;}/ ** query the specified column content in a data table **/function select ($ id) {$ query = 'select * from ''. $ this-> _ table. ''Where 'id' = \''. mysql_real_escape_string ($ id ). '\ ''; return $ this-> query ($ query, 1);}/** custom SQL query statement **/function query ($ query, $ singleResult = 0) {$ this-> _ result = mysql_query ($ query, $ this-> _ dbHandle); if (preg_match ("/select/I ", $ query) {$ result = array (); $ table = array (); $ field = array (); $ tempResults = array (); $ numOfFields = mysql_num_fields ($ this-> _ result); for ($ I = 0; $ I <$ numOfFields; ++ $ I) {array_push ($ table, mysql_field_table ($ this-> _ result, $ I); array_push ($ field, mysql_field_name ($ this-> _ result, $ I ));} while ($ row = mysql_fetch_row ($ this-> _ result) {for ($ I = 0; $ I <$ numOfFields; ++ $ I) {$ table [$ I] = trim (ucfirst ($ table [$ I]), "s "); $ tempResults [$ table [$ I] [$ field [$ I] = $ row [$ I];} if ($ singleResult = 1) {mysql_free_result ($ this-> _ result); return $ tempResults;} array_push ($ result, $ tempResults);} mysql_free_result ($ this-> _ result ); return ($ result) ;}/ ** number of returned result set rows **/function getNumRows () {return mysql_num_rows ($ this-> _ result );} /** release result set memory **/function freeResult () {mysql_free_result ($ this-> _ result );} /** return MySQL operation error message **/function getError () {return mysql_error ($ this-> _ dbHandle );}}
Create model. class. php with the following code:
connect(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME); $this->_model = get_class($this); $this->_table = strtolower($this->_model)."s"; } function __destruct() { } }
Create a View base class as template. class. php. the code is as follows:
_ Controller = $ controller; $ this-> _ action = $ action;}/* set variable */function set ($ name, $ value) {$ this-> variables [$ name] = $ value;}/* Display template */function render () {extract ($ this-> variables ); if (file_exists (ROOT. DS. 'application '. DS. 'view '. DS. $ this-> _ controller. DS. 'header. php ') {include (ROOT. DS. 'application '. DS. 'view '. DS. $ this-> _ controller. DS. 'header. php ');} else {include (ROOT. DS. 'application '. DS. 'view '. DS. 'header. php ');} include (ROOT. DS. 'application '. DS. 'view '. DS. $ this-> _ controller. DS. $ this-> _ action. '. php '); if (file_exists (ROOT. DS. 'application '. DS. 'view '. DS. $ this-> _ controller. DS. 'footer. php ') {include (ROOT. DS. 'application '. DS. 'view '. DS. $ this-> _ controller. DS. 'footer. php ');} else {include (ROOT. DS. 'application '. DS. 'view '. DS. 'footer. php ');}}}
After completing the above operations, basically the entire MVC framework has come out. now we should make our site. The website we want to do is actually very simple, a ToDo program.
First, create a site controller class named ItemsController. php under our/application/controller/Directory. the content is:
set('title',$name.' - My Todo List App'); $this->set('todo',$this->Item->select($id)); } function viewall() { $this->set('title','All Items - My Todo List App'); $this->set('todo',$this->Item->selectAll()); } function add() { $todo = $_POST['todo']; $this->set('title','Success - My Todo List App'); $this->set('todo',$this->Item->query('insert into items (item_name) values (\''.mysql_real_escape_string($todo).'\')')); } function delete($id) { $this->set('title','Success - My Todo List App'); $this->set('todo',$this->Item->query('delete from items where id = \''.mysql_real_escape_string($id).'\'')); } }
Next, we will first create a site model. under our/application/Model/directory, we will first create a site model class as Item, and the content will inherit the Model directly. the code is as follows:
The last step is to set the view part of our site. now we create an items folder under the/application/views/directory, and then create a file with the same Action as the controller in the items folder, view. php, viewall. php, add. php, delete. php, considering that such a page may need to share the header and the end of the page, create another two files named header. php, footer. php. the code for each file is as follows:
View. php file: view a single transaction to be processed
">Delete this item
Viewall. php file: View all pending transactions
/
">
Add. php file: add a transaction to be processed
Todo successfully added. Click here to go back.
Delete. php file: delete a transaction
Todo successfully deleted. Click here to go back.
Header. php: header file
<?php echo $title?>My Todo-List App
Footer. php: footer file
Of course, another essential operation is to create a table in the data. the specific code is as follows:
CREATE TABLE IF NOT EXISTS `items` ( `id` int(11) NOT NULL AUTO_INCREMENT, `item_name` varchar(255) NOT NULL, PRIMARY KEY (`id`)) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=17 ;
So far, a website developed using MVC has been developed. now you can access http: // localhost/todo/items/viewall? View the new site.