一、框架整体分析

在实现一个框架之前,我们需要了解这个框架应该达到一个怎样的效果,按照传统框架的思路,大致可以总结出以下这么几条:

1.实现MVC架构,将控制、逻辑、视图层进行分离。

2.封装各种函数及功能模块,实现一处编写,多处调用,减少代码冗余。

3.便于扩展,可方便的引入外部扩展库,对自身框架进行增强。

4.选好设计模式,封装或编写各种引擎模块。

基本的框架需求大概就是这个样子,有了这些需求,接下来就是一个架构的设计,这里面涉及到的很多问题需要解决,下面我们一步步进行一个剖析。

二、框架设计过程

1.框架目录

这其实是个很重要的步骤,你的选择不同,最后目录结构也会有很大区别,除了满足基本的三层之外,扩展库,前端文件,模版,资源文件等也需要找目录放置,而这又决定了之后你的调用是否方便,我此次框架设计使用了smaty引擎作为视图引擎,目录结构大概如下:

这张图展示出了两级目录的一个结构,更深入的目录由于图片显示有限就不一一弄出来了,而每个目录及主要文件的作用会在后文一一说到。

2.目录介绍

(1)data目录

可以看到上图中的目录结构,由于使用了smarty引擎,而在smarty引擎中需要配置缓冲目录和缓存目录,因此data目录的作用就在于此。

(2)framework目录

该目录是我们框架的核心所在,db目录放置了我们的数据库操作函数库。function目录放置了一个function.php的文件,该文件的作用主要为方便以M(‘do’)这样的模式对各层方法的调用进行快速实例化。libs目录放置了框架的核心工厂类文件,如数据库的操作类,视图操作类,方便外部文件以如DB::funtion()这样的方式对这里面的方法进行调用。view放置了smarty视图引擎。include.list.php则是我们框架在调用时需要包含的文件,这里通通放在一个数组里进行保存。pc.php是我们的框架启动引擎,负责对我们的各个模块进行统一初始化,以及对我们的url进行解析处理。

(3)img目录

用于放置我们的样式文件、js文件以及其他相关的资源文件

(4)libs目录

该目录和framework下的libs目录名字虽然一样,但可以看到,该目录下放置的是MVC三层中的对应业务处理内容以及一个org扩展目录,Controller放置控制器、Model放置模型、View放置视图处理类。

(5)tpl目录

这个目录则放置一些模板文件,用于前端展示,可以看到我放置了admin和index两个目录,分别用于前台和后台的模板文件存放。

(6)admin.php和index.php

一般来说,采用mvc架构都会使用单入口模式,而这两个文件就是单入口模式的入口文件,用以启动该框架。

(7)config.php

这个基本所有的框架都有,配置文件,包含了比如数据库的配置,smarty引擎的配置,及一些静态变量的定义等。

这些所有的结构都只是该微型框架的一个基本结构,实际上复杂的框架会有很多扩展的函数以及外部插件,可以在这个目录结构上做出相应调整。

3.框架关键点

(1)控制器动态调用

单入口模式通常的url大概类似 index.php?controller=控制器&method=方法,在通过get方法获取到控制器和方法名之后,我们可以通过如下方式进行动态初始化function C($name,$method){

require_once('/libs/Controller/'.$name.'Controller.class.php');

eval('$obj=new '.$name.'Controller();$obj->'.$method.'();');

}

function M($name){

require_once('/libs/Model/'.$name.'Model.class.php');

eval('$obj=new '.$name.'Model();');

return $obj;

}

function V($name){

require_once('/libs/View/'.$name.'View.class.php');

eval('$obj=new '.$name.'View();');

return $obj;

}

(2)原生方法改造

熟悉smarty的朋友都应该知道,smarty有assign和dispaly两个方法,分别用于注册变量和将变量输出到模版文件,但如果同时注册多个变量会让我们的代码变得很冗杂,所以我们尝试对这两个方法进行改造public static function assign($data){

foreach ($data as $key => $value) {

self::$view->assign($key,$value);

}

}

public static function display($template){

self::$view->display($template);

}

我们让assign方法重写,让其可以直接注册数组,这样就减少了我们的后续代码量,如果要引入其它外部库,也可以通过这种方法对原生函数进行改造来使其更加适用。

(3)文件包含逻辑

本框架的启动文件为pc.php,因此,包含了pc.php就基本上包含了整个框架所需要用到的文件,先看一下一个入口文件index.php的内容。header("Content-type:text/html;charset=utf-8");

date_default_timezone_set('Asia/Shanghai');

require_once('config.php');

require_once('framework/pc.php');

PC::run($config)

很简单,包含了配置文件和框架启动引擎pc.php,然后调用run方法启动该框架就可以,再看看pc.php的内容$currentdir=dirname(__FILE__);

include_once($currentdir.'/include.list.php');

foreach ($paths as $path) {

include_once($currentdir.'/'.$path);

}

/**

* 完成一系列的初始化和调用控制器

*/

class PC

{

public static $controller;

public static $method;

private static $config;

private static function init_db(){

DB::init('mysql',self::$config['dbconfig']);

}

private static function init_view(){

VIEW::init('Smarty',self::$config['viewconfig']);

}

private static function init_controller(){

self::$controller=isset($_GET['controller'])?daddslashes($_GET['controller']):'index';

}

private static function init_method(){

self::$method=isset($_GET['method'])?daddslashes($_GET['method']):'index';

}

public static function run($config){

self::$config = $config;

self::init_db();

self::init_view();

self::init_controller();

self::init_method();

C(self::$controller,self::$method);

}

}

foreach遍历包含include.list.php中的所有文件,并将控制器和对应方法获取传递给C类进行自动包含。再看一下include.list.php有哪些东西$paths=$arrayName = array(

'function/function.php',

'libs/core/DB.class.php',

'libs/core/VIEW.class.php',

'db/mysql.class.php',

'view/Smarty/Smarty.class.php'

);

这里面存储了一个数组,包含了咱们的两个工厂类、数据库操作类、外部引擎类、核心function类。

至此,可以梳理一下整个框架对一个url请求的处理流程:

(4)业务分离

mvc的核心就在于各层之间的严格分离,但Controller层和Model经常容易被混淆在一起,这样会导致mvc架构失去原有的意义,我们需要清楚,控制层只实现简单的控制和逻辑处理,不涉及到具体的业务和数据交互,所有的具体操作都应放到Model层。另外,这两层中的类名和文件名也应保持一致。

(5)方法控制

我们在通过url的形式调用控制器及方法时,某些方法是不想被外部调用到的,比如登录检查函数,这个时候我们可以通过将函数定义为私有函数的方式避免其直接被通过url的形式调用到,来防止风险的发生。

(6)扩展性设计

一个框架应该具备好的扩展性,尤其对于新外部库引入,应该能很容易通过简单修改就可以使用,因此应该将配置项单独分离存储。

三、总结

该框架基本设计就是这个样子,很简单,但基本实现了mvc架构,虽然和市面上的成熟框架相差很多,但重写一遍对于mvc的架构理解会更加深入,加之如今越来越多的网站都采用的这种单入口mvc架构,对于这类网站的渗透更需要很好的理解。

一、框架整体分析

在实现一个框架之前,我们需要了解这个框架应该达到一个怎样的效果,按照传统框架的思路,大致可以总结出以下这么几条:

1.实现MVC架构,将控制、逻辑、视图层进行分离。

2.封装各种函数及功能模块,实现一处编写,多处调用,减少代码冗余。

3.便于扩展,可方便的引入外部扩展库,对自身框架进行增强。

4.选好设计模式,封装或编写各种引擎模块。

基本的框架需求大概就是这个样子,有了这些需求,接下来就是一个架构的设计,这里面涉及到的很多问题需要解决,下面我们一步步进行一个剖析。

二、框架设计过程

1.框架目录

这其实是个很重要的步骤,你的选择不同,最后目录结构也会有很大区别,除了满足基本的三层之外,扩展库,前端文件,模版,资源文件等也需要找目录放置,而这又决定了之后你的调用是否方便,我此次框架设计使用了smaty引擎作为视图引擎,目录结构大概如下:

这张图展示出了两级目录的一个结构,更深入的目录由于图片显示有限就不一一弄出来了,而每个目录及主要文件的作用会在后文一一说到。

2.目录介绍

(1)data目录

可以看到上图中的目录结构,由于使用了smarty引擎,而在smarty引擎中需要配置缓冲目录和缓存目录,因此data目录的作用就在于此。

(2)framework目录

该目录是我们框架的核心所在,db目录放置了我们的数据库操作函数库。function目录放置了一个function.php的文件,该文件的作用主要为方便以M(‘do’)这样的模式对各层方法的调用进行快速实例化。libs目录放置了框架的核心工厂类文件,如数据库的操作类,视图操作类,方便外部文件以如DB::funtion()这样的方式对这里面的方法进行调用。view放置了smarty视图引擎。include.list.php则是我们框架在调用时需要包含的文件,这里通通放在一个数组里进行保存。pc.php是我们的框架启动引擎,负责对我们的各个模块进行统一初始化,以及对我们的url进行解析处理。

(3)img目录

用于放置我们的样式文件、js文件以及其他相关的资源文件

(4)libs目录

该目录和framework下的libs目录名字虽然一样,但可以看到,该目录下放置的是MVC三层中的对应业务处理内容以及一个org扩展目录,Controller放置控制器、Model放置模型、View放置视图处理类。

(5)tpl目录

这个目录则放置一些模板文件,用于前端展示,可以看到我放置了admin和index两个目录,分别用于前台和后台的模板文件存放。

(6)admin.php和index.php

一般来说,采用mvc架构都会使用单入口模式,而这两个文件就是单入口模式的入口文件,用以启动该框架。

(7)config.php

这个基本所有的框架都有,配置文件,包含了比如数据库的配置,smarty引擎的配置,及一些静态变量的定义等。

这些所有的结构都只是该微型框架的一个基本结构,实际上复杂的框架会有很多扩展的函数以及外部插件,可以在这个目录结构上做出相应调整。

3.框架关键点

(1)控制器动态调用

单入口模式通常的url大概类似 index.php?controller=控制器&method=方法,在通过get方法获取到控制器和方法名之后,我们可以通过如下方式进行动态初始化function C($name,$method){

require_once('/libs/Controller/'.$name.'Controller.class.php');

eval('$obj=new '.$name.'Controller();$obj->'.$method.'();');

}

function M($name){

require_once('/libs/Model/'.$name.'Model.class.php');

eval('$obj=new '.$name.'Model();');

return $obj;

}

function V($name){

require_once('/libs/View/'.$name.'View.class.php');

eval('$obj=new '.$name.'View();');

return $obj;

}

(2)原生方法改造

熟悉smarty的朋友都应该知道,smarty有assign和dispaly两个方法,分别用于注册变量和将变量输出到模版文件,但如果同时注册多个变量会让我们的代码变得很冗杂,所以我们尝试对这两个方法进行改造public static function assign($data){

foreach ($data as $key => $value) {

self::$view->assign($key,$value);

}

}

public static function display($template){

self::$view->display($template);

}

我们让assign方法重写,让其可以直接注册数组,这样就减少了我们的后续代码量,如果要引入其它外部库,也可以通过这种方法对原生函数进行改造来使其更加适用。

(3)文件包含逻辑

本框架的启动文件为pc.php,因此,包含了pc.php就基本上包含了整个框架所需要用到的文件,先看一下一个入口文件index.php的内容。header("Content-type:text/html;charset=utf-8");

date_default_timezone_set('Asia/Shanghai');

require_once('config.php');

require_once('framework/pc.php');

PC::run($config)

很简单,包含了配置文件和框架启动引擎pc.php,然后调用run方法启动该框架就可以,再看看pc.php的内容$currentdir=dirname(__FILE__);

include_once($currentdir.'/include.list.php');

foreach ($paths as $path) {

include_once($currentdir.'/'.$path);

}

/**

* 完成一系列的初始化和调用控制器

*/

class PC

{

public static $controller;

public static $method;

private static $config;

private static function init_db(){

DB::init('mysql',self::$config['dbconfig']);

}

private static function init_view(){

VIEW::init('Smarty',self::$config['viewconfig']);

}

private static function init_controller(){

self::$controller=isset($_GET['controller'])?daddslashes($_GET['controller']):'index';

}

private static function init_method(){

self::$method=isset($_GET['method'])?daddslashes($_GET['method']):'index';

}

public static function run($config){

self::$config = $config;

self::init_db();

self::init_view();

self::init_controller();

self::init_method();

C(self::$controller,self::$method);

}

}

foreach遍历包含include.list.php中的所有文件,并将控制器和对应方法获取传递给C类进行自动包含。再看一下include.list.php有哪些东西$paths=$arrayName = array(

'function/function.php',

'libs/core/DB.class.php',

'libs/core/VIEW.class.php',

'db/mysql.class.php',

'view/Smarty/Smarty.class.php'

);

这里面存储了一个数组,包含了咱们的两个工厂类、数据库操作类、外部引擎类、核心function类。

至此,可以梳理一下整个框架对一个url请求的处理流程:

(4)业务分离

mvc的核心就在于各层之间的严格分离,但Controller层和Model经常容易被混淆在一起,这样会导致mvc架构失去原有的意义,我们需要清楚,控制层只实现简单的控制和逻辑处理,不涉及到具体的业务和数据交互,所有的具体操作都应放到Model层。另外,这两层中的类名和文件名也应保持一致。

(5)方法控制

我们在通过url的形式调用控制器及方法时,某些方法是不想被外部调用到的,比如登录检查函数,这个时候我们可以通过将函数定义为私有函数的方式避免其直接被通过url的形式调用到,来防止风险的发生。

(6)扩展性设计

一个框架应该具备好的扩展性,尤其对于新外部库引入,应该能很容易通过简单修改就可以使用,因此应该将配置项单独分离存储。

三、总结

该框架基本设计就是这个样子,很简单,但基本实现了mvc架构,虽然和市面上的成熟框架相差很多,但重写一遍对于mvc的架构理解会更加深入,加之如今越来越多的网站都采用的这种单入口mvc架构,对于这类网站的渗透更需要很好的理解。

更多PHP微型框架设计 相关文章请关注PHP中文网!

本文原创发布php中文网,转载请注明出处,感谢您的尊重!

设计php框架_PHP微型框架设计相关推荐

  1. AI框架精要:设计思想

    AI框架精要:设计思想 本文主要介绍飞桨paddle平台的底层设计思想,可以帮助用户理解飞桨paddle框架的运作过程,以便于在实际业务需求中,更好的完成模型代码编写与调试及飞桨paddle框架的二次 ...

  2. .NET框架设计—常被忽视的框架设计技巧

    阅读目录: 1.开篇介绍 2.元数据缓存池模式(在运行时构造元数据缓存池) 2.1.元数据设计模式(抽象出对数据的描述数据) 2.2.借助Dynamic来改变IOC.AOP动态绑定的问题 2.3.元数 ...

  3. OSGI框架的功能和设计思

    支持模块化的动态部署  基于 OSGi 而构建的系统可以以模块化的方式(例如 jar 文件等)动态地部署至框架中,从而增加.扩展或改变系统的功能. 要以模块化的方式部署到 OSGi 中,必须遵循 OS ...

  4. Spring框架的设计理念与设计模式分析

    spring设计原理 Spring框架的设计理念与设计模式分析 2016-1-27 by Damon 摘要:Spring作为现在最优秀的框架之一,被广泛的使用并有很多对其分析的文章.本文将从另外一个视 ...

  5. 为什么ui框架设计成单线程_评估UI设计的备忘单

    为什么ui框架设计成单线程 Whether you're evaluating your design proposals or giving feedback to a colleague duri ...

  6. Hadoop精华问答:Hadoop框架最核心的设计是?

    2006年项目成立的一开始,"Hadoop"这个单词只代表了两个组件--HDFS和MapReduce.到现在的13个年头,这个单词代表的是"核心",今天我们就来 ...

  7. atitit.atiOrmStoreService 框架的原理与设计 part1  概述与新特性

    atitit.atiOrmStoreService 框架的原理与设计 part1  概述与新特性 1. 新特性如下 支持生成sql在无数据库连接的情况下 2. Orm设计 主要的俩个以来service ...

  8. css框架和js框架_优雅设计的顶级CSS框架

    css框架和js框架 Brief discussion: 简要讨论: Well, who doesn't want their website or web page to look attracti ...

  9. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之LED驱动框架--面向对象、分层设计思想

    文章目录 前言 1.LED驱动程序框架 1.1.对于LED驱动,我们想要什么样的接口? 1.2.LED驱动要怎么写,才能支持多个板子?分层写 1.3.程序分析 驱动程序 应用程序 Makefile 1 ...

最新文章

  1. AI一分钟|特斯拉宣布裁员9%;Facebook启动隐私设计实验室;百度Apollo与宝马拜腾联姻...
  2. 【必看】如何在 Linux 上恢复误删除的文件或目录
  3. HDL输入设计详解攻略
  4. cocos2d-x游戏实例(23)-简易动作游戏(1)
  5. On the Difference Between Orthogonal Matching Pursuit and Orthogonal Least Squares
  6. win32 api 文件操作!
  7. 惊!Python能够检测动态的物体颜色!
  8. python经典题库及答案文库_Python100经典练习题
  9. AD19原理图背景栅格去掉(改为纯色)
  10. JavaScript 图像延迟加载库 Echo.js的简单使用
  11. 史上最全Java基础视频教程
  12. php fseek函数,php fseek函数怎么用
  13. Python-字符串str和json格式的转换
  14. CNZZ站长统计怎么用
  15. 阿里云 x86计算机,什么是x86服务器?x86是多少位系统?
  16. VB.net 图片刷新闪烁 解决方案
  17. 爬取公众号的文章,同时处理图片不显示问题(JAVA)
  18. RabbitMQ详解及其特性
  19. 齐聚绿城 | 锦江都城酒店聚焦中高端酒店投资新方向
  20. mcnpf5输出结果_MCNP使用教程

热门文章

  1. Oracle在rownum使用结果集排序
  2. [ACM_NYOJ_15]括号匹配(二)
  3. 初学者python笔记(map()函数、reduce()函数、filter()函数、匿名函数)
  4. linux用户管理和群界面怎么打开,Linux的用户和组群管理
  5. asp.net session 如何知道是哪个浏览器客户端_小弟该如何复习 Java?
  6. Python绘制三次贝塞尔曲线
  7. java 判断图片损坏_如何在Java中检测损坏的图像(PNG,JPG)
  8. hive动态分区shell_Hive/Shell 创建Hive 库 ,表脚本,Hive 动态增加分区脚本
  9. 启动计算机时页面配置出现问题,开机提示“由于启动计算机时出现了页面配置问题…”...
  10. linux申请cache和释放cache,Linux--- 手工释放系统cache