type
Post
status
Published
date
May 24, 2015
slug
create-a-php-framework
summary
个人觉得徒手写一个PHP框架是帮助我们了解MVC架构的好办法,同时对PHP的资源调度以及代码组织都是一个很好的锻炼。
tags
PHP
category
技术分享
icon
password
Property
Dec 25, 2022 09:20 AM

开始

首先我们建立基本的文件夹结构,如下:
application ——controller ——model ——view system index.php
application是项目的目录,而system不用说就是框架文件的目录了。 index.php 是我们所有请求的入口,我们规定通过如下的url来调用controllerlocalhost/index.php?c=controller&a=action&param=123

设置index.php 入口以及路由

因为所有的请求都是通过index.php发起的,因此我们需要在index.php里面进行一些初始化的设置:
define('BASE_ROOT', dirname(__FILE__) . DIRECTORY_SEPARATOR); define('APP_ROOT', BASE_ROOT . 'application' . DIRECTORY_SEPARATOR);
因为我们规定url参数中的c是控制器名,a是方法名,因此index.php中需要一个路由函数去活取这两个参数:
define('BASE_ROOT', dirname(__FILE__) . DIRECTORY_SEPARATOR); define('APP_ROOT', BASE_ROOT . 'application' . DIRECTORY_SEPARATOR); function route(){ $c = isset($_GET['c'])?$_GET['c']:'index'; $a = isset($_GET['a'])?$_GET['a']:'index'; $r['c']=ucfirst(strtolower(trim($c))); $r['a']=strtolower(trim($a)); return $r; } $routeArr = route(); $controller=$routeArr['c']; $action=$routeArr['a'];
获取到了需要实例化的controller以后,就可以进行相关操作了:
define('BASE_ROOT', dirname(__FILE__) . DIRECTORY_SEPARATOR); define('APP_ROOT', BASE_ROOT . 'application' . DIRECTORY_SEPARATOR); function route(){ $c = isset($_GET['c'])?$_GET['c']:'index'; $a = isset($_GET['a'])?$_GET['a']:'index'; $r['c']=ucfirst(strtolower(trim($c))); $r['a']=strtolower(trim($a)); return $r; } $routeArr = route(); $controller=$routeArr['c']; $action=$routeArr['a']; //根据route的参数加载所需的文件 if (file_exists(APP_ROOT . 'controller/' . $controller.'Controller.php' )){ require_once APP_ROOT . 'controller/' . $controller.'Controller.php'; $obj=new $controller(); if (method_exists($obj,$action)){ $obj->$action(); }else{ die('func not exist'); } }else{ die('file not exist'); }

创建测试控制器

我们在controller文件夹里面创建一个 IndexController.php 文件:
class IndexController{ public function test(){ echo 'test data'; } }
试一试 localhost/index.php?c=index&a=test ,不出意外就能得到test data 了。

提取父类控制器

光是这样肯定是不够的,因为我们需要在controller里面连接model,调用模板,加载各种工具类等。因此我们需要一个带一些公用方法的 父类,这个父类可以被所有的controller继承。
我们创建一个controller.php文件:
class controller { //打印的方法 public function dump($data){ echo '<p>'; print_r($data); echo '</p>'; die; } }
这样一个简单的父类就完成了,里面带了一个很常用的格式化打印数据的方法。那么这个父类我们放在哪里呢? 最简单的方法就是放在 application/controller文件夹里面了,但是一般来说application文件夹是用来放我们项目本身的代码的,框架的代码我们最好放在 system 文件夹里面,然后通过__autoload() 函数自动调用。
我们可以在index.php 里面添加这个函数:
function __autoload($className){ if(file_exists(BASE_ROOT . 'system/' . $className . '.php')){ require_once BASE_ROOT . 'system/' . $className . '.php'; } }
接下来我们就能在项目的controller继承这个父类了:
class IndexController extends Controller { public function test(){ $this->dump('test data'); } }

Model

接下来我们在application文件夹下面创建model文件夹,用来存放模型。那怎么通过controller来调用model?自然就是通过父类自带 的方法了。我们在controller.php里面添加一个方法:
public function model($modelName){ $modelFile = $modelName . 'Model'; return new $modelFile(); }
单是这样还不行,因为php并不知道我们试图实例化的这个model文件在哪里,因此我们需要通过__autoload()函数告诉PHP:
function __autoload($className){ if(file_exists(BASE_ROOT . 'system/' . $className . '.php')){ require_once BASE_ROOT . 'system/' . $className . '.php'; }elseif(file_exists(APP_ROOT . 'model/' . $className . '.php')){ require_once APP_ROOT . 'model/' . $className . '.php'; } }
然后我们就可以写一个测试用的TestModel.php 了:
class TestModel { public function findData(){ return 'model data'; } }
试着在TestController.php 里面调用看看:
class IndexController extends Controller { public function test(){ $testModel = $this->model('Test'); echo $testModel->findData(); //输出 model data; } }

连接数据库

但是现在的model是无法连接数据库的,这样的model就是个废物。但是在每一个model里面写连接数据库的方法是很蠢的,最好的 方法就是通过父类的model连接数据库,其他model继承父类就好了。
和controller.php相同,我们在sysytem文件夹下创建一个model.php
class model { protected $_db; public function __construct(){ $this->_db=new mysqli('localhost', 'root','123456', 'myphp'); if(mysqli_connect_errno()){ echo 'error...'.mysqli_connect_errno(); } } public function query($sql){ $result=$this->_db->query($sql); if($result->num_rows){ while ($row = $result->fetch_assoc()) { $myRow[] = $row; } return $myRow; } } }
自然我们所有的model都继承这个父类model:
class TestModel extends Model { // other code...... }
让我们在本地建立一个myphp数据库,再新建一个user表,格式如下:
id
name
age
1
zhang
20
2
shao
21
3
wang
22
让我们写一个UserController连接UserModel查找数据,所以我们要这么做:
application/controller 文件夹下面创建UserController.php,内容如下:
class UserController extends Controller { public function user(){ $id = $_GET['id']; $userModel = $this->model('User'); $user = $userModel->getUser($id); $this->dump($user); } }
application/model 文件夹下面创建UserModel.php,内容如下:
class UserModel extends Model { public function getUser($id){ $sql = 'select * from user where id ='.$id; $data = $this->query($sql); return $data; } }
试着通过localhost/index.php?c=user&a=user&id=1 请求看看吧!
PHP 中 session_name 包含半角句号时引发的问题我被裁员了!2022年年终总结

杂鱼
杂鱼
菜鸟程序员