前言

说到写PHP的MVC框架,大家想到的第一个词--“造轮子”,是的,一个还没有深厚功力的程序员,写出的PHP框架肯定不如那些出自大神们之手、经过时间和各种项目考验的框架。但我还是准备并且这么做了,主要是因为:

  • 认为有关PHP的方方面面都了解了,但自己学习PHP的时间还短,基础并不扎实,很多常用函数的参数还偶尔要查手册,而且对于PHP的一些较新的特性如命名空间、反射等只是简单的看过,并没有能实际应用过。
  • PHP的知识多且杂,一个普通的项目往住是业务逻辑代码为主,而框架是一个能把这些知识点能融汇在一起的项目。
  • 在自己写一个框架的时候,也会参考一些我使用过的框架如TP/CI/YII等的源码,在自己看源码时也能帮助自己理解框架,更容易接受以后要使用的框架。

所以说,这次造轮子的目的不是为了造轮子而是为了在造轮子的过程中熟悉其工艺,总结轮子特点,更好的使用轮子。

如果说写一个完整的PHP框架,那需要掌握的PHP知识点非常多,像设计模式、迭代器、事件与钩子等等,还有许多基础知识的灵活应用。我自认为这些还无法完全掌控,所以我的步骤是先自己搭建一个骨架,然后参考借鉴不同的PHP框架的特点,将其慢慢完善。因为工作原因,而且晚上还要补算法、网络等编程基础,PHP框架部分可能只有周末有时间更新,我会在进行框架功能更新之后,总结使用的知识点,更新博文。

首先放上框架的目前源码:GITHUB/zhenbianshu


框架整体

首先自己总结一下PHP的MVC框架的工作流程:

简单来说,它以一个入口文件来接受请求,选择路由,处理请求,返回结果。

当然,几句话总结完的东西实际上要做的工作很多,PHP框架会在每次接受请求时,定义常量,加载配置文件、基础类,根据访问的URL进行逻辑判断,选择对应的(模块)控制器和方法,并且自动加载对应类,处理完请求后,框架会选择并渲染对应的模板文件,以html页面的形式返回响应。在处理逻辑的时候,还要考虑到错误和异常的处理。

1、作为MVC框架,一定要有一个唯一的入口文件来统领全局,所有的访问请求都会首先进入这个入口文件,如我框架根目录的index.php,在里面,我定义了基本文件夹路径,当前环境,并根据当前环境定义错误报告的级别。

2、PHP中加载另外的文件,使用require和include,它们都是将目标文件内容加载到当前文件内,替换掉require或include语句,require是加载进来就执行,而include是加载进来在需要的时候执行,而它们的_once结构都是表示在写多次的时候只执行一次。

3、框架内的配置变量等使用专用的配置文件来保存,这里我仿照了TP里的数组返回法,用了一个compileConf()函数来解析数组,将数组的键定义为常量,值为数组的值。

if (!function_exists('compile_conf')) {
function compileConf($conf) {
foreach ($conf as $key => $val) {
if(is_array($val)){
compileConf($val);
}else{
define($key, $val);
}
}
}
}
compileConf(require_once CONF_PATH.'config.php');

命名空间和自动加载

为什么把命名空间和自动加载放到一块说呢?

在一个PHP项目中,类特别多的时候,如果类名重复的话就会造成混乱,而且相同文件夹内也不能存在同名的文件,所以这时候命名空间和文件夹就搭档出场了。文件夹就是一个一个的盒子,命名空间在我理解就像是一个标签,盒子对应标签。我们定义类时,把各种类用不同的盒子分别装好,并贴上对应的标签。而在自动加载类时,我们根据标签(命名空间)可以很轻易找到对应的盒子(文件夹)然后找到对应的类文件。

而类的自动加载,我们知道的__autoload()魔术函数,它会在你实例化一个当前路径找不到的对象时自动调用,根据传入的类名,在函数体内加载对应的类文件。

现在我们多用spl_autoload_register()函数,它可以注册多个函数来代替__autoload函数的功能,我们传入一个函数名为参数,spl_autoload_register会将这个函数压入栈中,在实例化一个当前路径内找不到的类时,系统将会将函数出栈依次调用,直到实例化成功。

spl_autoload_register('Sqier\Loader::autoLoad');

class Loader {
public static function autoLoad($class) {
//如果有的话,去除类最左侧的\
$class = ltrim($class, '\\');
//获取类的路径全名
$class_path = str_replace('\\', '/', $class) . EXT;
if (file_exists(SYS_PATH . $class_path)) {
include SYS_PATH . $class_path;
return;
}
if (file_exists(APP_PATH . $class_path)) {
include APP_PATH . $class_path;
return;
}
}

现在Loader类还是一个简单的类,待以后慢慢完善。


路由选择

接下来就是路由选择了,其本质是根据当前定义的全局URL模式选择合适的方法来分析传入的URI,加载对应的类,并实现对应的方法。

class Router {
public static $uri; public static function bootstrap() {
self::$uri = $_SERVER['REQUEST_URI'];
switch (URL_MODE) {
case 1: {
self::rBoot();
break;
}
default: {
self::rBoot();
}
}
} public static function rBoot() {
$router = isset($_GET['r']) ? explode('/', $_GET['r']) : [
'index',
'index'
];
$cName = 'Controller\\' . ucfirst($router[0]);
$aName = isset($router[1]) ? strtolower($router[1]) . 'Action' : 'indexAction';
$controller = new $cName();
$controller->$aName();
}
}

这样,我在地址栏输入 zbs.com/index.php?r=index/login 后,系统会自动调用/app/Controller/Index.php下的login方法。完成了这么一个简单的路由。


后续

接下来我会优化现有的工具类,添加显示层,添加数据库类,还会将一些别的框架里非常cool的功能移植进来~

待续...

(转)php自己创建框架的更多相关文章

  1. ALSA driver--PCM实例创建框架

    在介绍PCM 之前,我们先给出创建PCM实例的框架. #include <sound/pcm.h> .... /* hardware definition */ static struct ...

  2. 创建框架链接--frameset的连接方法

    首先看下小编的目录架构 1.html将作为主页面 2.html将作为目录页面,里面有2个目录,分别是目录一和目录二 3.html为目录一将要链接的页面 4.html为目录二将要链接的页面 然后,看下1 ...

  3. ios中创建自己的框架

    如果你是IOS的新手,并有.net开发的背景(就像我一样),你可能到处去找,哪里有dll呢? 其实,IOS平台是使用框架而不是dll,框架里面包含公共头文件和二进制文件.很不幸,XCode并不支持你自 ...

  4. C++反射机制:可变参数模板实现C++反射(使用C++11的新特性--可变模版参数,只根据类的名字(字符串)创建类的实例。在Nebula高性能网络框架中大量应用)

    1. 概要   本文描述一个通过C++可变参数模板实现C++反射机制的方法.该方法非常实用,在Nebula高性能网络框架中大量应用,实现了非常强大的动态加载动态创建功能.Nebula框架在码云的仓库地 ...

  5. MFC - 微软基础类库和框架

    一 MFC的概念和作用 1 什么是MFC?? 全称 Microsoft Foundation Class Library我们称之为微软基础类库 1)从硬盘的存在形式上来说 MFC就是一个库(静/动态库 ...

  6. JavaGUI——设置框架背景颜色和按钮颜色

    import java.awt.Color; import javax.swing.*; public class MyDraw { public static void main(String[] ...

  7. 无线客户端框架设计(2):项目结构的设计(iOS篇)

    本文附带源码:YoungHeart-Chapter-02.zip 在设计任何一个框架之前,都应规划好项目结构. 假定Git作为我们的项目管理工具.我们要建立两个仓库,一个用于存放我们的框架,另一个用于 ...

  8. 十二、EnterpriseFrameWork框架核心类库之与EntLib结合

    从本章开始对框架的讲叙开始进入核心类库的讲解,前面都是对框架外在功能讲解,让人有个整体的概念,知道包含哪些功能与对系统开发有什么帮助.以后多章都是讲解核心类库的,讲解的方式基本按照代码的目录结构,这样 ...

  9. PowerDesigner(二)-项目和框架矩阵(转)

    项目和框架矩阵 项目是PowerDesigner 15的新概念,通过项目系统分析/设计人员可以对模型以及各类文档进行分组.项目也可以包含框架矩阵,以表格的形式体现各个模型之间的关系. 项目和框架矩阵解 ...

随机推荐

  1. javascript选取文档元素

    用指定的id属性 用指定的name属性 用指定的标签名字 用指定的CSS类 匹配指定的CSS选择器 通过ID选取元素 var section1 = document.getElementById(&q ...

  2. praise包--R给你点赞!

    1.praise包干什么的? praise包就一个功能:赞你! 2.praise包怎么搞? 2.1安装 直接安装: install.packages("praise") 从gith ...

  3. Visual Studio: How to change ipch path in Visual Studio 2010 (.sdf, *.opensdf, ...)

    Link: http://stackoverflow.com/questions/4315681/how-to-change-ipch-path-in-visual-studio-2010 引用: T ...

  4. iOS之04-方法的声明和实现

    本次重点学习和理解OC对象方法的声明和定义 代码: /* 计算器类 方法: 1> 返回 π 2> 计算某个整数的平方 3> 计算两个整数的和 */ #import <Found ...

  5. NHibernate 中删除数据的几种方法

    今天下午有人在QQ群上问在NHibernate上如何根据条件删除多条数据,于是我自己就写了些测试代码,并总结了一下NHibernate中删除数据的方式,做个备忘.不过不能保证囊括所有的方式,如果还有别 ...

  6. unity meshrender理解

    网格渲染器,其中unity里面多有的材质在渲染的时候都是会划分成三角形的,所以当添加一些物体的时候,例如3d text的时候,默认添加网格渲染器. 最常用的就是获取材质. 下面是一个利用网格渲染器获得 ...

  7. 图解Storm

    问题导读:1.你认为什么图形可以显示hadoop与storm的区别?(电梯)2.本文是如何形象讲解hadoop与storm的?(离线批量处理.实时流式处理)3.hadoop map/reduce对应s ...

  8. Ext中Grid重新load设置URL

    一.前言    Extjs中grid网格有时候需要重新加载,加载的时候对应不同的URL,什么情况出现:有需要我们在添加附件的时候,添加完成了附件,需要把另一个show添加的数据重新加载到grid中,而 ...

  9. BZOJ 2049 & LCT又一模板

    题意: 自己看...加边删边问联通... SOL: 就加了一个findroot而已... 然而时间还是惨不忍睹...优化全开也才1700ms...膜seter... Code: /*========= ...

  10. 警惕自己,不断学习c++【转】

    每天早上起床看一遍,时刻警惕自己,每天至少要浏览http://www.cplusplus.com 1.把C++当成一门新的语言学习(和C没啥关系!真的.):2.看<Thinking In C++ ...