ThinkPHP 프레임워크는 중국에서 잘 알려져 널리 사용되는 PHP 프레임워크입니다. 몇 가지 간단한 개발 예제를 통해 이 프레임워크가 제공하는 개발 편의성과 손쉬운 확장 설계에 대해 자세히 살펴보겠습니다. 동시에 소스 코드 분석의 관점에서 프레임워크의 몇 가지 단점을 살펴보고 포괄적이고 객관적인 평가를 하려고 노력합니다. 여기서는 이미 ThinkPHP 프레임워크를 사용했다고 가정합니다. 기본적인 사용법은 공식 문서를 참조하세요.
1. 프레임워크 계층화 및 URL 라우팅
프레임워크 설치는 매우 간단합니다. 그냥 다운받아서 웹서버 디렉토리에 넣어두시면 됩니다. 다만, 기본 항목 파일 위치를 사용하지 마시고, 별도의 디렉토리에 넣어두시는 걸 추천드립니다. 코드와 데이터를 보호하세요. 예를 들어 내 항목 파일과 웹 서버 구성 디렉터리는 웹 디렉터리에 있습니다(외부 프레임의 index.php는 삭제되지 않고 사용되지 않습니다).
대부분의 MVC 프레임워크와 마찬가지로 프레임워크의 디렉터리 구조에 따라 자체 Controller와 View만 확장하면 되며 일부 페이지가 개발됩니다. ThinkPHP는 자체 URL을 구성하기 위해 모듈, 컨트롤러 및 액션의 3계층 구조를 제공합니다(버전 3.1은 그룹화, 액션 및 메소드라고 하며 3.2는 보다 국제적입니다). 디렉토리 구조는 다음과 같습니다.
여기에서 강력히 추천합니다:
1. 비즈니스는 별도로 계층화되어 있으므로 컨트롤러와 모델에 배치할 필요가 없습니다. 예를 들어 확장 함수 라이브러리 Application/Common/Common/function.php를 사용하여 비즈니스 계층 이름을 Service:
<code>function service($name)<br>{<br> return D($name, 'Service');<br>}</code>장점은 재사용이 가능하다는 것입니다. 나중에 wap 페이지를 개발하고 다른 컨트롤러를 작성하려는 경우 MySQL에서 MongoDB로 데이터베이스를 마이그레이션하는 등 향후 데이터 저장소가 변경되면 서비스를 재사용할 수 있습니다. 모델은 문제가 없지만 서비스에는 여전히 수정이 필요하지 않습니다.
3계층 디렉토리는 이미 일반 웹 애플리케이션을 처리할 수 있습니다. 보다 복잡한 웹 애플리케이션의 경우 다양한 항목 파일을 정의하고 이를 해결하기 위해 다양한 애플리케이션을 로드할 수 있습니다. 더 복잡한 애플리케이션? 포털이나 대규모 웹사이트의 경우 PHP 프레임워크가 모든 문제를 해결할 수는 없습니다. 자체 미들웨어와 맞춤형 프레임워크가 필요합니다.
ThinkPHP는 4가지 URL 액세스 모드를 지원합니다.
일반 모드, 기존 URL 모드, 와 같이 모든 매개변수가 분리됩니다.
http://localhost/tp/index.php?m=Ucai&c=User&a=index¶=xxx
라우팅 매개변수: m 매개변수는 모듈을 나타내고, c는 컨트롤러를 나타내고, a는 액세스 방법을 나타냅니다.
2.
호환 모드
http://localhost/tp/index.php?s=/Ucai/User/index/para/xxx
라우팅 매개변수는 s 매개변수를 통해 조합됩니다. 물론 데이터 매개변수를 s 매개변수에 배치할 필요는 없습니다.
3.
경로정보 모드
http://localhost/tp/index.php/Ucai/User/index/para/xxx
이 모드는 엔트리 파일과 실제 스크립트를 함께 넣어두는 방식으로 의미가 명확하고 SEO에도 편리합니다
4.
다시 쓰기 모드
http://localhost/tp/Ucai/User/index/para/xxx
이 모드는 웹 서버의 재작성 구성을 통해 항목 파일을 숨겨 더욱 친숙하게 만듭니다.
pathinfo 및 rewrite 모드에는 웹 서버 지원이 필요합니다. ThinkPHP에는 어떤 모드로 설정해야 하는지가 설정되어 있습니다. 실제로 U 메소드에서 URL 링크를 생성할 때 사용됩니다. 접속 시 웹 서버가 지원하는 한 어떤 메소드든 사용할 수 있습니다.
ThinkPHP는 구성할 필요가 없지만 첫 번째 액세스 모드를 사용하는 한 모든 후속 URL은 사용자가 이미 액세스했고 거기에 있기 때문에 이 방식으로 생성됩니다. 지원되지 않습니다. 지원 문제가 없습니다.
일반 URL이 요구 사항을 충족할 수 없는 경우 라우팅을 구성하여 URL을 더욱 최적화할 수 있습니다. 예를 들어 URL을 더 간단하게 구성하고 싶습니다.
모듈 구성 파일에 다음 라우팅 구성만 추가하면 정규식을 사용하면 더 간단해질 수 있습니다
<code>'URL_ROUTE_RULES' => array(<br> 'login/:para' => 'Ucai/User/index',<br> 'login' => 'Ucai/User/index',<br> ),</code>2. ThinkPHP 확장
ThinkPHP 자체에는 풍부한 구성 요소와 드라이버가 포함되어 있습니다. ThinkPHP의 확장 설계를 이해하기 위해 데이터베이스 드라이버 확장과 동작 확장을 예로 들어 보겠습니다.
虽然ThinkPHP提供了众多的数据库驱动,但是也并不能满足所有的需求。例如我们的数据很可能不是通过直接访问数据库去实现,而是通过一些中间件(例如C程序)进行转发,从而获得更好的性能,这时就需要扩展数据库驱动来支持。
扩展非常简单,在DB/Driver目录下新建自己的驱动,例如Custom.php,然后实现request和execute方法扩展就算完成了,然后再配置文件里配置DB_TYPE='custom',就可以使用了。这里的request表示查询,execute表示更改数据,所有其他操作都会在Model里进行解析,包装成sql语句调用这两个方法执行。
例如我所实现的最简单的query方式,通过shell命令调用sqlite执行sql语句:
<code>public function query($str) {<br> $cmd = sprintf('sqlite3 %s "%s"', $this->config['params']['dbfile'], $str);<br> exec($cmd, $arr);<br>}</code>
当然这个只是示例,ThinkPHP本身就支持sqlite3,通过pdo的方式去连接就可以。实际的应用环境可能是通过连接4层协议访问中间层端口获取数据。
四、Behavior行为扩展
Behavior行为设计是ThinkPHP框架的核心,通过行为配置和扩展,为系统的伸缩性和定制性提供了最大的支持。
假如我们要加入登录验证的功能,按照常规我们会设计自己的父类Controller,然后所有其他的Controller都从这里继承。但有了Behavior会变得更加简单和灵活,我们只需要在tags.php(没有的话在配置目录新建)添加一个Behavior就可以了:
<code>return array(<br> 'action_begin' => array('Ucai\Behavior\AuthBehavior'),<br> 'view_begin' => array('Ucai\Behavior\OutputBehavior'),<br>);</code>
程序在执行到action_begin流程时就会调用这个Behavior,我们可以根据状态进行跳转或终止执行。
<code>namespace Ucai\Behavior;<br>class AuthBehavior {<br> // 行为扩展的执行入口必须是run<br> public function run(&$return) {<br> //不需要验证的action设置为true<br> if (!$return['AUTH_PUBLIC']) {<br> if (service('User')->checkLogin())<br> {<br> $return = true;<br> }<br> else<br> {<br> header('Content-Type: text/html; charset=utf-8');<br> redirect(U('User/index', array('url' => $_SERVER['HTTP_REFERER'])), 5, '需要登录,5秒后跳转。。。');<br> }<br> }<br> }<br>}</code>
对于不需要登录的页面我们可以在Controller里添加配置,所有不配置的都会要求登录验证。
<code>public $config = array('AUTH_PUBLIC' => true);</code>
这里大家对继承和Behavior实现登录验证做一个对比,可能觉得区别不大。但是在一个复杂的项目里,这种功能会非常多,如果每个功能都放到父类里,就会非常庞大,并且部分子类可能又不需要,这时候用Behavior去定制流程就会显得游刃有余。
在上面的配置中我们还发现了一个配置OutputBehavior更能说明问题,大家有没有猜到,这个Behavior我是用来在view里输出一些共有变量,例如jscss的域名和路径等。在没有Behavior之前,大家是不是需要一个公共方法,然后每个页面都去调用一次,或者改写View的类代码?有了Behavior就显得方便许多。
<code>namespace Ucai\Behavior;<br>class OutputBehavior {<br> public function run(&$return) {<br> $view = \Think\Think::instance('Think\View');<br> $view->assign('STATIC_URL', 'http://p3.ucai.cn/static');<br> }<br>}</code>
扩展总结:通过Behavior扩展和数据库驱动扩展大家可以看到,ThinkPHP提供了很灵活的扩展和增强机制,能满足众多需求。其他存储、缓存、日志、模板引擎等如果需要也能很方便的扩展。
五、源码分析与不足
首先我们来分析一下框架执行的大致流程:
index.php(入口、调试模式、应用路径)
--> ThinkPHP.php(定义路径与访问模式)
--> Think\Think(类加载器、异常处理、读取共有配置)
--> Think\App(请求url调度解析、执行调度解析结果)
--> exec 执行用户定义的Controller的Action方法
--> Think\Dispatcher(根据url模式解析M、C、A和参数,加载模块配置)
--> Think\Controller(调用视图、包装和重定向)
可以看到,框架的内部流程其实比较简单,还有2个很重要的类:
Think\Hook: 监听App、Action、View的各个阶段,执行Behavior
Think\Behavior: 可配置(配置文件)可增删(代码)
在分析源代码的过程中,我们也看到了一些不足:
1、宏定义过多,难于维护和修改
建议:只在个别文件定义极少数几个宏,其余用类常量包装
2、面向过程代码过多,封装不清晰
建议:用面向对象思想包装
例如:url的解析和包装,现在是在Dispatcher里生成APP宏,然后在U方法里读取宏并生成最终url。其实完全可以定义一个类来包装例如UrlHelper,而类的二个方法parse和generate分别负责解析和生成url,这样代码结构会清晰很多。
3、有的函数和类代码封装过多,复用和改进不方便
建议:用组合来封装独立功能内容
例如:Model的校验功能,完全可以独立成类,也可以用于非Model对象调用。而现在的校验接口是Model的保护性方法,只能在Model的create函数调用,外面必须通过create方法才能校验。
4、代码规范和风格问题
希望代码风格能更加规范和标准,例如DB类作为模板方法的父类,应该用抽象方法或抛出异常形式定义所有Model需用到的方法。事实上有些方法子类是不需要的,而Db类却没有实现。
六、总结
중국에서 널리 사용되는 PHP 프레임워크인 ThinkPHP는 실제로 개발에 편리함을 가져다주었습니다. 프레임워크 개발자는 웹 프로세스에 대한 철저한 이해를 갖추고 있으며 PHP 기능 응용 프로그램에 능숙합니다. 프레임워크는 다양한 요구 사항에 적응할 수 있는 유연한 구성과 확장을 정의하고 개발을 가속화하기 위한 풍부한 구성 요소와 모듈을 제공합니다. 마지막으로, ThinkPHP의 문서화와 커뮤니티 지원은 매우 완벽하며, 이는 프레임워크의 인기에 있어서 없어서는 안 될 부분이기도 합니다. 또한 ThinkPHP가 향후 구조를 더욱 개선하고 최고의 PHP 프레임워크를 구축할 수 있기를 바랍니다.