编写PHP的Framework_第1页
编写PHP的Framework_第2页
编写PHP的Framework_第3页
已阅读5页,还剩12页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、编写PHP的Framework框架这个概念可能一开始就吓坏了很多PHP的Coder,其实你只要把一个Framework想明白了,其实也没啥,只是别人功能更复杂,细节考虑的更多,代码质量更高。 框架最重要的一个文件为入口文件,基本上相当于一个总控开关,所有的请求都需要经过这个文件:1 run(); 这个文件可以只做一件事情,那就是将控制权交给框架。 大家都知道,一个MVC的应用,所有的请求都必须经过控制器,所以下面我们来编写一个比较简单的控制器:1 ?php2 class Test_IndexController extends Tp_Controller 3 public function i

2、ndexAction() 4 echo a;5 6 这个类只需要继承自Tp_Controller即可,Tp_Controller是Toper的控制器的基类,只要你继承它,你就可以使用框架帮你写好的一系列方法,这样就可以大大减少你自己的工作量了,并且按照规范,函数名也是有意义的,如刚才写的这个函数代表的意义就是访问Test模块IndexContrller这个控制器下面的index这个Action。 那么如何使用模型呢?实际上非常简单。1 ?php2 class Test_IndexModel extends Tp_Model 3 public function test() 4 return t

3、est;5 6 原理和控制器一样,也是继承框架的类,然后自定义方法,这个地方的方法名没有限制,可以随意。 那么编写模型之后怎么在控制器中调用呢,其实方法就是在控制器中实例化这个模型类,然后调用相应的方法即可,所以修改刚才这个控制器的类:1 test();6 7 为什么没有include语句? 那是因为框架帮你做完了这一切,当然,框架不是万能的,当你比较熟悉之后,也可以选择不使用自动导入。 刚才我们所做的一切都没有View,那么怎么编写View呢,实际上就是一个HTML文件,框架在View这一层一般是实现标签库,标签库帮你完成一些原来需要用PHP代码才能完成的事情,比如循环遍历,没有标签库可能你

4、就只能在这个View的文件中使用,这样对于代码分离很不好。 如果你对标签库没有概念,那么你直接看下面的代码吧!1 2 3 test4 5 6 7 8 这是一段没有什么难度的代码,唯一的难度可能就是这个print标签,这个标签是框架定义的,它的功能很简单,就是打印一个字符串,你可能觉得这样没什么意义,因为我使用PHP代码也可以很轻易的完成这个功能,但是你想像一下一个做前端的为什么还需要懂PHP呢,如果使用标签库,那么前端开发人员就可以像使用HTML标签一样操作数据了。 我们知道所有的请求都必须要通过控制器,所以外部是无法直接访问这个视图文件的,所以又需要修改控制器的代码了!1 test();6

5、$this-_display(Test.test);7 8 如果你学过smarty,你可能对display方法很熟悉,实际上这个函数的功能就是显示一个模板文件! 好了,一个基本的MVC应用就搭起来了,不是很难吧! 如何查看效果呢,有两种方式: 1.CGI:打开浏览器,浏览器访问时,如果您的域名是:localhost/testframework,那么您可以使用localhost/testframework/Public/index.php/Test/Index/index来访问,如果您设置了虚拟主机,如,那么只需要使用/Test/Index/index就可以访

6、问了; 2.CLI:通过命令行直接执行PHP脚本时,在Public目录下面使用php index.php m:test c:Index a:index。实际上要自己实现一个MVC的应用也不难,我们知道MVC里面所有内容都必须经过控制器,所以如何把控制权交给控制器呢?我们需要一个入口文件,入口文件负责将传递的请求交给对应的控制器,实际上也就是完成路由的功能。为了学习的需要,可以将路由的功能简化,用户通过GET方式将控制器的名和Action的名传递过来,入口文件接收到所有参数之后,按照之前约定的规则include某一个文件,然后实例化这个类,再调用这个类的相应方法。01 $action();13

7、else 14 echo the method does not exists;15 16 else 17 echo the class does not exists;18 19 else 20 echo controller not exists;看着代码行数还是挺多的哦,实际上实现的功能比较简单,就是通过接受通过GET方式传递的控制器名和Action名,如果没有传递,那么调用默认的控制器名或者Action名,当用户传递了控制器名和Action名之后可能会存在这样一个问题,就是通过我们之前约定的规则找不到相应的文件或者类或者方法,那么我们需要显示友好的信息,而不是让PHP抛出一系列的警告,

8、这样对于程序的健壮性很有帮助。当有了控制器之后,一切都变得简单了,对于模型,我们可以把它看成是一个普通的类,只是在功能上它负责业务逻辑的处理。1 ?php2 class IndexModel 3 public function test() 4 return Hello world!;5 6 作为演示,我们只是在这个模型里面返回一个Hello World,那么控制器怎么使用这个模型呢,实际上也就是首先include这个文件,然后实例化类,调用相应的方法。 我们现在修改控制器为:01 test();09 else 10 echo model does not exists;11 12 13 现在

9、模型有了,那么怎么连接视图呢?1 2 3 4 5 6 7 写完视图之后,怎么通过控制器调用这个视图呢? 修改控制器至如下:01 test();09 $viewPath = dirname(_FILE_) . /./views/index.php;10 if(file_exists($viewPath) 11 include $viewPath;12 else 13 echo view does not exists;14 15 else 16 echo model does not exists;17 18 按照上一次我讲的内容,一个基本的MVC构架是已经搭建起来了的,但是本身还存在很多问题,

10、如:模型这一块儿每次连接DB,关闭DB的代码冗余,视图这一块儿还是代码,每个文件要使用很多include代码等等。要编写一个框架,那么首先就要规定一个标准的目录结构,我们暂时把这个目录结构定死,不允许用户修改,这样可以减少代码量,方便大家看的更明白。由于之前编写了Toper,所以我准备沿用Toper的目录结构来做演示: Library(框架存放目录)Test(假设这个框架名就叫test)UserApps (用户的APP存放目录)Configs(配置文件存放目录)Modules(模块存放目录)Controllers (所有控制器存放目录)Models (模型存放目录)Views (视图存放目录)

11、Helpers (辅助文件目录)Plugins(插件存放目录,暂时用不上)Public (网站根目录)index.php (最重要的入口文件) 这个地方有点需要解释一下,Public目录才是网站的根目录,Library目录和UserApps目录是存放在网站根目录之外的,这样用户通过浏览器访问时就不能直接访问这个文件,这样可以提高网站的安全性。之前我们把路由的功能全部放在入口文件这一块儿,实际上这是不合适的,入口文件不应该做这些逻辑的处理,所以我们把之前存放在入口文件的代码迁移到library目录的Test目录下面,由于之前在入口文件中完成的功能是路由,所以我们把代码迁移到Route.php,这

12、个文件就完成路由的功能。 好,我们来看看Route.php这个文件的内容:01 $action();15 else 16 echo the method does not exists;17 18 else 19 echo the class does not exists;20 21 else 22 echo controller not exists;23 24 25 这个时候,看到没,我们只是把之前放在入口文件的代码拷贝到Route.php这个文件中了,那么这样有什么好处呢? 入口文件代码少了!1 ?php2 include dirname(_FILE_) . /./Library/Te

13、st/Route.php;3 Route:run(); 只有两行的代码,够简洁吧! 但是你看到一个问题没有,每次我都需要使用dirname来确定当前路径,而如果这个框架中有20个文件,每个文件中有3处使用dirname来获取绝对路径,那么感觉到恐怖了吧,90处重复代码,如果以后路径一修改,那将会是你的噩梦! 所以,我们不妨在入口文件定义一个路径,这个路径作为APP的基路径,由于我们经常也会使用Library下面的Test目录路径,我们也设置一个框架路径,所以,入口文件修改为:1 ?php2 defined(APP_PATH) | define(APP_PATH,dirname(_FILE_)

14、. /.);3 defined(FRAMEWORK_PATH) | define(FRAMEWORK_PATH,APP_PATH . /Library/Test);4 include FRAMEWORK_PATH . /Route.php;5 Route:run(); 那么Route.php相应的也需要修改:01 $action();15 else 16 echo the method does not exists;17 18 else 19 echo the class does not exists;20 21 else 22 echo controller not exists;23

15、24 25 实际上PHP已经有相应的机制可以实现这个功能了,这个机制就是autoload,它会在试图使用尚未被定义的类时自动调用。现在我们可以在Route.php中的开头定义autoload函数(当然,这样是不规范的,但是为了简单,先这么做)。我们现在的自动导入需要导入两类文件,一类是框架类文件,另外一类是用户应用模块的类文件,为了简化代码,可以假设框架的所有文件都存放在/Library/Test目录下面,用户类文件都存放在/UserApps/Modules目录下面,并且只会在Controllers,Models,Helpers这三个目录下面,并且这几个目录下面没有子目录。对于这个自动导入的函

16、数,它需要首先尝试导入框架类文件,如果该文件不存在,说明是用户类文件,然后再尝试导入用户类文件,如果是,那么include它。注意:由于要频繁使用UserApps/Modules这个目录,所以我定义了一个MODULES_PATH这个常量;01 function _autoload($className) 02 $frameworkFileName = FRAMEWORK_PATH . / . $className . .php;03 if(is_file($frameworkFileName) 04 include $frameworkFileName;05 else 06 /用户类文件07

17、$controllerFileName = MODULES_PATH . /Controllers/ . $className . .php;08 if(is_file($controllerFileName) 09 include $controllerFileName;10 else 11 $modelFileName = MODULES_PATH . /Models/ . $className . .php;12 if(is_file($modelFileName) 13 include $modelFileName;14 else 15 $helperFileName = MODULE

18、S_PATH . /Helpers/ . $className . .php;16 if(is_file($helperFileName) 17 include $helperFileName;18 else 19 throw new Exception(class not found);20 21 22 23 24 当你把这个函数写完之后,可以在之前已经写好的IndexController.php中去测试一下,比如在和IndexController同一目录下面建立一个文件Test.php,文件代码如下:1 ?php2 class Test 3 public function test() 4

19、 echo Test;5 6 然后在IndexController.php中使用如下:1 test();6 7 如果出现Test,那么恭喜你,自动导入成功了! 现在再考虑一下,如果针对一个很复杂的项目,使用这种方式来自动导入,有什么问题吗?其实问题是比较严重的,首先对于框架的文件,我们不可能将所有文件都存放在一个目录下面,这样当文件多了之后就检索就麻烦了;对于用户类文件,比如控制器的文件,我们不可能将它全部存放在一个目录下面,我们需要按照模块切分目录等。如果用_autoload来实现的话,这个函数的代码量就太大了,而且如果有一个地方的修改那么就可能牵一发而动全身,这样对于项目的维护是很不利的。那么我们怎么解决这个问题呢?方法一:我们定义很多辅助函数,比如导入框架文件,我们定义一个frameworkAutoloadHelper,对于用户文件定义一个userAutoloadHelper,然后将业务逻辑存放在这两个函数中,最后在_autoload中调用这两个函数即可,当用户功能需要修改的时候,代码维护性就好一些了;方法2:在SPL中已经定义了一个spl_autoload_register,可以使用这个来讲自动导入的功能分摊到多个类中,而且还可以将自动导入的控制权交给用户,这对于框架来说是比

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论