[转]1小时内打造你自己的PHP MVC框架

简介

MVC框架在现在的开发中相当流行,不论你使用的是JAVA,C#,PHP或者IOS,你肯定都会选择一款框架。虽然不能保证100%的开发语言都会使用框架,但是在PHP社区当中拥有*多数量的MVC框架。今天你或许还在使用Zend,明天你换了另一个项目也许就会转投Yii,Laravel或者CakePHP的怀抱。如果你刚开始使用一种框架,当你看它的源码的时候你会觉得一头雾水,是的,这些框架都很复杂。因为这些流行的框架并不是短时间之内就写出来就发行的,它们都是经过一遍又一遍的编写和测试加上不断的更新函数库才有了今天得模样。所以就我的经验来看,了解MVC框架的设计核心理念是很有必要的,不然你就会感觉在每一次使用一个新的框架的时候一遍又一遍的从头学习。

所以*好的理解MVC的方法就是写一个你自己的MVC框架。在这篇文章中,我将会向你展示如何构建一个自己的MVC框架。

MVC架构模式

M: Model-模型

V: View-视图

C: Controller-控制器

MVC的关键概念就是从视图层分发业务逻辑。首先解释以下HTTP的请求和相应是如何工作的。例如,我们有一个商城网站,然后我们想要添加一个商品,那么*简单的一个URL就会是像下面这个样子:

http://bestshop.com/index.php?p=admin&c=goods&a=add

http://bestshop.com就是主域名或者基础URL;

p=admin 意味着处在管理模块,,或者是系统的后台模块。同时我们肯定也拥有前台模块,前台模块供所有用户访问(本例中, 它是p=public)

c=goods&a=add 意思是URL请求的是goods控制器里的add方法。

前台控制器设计

在上面的例子中index.php中是什么?在PHP框架中它被称为入口文件。这个文件通常都被命名为index.php,当然你也可以给它别的命名。这个index.php的*主要的作用就是作为HTTP请求的唯一入口文件,这样无论你的URL请求什么资源,它都必须通过这个Index.php来请求。你可能要问为什么,它是如何做到的?PHP中的前端控制器用到了Apache服务器的分布式配置.htaccess实现的。在这个文件中,我们可以使用重写模块告诉Apache服务器重定向到我们的index.php入口文件,就像下面这样:

<IfModule mod_rewrite.c>

   Options +FollowSymLinks

   RewriteEngine on

   # Send request via index.php

   RewriteCond %{REQUEST_FILENAME} !-f

   RewriteCond %{REQUEST_FILENAME} !-d

   RewriteRule ^(.*)$ index.php/$1 [L]

</IfModule>

这个配置文件非常有用,还有当你重写这个配置文件的时候你不需要重启Apache。但是当你修改Apache的其他配置文件的时候你都需要重启Apache才能生效,因为Apache只有在启动的时候才会读取这些配置文件。

同时,index.php还会进行框架的初始化并且分发路由请求给对应的控制器和方法。

我们的MVC目录结构

现在让我们开始创建我们的框架目录结构。我们你可以随便先建立一个文件夹,命名为你项目的名称,比如:/bestshop。在这个文件夹下你需要建立下面的文件夹:

/application-存放web应用程序目录

/framework-存放框架文件目录

/public-存放所有的公共的静态资源,比如HTML文件,CSS文件和jJS文件。

index.php-唯一入口文件

然后在application文件夹下再建立下一级的目录

/config-存放应用的配置文件

/controllers-应用的控制器类

/model-应用的模型类

/view-应用的视图文件

现在在application/controllers文件夹下,我们还需要创建两个文件夹,一个frontend,一个backend:

同样的,在view下也建立frontend和backend文件夹:

就像你看到的,在application的controllers和view下面建立了backen和frontend文件夹,就像我们的用用有前台和后台功能一样。但是为什么不在model下也这样做呢?

Well, the reason here is, normally for a web app:是因为一般在我们的应用中,前台和后台其实是可以看做是两个“网站的”,但是CRUD操作的是同一个数据库,这就是问什么管理员更新了货物的价格的时候,前台用户可以马上看到价格的变化,因为前台和后台是共享一个数据库(表)的。所以在model中没必要再去建立两个文件夹。

:现在让我们回到framework文件夹中,一些框架的文件夹命名会用框架的名字命名,比如"symfony"。在framework中让我们快速建立下面的子目录:

/core-框架核心文件目录

/database-数据库目录(比如数据库启动类)

/helpers-辅助函数目录

/libraries-类库目录

现在进入public文件夹,建立下面的目录:

/css-存放css文件

/images-存放图片文件

/js-存放js文件

/uploads-存放上传的文件

OK。到目前为止这就是我们这个迷你的MVC框架的目录结构了!

框架核心类

现在在framework/core下建立一个Framework.class.php的文件。写入以下代码:

 1 // framework/core/Framework.class.php
 2
 3 class Framework {
 4
 5
 6    public static function run() {
 7
 8        echo "run()";
 9
10    }

我们创建了一个静态方法run(),现在让我们通过入口文件index.php测试一下:

1 <?php
2
3
4 require "framework/core/Framework.class.php";
5
6
7 Framework::run();

你可以在你的浏览器里访问index.php看到结果。通常这个静态方法被命名为run()或者bootstrap()。在这个方法中,我们要做3件*主要的事情:

 1 class Framework {
 2
 3
 4    public static function run() {
 5
 6 //        echo "run()";
 7
 8        self::init();
 9
10        self::autoload();
11
12        self::dispatch();
13
14    }
15
16
17    private static function init() {
18
19    }
20
21
22    private static function autoload() {
23
24
25    }
26
27
28    private static function dispatch() {
29
30
31    }
32
33 }

初始化

init()方法:

 1 // Initialization
 2
 3 private static function init() {
 4
 5     // Define path constants
 6
 7     define("DS", DIRECTORY_SEPARATOR);
 8
 9     define("ROOT", getcwd() . DS);
10
11     define("APP_PATH", ROOT . ‘application‘ . DS);
12
13     define("FRAMEWORK_PATH", ROOT . "framework" . DS);
14
15     define("PUBLIC_PATH", ROOT . "public" . DS);
16
17
18     define("CONFIG_PATH", APP_PATH . "config" . DS);
19
20     define("CONTROLLER_PATH", APP_PATH . "controllers" . DS);
21
22     define("MODEL_PATH", APP_PATH . "models" . DS);
23
24     define("VIEW_PATH", APP_PATH . "views" . DS);
25
26
27     define("CORE_PATH", FRAMEWORK_PATH . "core" . DS);
28
29     define(‘DB_PATH‘, FRAMEWORK_PATH . "database" . DS);
30
31     define("LIB_PATH", FRAMEWORK_PATH . "libraries" . DS);
32
33     define("HELPER_PATH", FRAMEWORK_PATH . "helpers" . DS);
34
35     define("UPLOAD_PATH", PUBLIC_PATH . "uploads" . DS);
36
37
38     // Define platform, controller, action, for example:
39
40     // index.php?p=admin&c=Goods&a=add
41
42     define("PLATFORM", isset($_REQUEST[‘p‘]) ? $_REQUEST[‘p‘] : ‘home‘);
43
44     define("CONTROLLER", isset($_REQUEST[‘c‘]) ? $_REQUEST[‘c‘] : ‘Index‘);
45
46     define("ACTION", isset($_REQUEST[‘a‘]) ? $_REQUEST[‘a‘] : ‘index‘);
47
48
49     define("CURR_CONTROLLER_PATH", CONTROLLER_PATH . PLATFORM . DS);
50
51     define("CURR_VIEW_PATH", VIEW_PATH . PLATFORM . DS);
52
53
54     // Load core classes
55
56     require CORE_PATH . "Controller.class.php";
57
58     require CORE_PATH . "Loader.class.php";
59
60     require DB_PATH . "Mysql.class.php";
61
62     require CORE_PATH . "Model.class.php";
63
64
65     // Load configuration file
66
67     $GLOBALS[‘config‘] = include CONFIG_PATH . "config.php";
68
69
70     // Start session
71
72     session_start();
73
74 }

在注释中你可以看到每一步的目的。

自动加载

在项目中,我们不想在脚本中想使用一个类的时候手动的去include或者require加载,这就是为什么PHP MVC框架都有自动加载的功能。例如,在symfony中,如果你想要加载lib下的类,它将会被自动引入。很神奇是吧?现在让我们在自己的框架中加入自动加载的功能。

这里我们要用的PHP中的自带函数spl_autoload_register:

 1 // Autoloading
 2
 3 private static function autoload(){
 4
 5     spl_autoload_register(array(__CLASS__,‘load‘));
 6
 7 }
 8
 9
10 // Define a custom load method
11
12 private static function load($classname){
13
14
15     // Here simply autoload app&rsquo;s controller and model classes
16
17     if (substr($classname, -10) == "Controller"){
18
19         // Controller
20
21         require_once CURR_CONTROLLER_PATH . "$classname.class.php";
22
23     } elseif (substr($classname, -5) == "Model"){
24
25         // Model
26
27         require_once  MODEL_PATH . "$classname.class.php";
28
29     }
30
31 }

每一个框架都有自己的命名规则,我们的也不例外。对于一个控制器类,它需要被命名成类似xxxController.class.php,对于一个模型类,需要被命名成xxModel.class.php。为什么在使用一个框架的时候你需要遵守它的命名规则呢?自动加载就是一条原因。

路由/分发

// Routing and dispatching

private static function dispatch(){

    // Instantiate the controller class and call its action method

    $controller_name = CONTROLLER . "Controller";

    $action_name = ACTION . "Action";

    $controller = new $controller_name;

    $controller->$action_name();

}

在这步中,index.php将会分发请求到对应的Controller::Aciton()方法中。

基础Controller类

通常在框架的核心类中都有一个基础的控制器。在symfony中,被称为sfAction;在iOS中,被称为UIViewController。在这里我们命名为Controller,在framework/core下建立Controller.class.php

 1 <?php
 2
 3 // Base Controller
 4
 5 class Controller{
 6
 7     // Base Controller has a property called $loader, it is an instance of Loader class(introduced later)
 8
 9     protected $loader;
10
11
12     public function __construct(){
13
14         $this->loader = new Loader();
15
16     }
17
18
19     public function redirect($url,$message,$wait = 0){
20
21         if ($wait == 0){
22
23             header("Location:$url");
24
25         } else {
26
27             include CURR_VIEW_PATH . "message.html";
28
29         }
30
31
32         exit;
33
34     }
35
36 }
37 基础控制器有一个变量$loader,它是Loader类的实例化(后面介绍)。准确的说,$this->loader是一个变量指向了被实例化的Load类。在这里我不过多的讨论,但是这的确是一个非常关键的概念。我遇到过一些PHP开发者相信在这个语句之后:
38
39 $this->loader = new Loader();
40 $this->load是一个对象。不,它只是一个引用。这是从Java中开始使用的,在Java之前,在C++和Objective C中被称为指针。引用是个封装的指针类型。比如,在iOS(O-C)中,我们创建了一个对象:
41
42 UIButton *btn = [UIButton alloc] init];

加载类

在framework.class.php中,我们已经封装好了应用的控制器和模型的自动加载。但是如何自动加载在framework目录中的类呢?现在我们可以新建一个Loader类,它会加载framework目录中的类和函数。当我们加载framework类时,只需要调用这个Loader类中的方法即可。

 1 class Loader{
 2
 3     // Load library classes
 4
 5     public function library($lib){
 6
 7         include LIB_PATH . "$lib.class.php";
 8
 9     }
10
11
12     // loader helper functions. Naming conversion is xxx_helper.php;
13
14     public function helper($helper){
15
16         include HELPER_PATH . "{$helper}_helper.php";
17
18     }
19
20 }

封装模型

我们需要下面两个类来封装基础Model类:

Mysql.class.php - 在framework/database下建立,它封装了数据库的链接和一些基本查询方法。

Model.class.php - framework/core下建立,基础模型类,封装所有的CRUD方法。

Mysql.class.php :

  1 <?php
  2
  3 /**
  4
  5 *================================================================
  6
  7 *framework/database/Mysql.class.php
  8
  9 *Database operation class
 10
 11 *================================================================
 12
 13 */
 14
 15 class Mysql{
 16
 17     protected $conn = false;  //DB connection resources
 18
 19     protected $sql;           //sql statement
 20
 21
 22
 23     /**
 24
 25      * Constructor, to connect to database, select database and set charset
 26
 27      * @param $config string configuration array
 28
 29      */
 30
 31     public function __construct($config = array()){
 32
 33         $host = isset($config[‘host‘])? $config[‘host‘] : ‘localhost‘;
 34
 35         $user = isset($config[‘user‘])? $config[‘user‘] : ‘root‘;
 36
 37         $password = isset($config[‘password‘])? $config[‘password‘] : ‘‘;
 38
 39         $dbname = isset($config[‘dbname‘])? $config[‘dbname‘] : ‘‘;
 40
 41         $port = isset($config[‘port‘])? $config[‘port‘] : ‘3306‘;
 42
 43         $charset = isset($config[‘charset‘])? $config[‘charset‘] : ‘3306‘;
 44
 45
 46
 47         $this->conn = mysql_connect("$host:$port",$user,$password) or die(‘Database connection error‘);
 48
 49         mysql_select_db($dbname) or die(‘Database selection error‘);
 50
 51         $this->setChar($charset);
 52
 53     }
 54
 55     /**
 56
 57      * Set charset
 58
 59      * @access private
 60
 61      * @param $charset string charset
 62
 63      */
 64
 65     private function setChar($charest){
 66
 67         $sql = ‘set names ‘.$charest;
 68
 69         $this->query($sql);
 70
 71     }
 72
 73     /**
 74
 75      * Execute SQL statement
 76
 77      * @access public
 78
 79      * @param $sql string SQL query statement
 80
 81      * @return $result,if succeed, return resrouces; if fail return error message and exit
 82
 83      */
 84
 85     public function query($sql){
 86
 87         $this->sql = $sql;
 88
 89         // Write SQL statement into log
 90
 91         $str = $sql . "  [". date("Y-m-d H:i:s") ."]" . PHP_EOL;
 92
 93         file_put_contents("log.txt", $str,FILE_APPEND);
 94
 95         $result = mysql_query($this->sql,$this->conn);
 96
 97
 98
 99         if (! $result) {
100
101             die($this->errno().‘:‘.$this->error().‘<br />Error SQL statement is ‘.$this->sql.‘<br />‘);
102
103         }
104
105         return $result;
106
107     }
108
109     /**
110
111      * Get the first column of the first record
112
113      * @access public
114
115      * @param $sql string SQL query statement
116
117      * @return return the value of this column
118
119      */
120
121     public function getOne($sql){
122
123         $result = $this->query($sql);
124
125         $row = mysql_fetch_row($result);
126
127         if ($row) {
128
129             return $row[0];
130
131         } else {
132
133             return false;
134
135         }
136
137     }
138
139     /**
140
141      * Get one record
142
143      * @access public
144
145      * @param $sql SQL query statement
146
147      * @return array associative array
148
149      */
150
151     public function getRow($sql){
152
153         if ($result = $this->query($sql)) {
154
155             $row = mysql_fetch_assoc($result);
156
157             return $row;
158
159         } else {
160
161             return false;
162
163         }
164
165     }
166
167     /**
168
169      * Get all records
170
171      * @access public
172
173      * @param $sql SQL query statement
174
175      * @return $list an 2D array containing all result records
176
177      */
178
179     public function getAll($sql){
180
181         $result = $this->query($sql);
182
183         $list = array();
184
185         while ($row = mysql_fetch_assoc($result)){
186
187             $list[] = $row;
188
189         }
190
191         return $list;
192
193     }
194
195     /**
196
197      * Get the value of a column
198
199      * @access public
200
201      * @param $sql string SQL query statement
202
203      * @return $list array an array of the value of this column
204
205      */
206
207     public function getCol($sql){
208
209         $result = $this->query($sql);
210
211         $list = array();
212
213         while ($row = mysql_fetch_row($result)) {
214
215             $list[] = $row[0];
216
217         }
218
219         return $list;
220
221     }
222
223
224
225
226     /**
227
228      * Get last insert id
229
230      */
231
232     public function getInsertId(){
233
234         return mysql_insert_id($this->conn);
235
236     }
237
238     /**
239
240      * Get error number
241
242      * @access private
243
244      * @return error number
245
246      */
247
248     public function errno(){
249
250         return mysql_errno($this->conn);
251
252     }
253
254     /**
255
256      * Get error message
257
258      * @access private
259
260      * @return error message
261
262      */
263
264     public function error(){
265
266         return mysql_error($this->conn);
267
268     }
269
270 }
271  

Model.class.php:

  1 <?php
  2
  3 // framework/core/Model.class.php
  4
  5 // Base Model Class
  6
  7 class Model{
  8
  9     protected $db; //database connection object
 10
 11     protected $table; //table name
 12
 13     protected $fields = array();  //fields list
 14
 15     public function __construct($table){
 16
 17         $dbconfig[‘host‘] = $GLOBALS[‘config‘][‘host‘];
 18
 19         $dbconfig[‘user‘] = $GLOBALS[‘config‘][‘user‘];
 20
 21         $dbconfig[‘password‘] = $GLOBALS[‘config‘][‘password‘];
 22
 23         $dbconfig[‘dbname‘] = $GLOBALS[‘config‘][‘dbname‘];
 24
 25         $dbconfig[‘port‘] = $GLOBALS[‘config‘][‘port‘];
 26
 27         $dbconfig[‘charset‘] = $GLOBALS[‘config‘][‘charset‘];
 28
 29
 30
 31         $this->db = new Mysql($dbconfig);
 32
 33         $this->table = $GLOBALS[‘config‘][‘prefix‘] . $table;
 34
 35         $this->getFields();
 36
 37     }
 38
 39     /**
 40
 41      * Get the list of table fields
 42
 43      *
 44
 45      */
 46
 47     private function getFields(){
 48
 49         $sql = "DESC ". $this->table;
 50
 51         $result = $this->db->getAll($sql);
 52
 53         foreach ($result as $v) {
 54
 55             $this->fields[] = $v[‘Field‘];
 56
 57             if ($v[‘Key‘] == ‘PRI‘) {
 58
 59                 // If there is PK, save it in $pk
 60
 61                 $pk = $v[‘Field‘];
 62
 63             }
 64
 65         }
 66
 67         // If there is PK, add it into fields list
 68
 69         if (isset($pk)) {
 70
 71             $this->fields[‘pk‘] = $pk;
 72
 73         }
 74
 75     }
 76
 77     /**
 78
 79      * Insert records
 80
 81      * @access public
 82
 83      * @param $list array associative array
 84
 85      * @return mixed If succeed return inserted record id, else return false
 86
 87      */
 88
 89     public function insert($list){
 90
 91         $field_list = ‘‘;  //field list string
 92
 93         $value_list = ‘‘;  //value list string
 94
 95         foreach ($list as $k => $v) {
 96
 97             if (in_array($k, $this->fields)) {
 98
 99                 $field_list .= "`".$k."`" . ‘,‘;
100
101                 $value_list .= "‘".$v."‘" . ‘,‘;
102
103             }
104
105         }
106
107         // Trim the comma on the right
108
109         $field_list = rtrim($field_list,‘,‘);
110
111         $value_list = rtrim($value_list,‘,‘);
112
113         // Construct sql statement
114
115         $sql = "INSERT INTO `{$this->table}` ({$field_list}) VALUES ($value_list)";
116
117         if ($this->db->query($sql)) {
118
119             // Insert succeed, return the last record&rsquo;s id
120
121             return $this->db->getInsertId();
122
123             //return true;
124
125         } else {
126
127             // Insert fail, return false
128
129             return false;
130
131         }
132
133
134
135     }
136
137     /**
138
139      * Update records
140
141      * @access public
142
143      * @param $list array associative array needs to be updated
144
145      * @return mixed If succeed return the count of affected rows, else return false
146
147      */
148
149     public function update($list){
150
151         $uplist = ‘‘; //update fields
152
153         $where = 0;   //update condition, default is 0
154
155         foreach ($list as $k => $v) {
156
157             if (in_array($k, $this->fields)) {
158
159                 if ($k == $this->fields[‘pk‘]) {
160
161                     // If it&rsquo;s PK, construct where condition
162
163                     $where = "`$k`=$v";
164
165                 } else {
166
167                     // If not PK, construct update list
168
169                     $uplist .= "`$k`=‘$v‘".",";
170
171                 }
172
173             }
174
175         }
176
177         // Trim comma on the right of update list
178
179         $uplist = rtrim($uplist,‘,‘);
180
181         // Construct SQL statement
182
183         $sql = "UPDATE `{$this->table}` SET {$uplist} WHERE {$where}";
184
185
186
187         if ($this->db->query($sql)) {
188
189             // If succeed, return the count of affected rows
190
191             if ($rows = mysql_affected_rows()) {
192
193                 // Has count of affected rows
194
195                 return $rows;
196
197             } else {
198
199                 // No count of affected rows, hence no update operation
200
201                 return false;
202
203             }
204
205         } else {
206
207             // If fail, return false
208
209             return false;
210
211         }
212
213
214
215     }
216
217     /**
218
219      * Delete records
220
221      * @access public
222
223      * @param $pk mixed could be an int or an array
224
225      * @return mixed If succeed, return the count of deleted records, if fail, return false
226
227      */
228
229     public function delete($pk){
230
231         $where = 0; //condition string
232
233         //Check if $pk is a single value or array, and construct where condition accordingly
234
235         if (is_array($pk)) {
236
237             // array
238
239             $where = "`{$this->fields[‘pk‘]}` in (".implode(‘,‘, $pk).")";
240
241         } else {
242
243             // single value
244
245             $where = "`{$this->fields[‘pk‘]}`=$pk";
246
247         }
248
249         // Construct SQL statement
250
251         $sql = "DELETE FROM `{$this->table}` WHERE $where";
252
253         if ($this->db->query($sql)) {
254
255             // If succeed, return the count of affected rows
256
257             if ($rows = mysql_affected_rows()) {
258
259                 // Has count of affected rows
260
261                 return $rows;
262
263             } else {
264
265                 // No count of affected rows, hence no delete operation
266
267                 return false;
268
269             }
270
271         } else {
272
273             // If fail, return false
274
275             return false;
276
277         }
278
279     }
280
281     /**
282
283      * Get info based on PK
284
285      * @param $pk int Primary Key
286
287      * @return array an array of single record
288
289      */
290
291     public function selectByPk($pk){
292
293         $sql = "select * from `{$this->table}` where `{$this->fields[‘pk‘]}`=$pk";
294
295         return $this->db->getRow($sql);
296
297     }
298
299     /**
300
301      * Get the count of all records
302
303      *
304
305      */
306
307     public function total(){
308
309         $sql = "select count(*) from {$this->table}";
310
311         return $this->db->getOne($sql);
312
313     }
314
315     /**
316
317      * Get info of pagination
318
319      * @param $offset int offset value
320
321      * @param $limit int number of records of each fetch
322
323      * @param $where string where condition,default is empty
324
325      */
326
327     public function pageRows($offset, $limit,$where = ‘‘){
328
329         if (empty($where)){
330
331             $sql = "select * from {$this->table} limit $offset, $limit";
332
333         } else {
334
335             $sql = "select * from {$this->table}  where $where limit $offset, $limit";
336
337         }
338
339
340
341         return $this->db->getAll($sql);
342
343     }
344
345 }
346  

现在我们可以在application下创建一个User模型,对应数据库里的user表:

 1 <?php
 2
 3 // application/models/UserModel.class.php
 4
 5 class UserModel extends Model{
 6
 7
 8     public function getUsers(){
 9
10         $sql = "select * from $this->table";
11
12         $users = $this->db->getAll($sql);
13
14         return $users;
15
16     }
17
18 }

后台的indexController:

 1 <?php
 2
 3 // application/controllers/admin/IndexController.class.php
 4
 5
 6 class IndexController extends BaseController{
 7
 8     public function mainAction(){
 9
10         include CURR_VIEW_PATH . "main.html";
11
12         // Load Captcha class
13
14         $this->loader->library("Captcha");
15
16         $captcha = new Captcha;
17
18         $captcha->hello();
19
20         $userModel = new UserModel("user");
21
22         $users = $userModel->getUsers();
23
24     }
25
26     public function indexAction(){
27
28                        $userModel = new UserModel("user");
29
30         $users = $userModel->getUsers();
31
32         // Load View template
33
34         include  CURR_VIEW_PATH . "index.html";
35
36     }
37
38     public function menuAction(){
39
40         include CURR_VIEW_PATH . "menu.html";
41
42     }
43
44     public function dragAction(){
45
46         include CURR_VIEW_PATH . "drag.html";
47
48     }
49
50     public function topAction(){
51
52         include CURR_VIEW_PATH . "top.html";
53
54     }
55
56 }

到目前为止,我们后台的index控制器就正常执行了,控制器中实例化了模型类,并且将得到的数据传给了视图中的模板,这样在浏览器中就能看到数据了。

转自:phpchina原创译文  1小时内打造你自己的PHP MVC框架  http://www.phpchina.com/article-40109-1.html

原文链接:http://www.codeproject.com/Articles/1080626/WebControls/

时间: 2024-10-11 11:46:24

[转]1小时内打造你自己的PHP MVC框架的相关文章

简单快速打造你自己的PHP MVC框架

简介 MVC框架在现在的开发中相当流行,不论你使用的是JAVA,C#,PHP或者IOS,你肯定都会选择一款框架.虽然不能保证100%的开发语言都会使用框架,所以最好的理解MVC的方法就是写一个你自己的MVC框架.兄弟连www.lampbrother.net在这篇文章中将会向你展示如何构建一个自己的MVC框架. MVC架构模式 M: Model-模型 V: View-视图 C: Controller-控制器 MVC的关键概念就是从视图层分发业务逻辑.首先解释以下HTTP的请求和相应是如何工作的.例

really?:讲师承诺:24小时内答疑;所有课时永久观看(不提供下载);课件下载

讲师承诺:24小时内答疑:所有课时永久观看(不提供下载):课件下载.看上图,really? 还有,我希望,51CTO学院,开发个客户端.我想平时,可以在我的安卓手机或iPhone上看教程.

(SegWit)隔离见证人在24小时内激活:比特币会如何变化?

海外最新数字货币比特币最新资讯: 什么是隔离见证? 隔离见证(通常简写为SegWit)是对比特币软件提出的一种更新,旨在解决比特币面临的一系列严重问题. SegWit是由比特币长期团队开发的对于Bitcoin Core的拟议更新.Bitcoin Core是当前最受欢迎的比特币标准客户端,由业内大多数企业使用. 最初,该更新旨在解决交易的可扩展性,这也是比特币软件中众所周知的弱点.虽然这种攻击向量对用户来说并不是最具破坏性的,但目前为止已经在多个攻击案例中被利用,因此也就凸显了修补这一漏洞的必要性

找出1小时内占用cpu最多的10个进程的shell脚本

cpu时间是一项重要的资源,有时,我们需要跟踪某个时间内占用cpu周期最多的进程. 在普通的桌面系统或膝上系统中,cpu处于高负荷状态也许不会引发什么问题.但对于需要处理大量请求的服务器来讲,cpu是极其重要的资源. 通过监视某个时期内cpu的使用情况,我们可以找出长期占用cpu的进程并对其进行优化,或调试其它相关问题. 在linux系统中,ps命令用于收集系统中进程的详细信息.这些信息包括cpu使用情况.正在执行的命令.内存使用.进程状态等.记录在一个小时内占用过的cpu的进程,然后通过恰当地

使用Symfony 2在三小时内开发一个寻人平台

简介 Symfony2是一个基于PHP语言的Web开发框架,有着开发速度快.性能高等特点.但Symfony2的学习曲线也比 较陡峭,没有经验的初学者往往需要一些练习才能掌握其特性. 本文通过一个快速开发寻人平台的实例向读者介绍 Symfony2框架的一些核心功能和特点.通过阅读本文,你可以通过一些具体的例子了解Symfony2框架的优秀特性和技术特点 ,从而体会到使用Symfony2框架支持快速网站开发这一优势. 适合人群 本文适用于希望提高PHP语言的开发技术,或者对Symfony2框架有兴趣

【视频】半小时内编写一个贪吃蛇游戏

贪吃蛇编写提纲 致谢: 感谢 Ronnie Mooney ,我是在学习了他的视频后完成这个视频的,你可以在 [C#] Creating a Snake Game - Less than an Hour 找到他的视频(需翻墙,请自备梯子). 编写 Input 静态类 初始化静态变量 private static readonly Hashtable _keys = new Hashtable() 编写方法 public static void ChangeState(Keys key, bool

一小时内完成百万计算任务?

公有云技术日益成熟和稳定,各种服务越来越完善,逐渐被各行业的客户所接受.越来越多的专业计算的客户也开始将目光转向公有云来解决算力不足的问题.想要充分的利用云的优势,高效的完成计算任务,需要从应用优化到底层架构适配一套端到端的解决方案.本期速石科技产品总监张先军将与大家分享速石专业计算云平台如何从各个层面帮助客户多快好省的完成计算任务的. 张先军:速石科技产品总监,超过12年的IT行业经验,曾在EMC,HP, 华为3com任职,熟悉虚拟化和云计算技术,专注于企业级IT产品定义和解决方案设计. 首先

微星极光公众号激活宝——微信公众号48小时内无限制定时推送消息

前言 凡是运营过公众号的人都知道,微信公众号分为订阅号和服务号,订阅号一天群发一次,服务号一月才四次,对于许多运营的公众号来说这次数远远不够用,最近发现微星极光推出了一个新功能:公众号激活宝,通过微信内部接口实现48小时内无限制向用户推送消息的功能 Q1:48小时信息推送可以实现无限制向用户推送消息吗? 答:可以,但是只能对48小时内与公众号互动的粉丝群发信息,这里的互动是指对话,扫码,关注,点菜单,只要满足其中一个动作均算作互动. Q2:48小时信息推送的内容有哪些? 答:没有数量限制地推送文

微信公众号如何查看48小时内客户足迹?48小时后还能查看客户足迹?

不少企业客服人员都在烦恼,每次接待客户都是通过刷新网页的形式进行沟通的.对接客户接待及时性不高,还容易流失高精准粉丝.经常总是忙忙碌碌,却又碌碌无大为,空有忙碌的姿态,然而业绩不好,老板就怀疑我们不努力,不好好干活,没多聊得客户回来成单,结果是因为我们的企业缺乏工具啊啊啊!前提:你得有一个鱼塘软件(还没有的快跟你老板说吧).处理消息有大动作--以往的你:新消息/留言来了,要刷新网页才看得到,稍微一个小动作,就一不小心关闭了网络,又得重新打开,你一脸茫然......浪费时间不说,主要是够折腾.现在