PHP搭建自己的web框架-总体概述


        这里讲的WEB是指运行在apache下的PHP WEB程序。

        首先要理解PHP在apache下的运行机制和请求的生命周期。

        PHP是脚本语言,它的执行过程就是从文件入口,一直到文件的最后的结尾,其中可以包含或引用其它文件,是面向过程的。在过程当中,可以使用对象来实现各种需要的逻辑处理。你可以把一个或者多个对象拿来完成所需要的功能,你也可以告诉一个对象你要完成什么功能,这是面向对象的开发方法,也是普遍的开发方法。所以,在面向过程的运行机制中,使用面向对象的开发方式。

        每一个HTTP请求的生命周期也是从入口开始,直到程序结束,其中的变量将不复存在,不同的HTTP请求的变量都是独立互不影响的。我们可使用global声明、$GLOBALS全局数组变量、static静态变量在同一HTTP请求中共享数据;使用session来实现会话级别的共享;使用缓存来实现站点全局数据共享。global声明一般在方法中,在面向过程的开发中使用,平时不会用到。$GLOBALS和static经常会用到,但不能直接操作,而是在对象里或专门的方法来管理,比如常用的单例模式使用$GLOBALS和static保存。


        PHP程序中,我们都会考虑尽量使框架简洁、高效、清晰、易用,这对开发和维护都很有好处。

        基本的程序模式使用MVC模式,分层分模块、同时需要一个好用的URL router配合MVC。

        URL router:很关键的一个组件,决定着源码文件的组织结构、代码的清晰度。一个好的router,能方便地找到逻辑入口,体现框架的易用性。    

        Model: 一直用数组。用数组主要担心数组内容不清楚,在项目中,属性参考数据库字段,因此数组内容还是相对明确的,Model的操作使用数据访问层DAO封装。数据库访问中,直接转化为数组形式,也比较高效。对于其它系统的交互数据对象,一般有接口文档定义。对于ORM中的Active Record技术,能不用还是不用的好。

        View: 开始使用smarty,但在性能报告中,smarty执行的方法耗时占比太多太多,后来使用tmd_tpl,就一个文件,简单易用高效,易修改。在视图模板中,结合PHP语法,并辅于模板变量。MVC的思想是分离,并不代表不能在View中使用PHP语法。如果是API接口,可以直接把数据转化为具体格式结果并返回。

        Controller: 或者action,代表着一个行为、一个方法、一个接口。只有一层的controller往往是不够用的,一般要分成接口层、业务层、数据访问层,可能还需要通信层。接口负责参数校验、接入权限控制,调用具体的业务,最后返回数据或显示页面等。所有的业务最好都以接口层开始,在这之前应只做框架方面的事情,当我们需要阅读某个业务实现时,只要顺着接口层入口开始读即可。业务层是执行实际的业务功能,业务层从数据访问层获得数据并进行业务上加工处理。数据访问层从数据库或调用接口获取数据,可进行简单的数据转换处理。如果PHP只是作为数据展示前端,后端由C/C++/GO等执行业务,那只需要封装业务层,在业务层里把数据请求到后端,然后返回给接口层。

                

        以上是程序的基本框架结构,或者说是业务的流程结构,通常作为系统最重要的部分。但离实用还有距离,还有很多基础功能要增加,比如session的处理,数据库访问,日志处理等功能。这些基本功能一般是可以独立于框架的,可以在不同的框架上应用。功能类不要与框架耦合太紧,一般使用组合方式。我们将这些基础功能按照用起来顺手的方式封装成核心类,使用单例或多例来调用,或对类进一步封装成全局使用的方法,方便使用。


        如上图,中心把握好、梳理好了,体现的是业务能力,因为随着业务发展,自然会形成业务分层的结构;而周边结合得好,体现的是框架能力,如何用得/开发得舒适顺手的问题。

        在调用功能类或者业务类时,都会涉及到类的加载或导入问题。那是否使用自动加载功能呢?根据个人体验和IDE支持程度,我觉得不直观,对IDE不友好,如F3找不到定义的方法,这是我们开源系统学习的感受,还有对性能的影响。还是直接require/include方便,虽然多写了些代码,但确实对开发维护阅读带了极大的方便(除了修改名称后导致引用变更不很方便,但可通过全局搜索来修改)。一些公共的类在入口里全局引用,业务类按需引用。性能损失?因为业务大部分时候都是垂直的,一般使用require/include即可,不需要require_once/include_once,即使多使用几个once也没什么关系,首先可保证正确性,且程序总体性能不是这个决定的。自动加载会增加很多判断、指令还有栈操作,文件的查找、损失的性能更多吧。不过一个好的自动加载实现还是可以考虑引入的,业务类的文件可以考虑,框架性的文件不使用自动加载,并且要简单、定位准确、高效、避免重复。

         加载后怎么使用?方法、类对象方法还是类静态方法调用?根据不同的场景决定。全局功能一般是方法调用,如thinkPHP获取配置内容的C方法,直接调用。如果在分层中,接口层->业务层->数据访问层,使用类静态方法调用。一些全局功能操作,如数据库操作类、一些第三方功能类、多态功能类,这些一般使用单例来使用,不需要多次产生新对象。

        关于反射功能,注解,IOC,面向切面编程等在其它语言中很有用的功能和实践,在PHP也基本能实现,虽然也看了很多实践例子,但并没有考虑运用到项目之中,能实现并不代表一定要用。LAMP能方便地开发一个网站,且一般是做网站应用,与做一个框架(如spring)是有区别的,因此对PHP的使用更多是关注网站的业务流程及其性能上,使业务流程清晰易于维护,使灵活性不至于复杂化业务、损害性能。高性能网站需要短平快,更何况很多网站是PHP做前端渲染,c/c++/java做后台业务,所以PHP网站就应尽量简单。因为我们是一个业务网站系统,业务流程是确定的,执行是从头到尾的,体现在代码上是业务代码要清晰的,如果在执行过程中被反射了一把,注入了一把,会影响人对业务的理解,同时开发维护BUG定位的时候也可能忽视框架动了什么手脚。不像一些通用的框架或者第三方包,需要足够的灵活供调用,灵活性就比较绕,还要牺牲一定的性能。使用这些功能,往往事先都要做一些初始化代码,或者一些配置初始化,并且每个HTTP请求都要执行一次,即使再简单的功能,没有必要,不像java那样只初始化一次。比如一些restfull框架会在入口处定义路由,还有大量的配置,这个虽然有一定的清晰灵活度,但这种情况下建议使用约定优于配置的思想。

       以上的一些做法有些与众不同或极端,但是也是经历过原始-->框架(高级特性,技巧)-->回归原始的过程,可以理解为个人的独特感受或经验。使用PHP的基本特性,从项目入手、业务流程理解、到开发维护,都使人轻松。性能方面没有过多损耗,也能方便定位优化。总之原始简单是对性能最好的提升;业务垂直隔离地编写,一眼就看出做了什么是对开发效率的提升。

       如果一开始没有能力按项目要求开发自己的PHP框架,那么在第一次使用一个框架后,在其它项目中就应考虑自己按需实现网站,并形成自己的框架。

       我觉得最简单好上手的PHP网站框架,需要一个路由、一个控制器配合一个视图模板引擎。其它功能模块则按需添加。

        

智能推荐

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告