一步步编写PHP的Framework(五)

 

       上一次我讲到使用自动导入可以实现一个类的延迟加载,这一次我想讲一下配置文件。

       不知道大家注意了没有,前几篇文章我都没有涉及到配置文件,可是在一个项目中,配置文件又是比不可少的。

       现在假设将Route.php中的默认控制器和Action变为可配置的,怎么弄呢?

       我们使用最简单的方式:

1 <?php
2  $defaultController = 'Index';
3  $defaultAction = 'index';

 

      然后在Route.php中include这个文件:

1 <?php
2 include APP_PATH . '/config.php';
1 $controller = empty($_GET['c']) ? $defaultController : trim($_GET['c']); //设置了默认的控制器
2 $action = empty($_GET['a']) ? $defaultAction : trim($_GET['a']); //设置了默认的Action

当然也可以使用这种方式:

1 <?php
2 return array(
3        'defaultController' => 'Index',
4        'defaultAction' => 'index'
5 );

     还是在Route.php中include:

1 <?php
2 $config = include APP_PATH . '/config.php';
1 $controller= empty($_GET['c']) ? $config['defaultController'] : trim($_GET['c']); //设置了默认的控制器
2 $action = empty($_GET['a']) ? $config['defaultAction'] : trim($_GET['a']); //设置了默认的Action

 

      但是由于配置文件很有可能在整个框架运行过程的各个类都有用到,而前两种方式都只能在某一个类里面的某一个方法中使用,怎么让它在各个类都可以使用呢?

      我们可以可以使用一个static方法来解决,比如专门定义一个Config类来存放配置信息,Config::get来读取配置信息,Config::set来设置配置信息,具体做法读者可以自己去尝试一下。

      当然我不准备采用这种方式,可能当时我看Thinkphp源码的时候被它优雅的特殊函数C迷住了吧,后面我在写Toper的时候也使用了一些特殊的函数,而C主要是负责设置和读取配置信息,个人观点,面向对象是必要的,但是不是什么都要面向对象,所以我准备定义一个function.php来存放一些公有的函数,我把它称为公有函数库。

      由于有了公有函数库,我们可以将上一篇里面的自动导入(__autoload)也转移到这个文件中,因为在Route.php出现一段__autoload的代码还是挺诡异的!!

      好了,怎么实现刚才我们说的通过一个函数来实现配置信息的设置和读取呢?

      好了,先展示我在Toper中的实现吧:

01 function C($name = null,$val = null) {
02     static $_config = array();
03     if(empty($name)) {
04         return $_config;
05     } elseif(is_string($name)) {
06         if(empty($val)) {
07             if(!strpos($name,'=>')) {
08                 //一维
09                 return isset($_config[$name]) ? $_config[$name] : null;
10             } else {
11                 //目前只支持二维
12                 $name = explode('=>',$name);
13                 returnisset($_config[$name[0]][$name[1]]) ? $_config[$name[0]][$name[1]] : null;
14             }
15         } else {
16             if(!strpos($name,'=>')) {
17                 //直接设置
18                 $_config[$name] = $val;
19             } else {
20                 //设置二维
21                 $name = explode('=>',$name);
22                 $_config[$name[0]][$name[1]] = $val;
23             }
24         }
25     } elseif(is_array($name)) {
26         foreach($name as $key=>$value) {
27             $_config[$key] = $value;
28         }
29         return ;
30     } else {
31         throw new Exception('参数类型出错');
32         return ;
33     }
34 }

 

         看着代码挺长的,实际上原理很简单,如果传递的参数只有一个,那么第二个参数就调用默认参数,即NULL,再识别是否第一个参数是否是字符串,那么这个函数就识别为读取,如果第二个参数不为空或第一个参数为数组,那么就识别为设置!!

         由于我自己现在比较懒,而且我用这个函数用的函数蛮顺手的,所以在这儿我就直接用这个函数来作为例子了,更多内容可以查看Toper的/Library/Toper/function.php。

         比如现在要读取defaultController,那么只要使用C('defaultController')即可,如果要设置,那么使用C('defaultController','Index')!!!

          现在我们只需要在入口文件中导入这个function.php即可:

 

1 <?php
2 defined('APP_PATH') define('APP_PATH',dirname(__FILE__) . '/..');
3 defined('FRAMEWORK_PATH') define('FRAMEWORK_PATH',APP_PATH . '/Library/Test');
4 defined('MODULES_PATH') define('MODULES_PATH',APP_PATH . '/UserApps/Modules');
5 include FRAMEWORK_PATH . '/function.php';
6 include FRAMEWORK_PATH . '/Route.php';
7 Route::run();

         大家可能注意到了,C函数最开始的时候,里面没有存放任何元素,那么我们怎么样进行初始化,将配置文件的内容写入C函数呢?

 

          之前我们将配置文件存放在项目根目录,这样实际上是不符合之前我们的约定的规范,所以现在讲这个配置文件剪切到/UserApps/Configs目录下面,为了更方便的使用这个路径,我们定义一个CONFIGS_PATH来指向配置文件的路径。

        现在我们看看入口文件变成了什么样了:

 

1 <?php
2 defined('APP_PATH') define('APP_PATH',dirname(__FILE__) . '/..');
3 defined('FRAMEWORK_PATH') define('FRAMEWORK_PATH',APP_PATH . '/Library/Test');
4 defined('MODULES_PATH') define('MODULES_PATH',APP_PATH . '/UserApps/Modules');
5 defined('CONFIGS_PATH') define('CONFIGS_PATH',APP_PATH . '/UserApps/Configs');
6 include FRAMEWORK_PATH . '/function.php';
7 C(include CONFIGS_PATH . '/config.php'); //写入配置信息
8 include FRAMEWORK_PATH . '/Route.php';
9 Route::run();

      然后我们修改一下Route.php

 

01 <?php
02 class Route {
03     public static function run() {
04         $controller= empty($_GET['c']) ? C('defaultController') : trim($_GET['c']); //设置了默认的控制器
05         $action= empty($_GET['a']) ? C('defaultAction') : trim($_GET['a']); //设置了默认的Action
06         $controllerBasePath = APP_PATH . '/UserApps/Modules/Controllers/';
07         $controllerFilePath = $controllerBasePath . $controller . 'Controller.php';
08         if(is_file($controllerFilePath)) {
09             include $controllerFilePath;
10             $controllerName = $controller . 'Controller';
11             if(class_exists($controllerName)) {
12                 $controllerHandler = new $controllerName();
13                 if(method_exists($controllerHandler,$action)) {
14                     $controllerHandler->$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 }
时间: 2024-12-03 19:28:02

一步步编写PHP的Framework(五)的相关文章

一步步编写PHP的Framework(十五)

  从今天开始我们开始介绍模型,模型是一个框架中非常重要的一块儿,控制器实际上不能进行数据的处理,这种处理的过程我们全部放在模型这一块儿来做.         如果是Java,即使是没用框架,它的模型这一块儿也挺复杂的,首先编写service接口,然后写实现,然后定义DAO接口,DAO实现,然后定义这几层之间传输数据的Domain,一般我认为它就是一个POJO.         Java这种契约式的编程方式很不错,即使后面的实现类发生改变,接口没有改变,代码的修改的量也不是很多.        

一步步编写PHP的Framework(一)

        框架这个概念可能一开始就吓坏了很多PHP的Coder,其实你只要把一个Framework想明白了,其实也没啥,只是别人功能更复杂,细节考虑的更多,代码质量更高.        框架最重要的一个文件为入口文件,基本上相当于一个总控开关,所有的请求都需要经过这个文件: 1 <?php 2 define('APP_PATH',dirname(__FILE__).'/..'); //应用路径 3 include APP_PATH.'/Library/Toper/Core/FrontCon

一步步编写PHP的Framework(九)

         之前讲到过对于异常的处理机制,最好可以自定义异常,如果debug打开,那么显示具体的调试信息,如果debug关闭,那么将异常记录到日志,然后跳转到错误页,这节课我就主要来讲一下这个异常处理机制.        现在我们定义一个异常的基类,在Toper中为Tp_Exception,在这儿,我就直接叫BaseException吧,那BaseException.php肯定首先是有一个架子的: 1 <?php 2 class BaseException extends Exceptio

一步步编写PHP的Framework(十)

  之前讲了这么多,实际上都只是为框架搭建了一个架子而已,框架里面还没有什么东西, 从今天开始,我就开始从Controller,Model,View这几块儿来分别介绍一下. PS:之前的很多内容我都没有细讲,就比如路由,真正的框架路由肯定不是通过GET方式指定的,而是正则,并且它需要兼容多个Server,多种方式. 我们知道所有的请求都需要经过控制器,所以首先还是说一下控制器. 我们之前已经 说过控制器的概念了,但是这个控制器还是功能太弱了,因为它只是从功能上是控制器,框架并没有为它做任何事情,

一步步编写PHP的Framework(十一)

  之前讲了怎么让实现跳转和请求的转发,当然,也只是很简单的说了一下,更深的内容需要你自己去读一下具体框架的实现. 现在跳转和转发有了,对于模型的编写可以后面再来,那我就先说一下怎么讲数据从控制器传递到视图,之前我们的实现方式非常丑陋: 1 $viewPath = dirname(__FILE__) . '/../views/index.php'; 2 if(file_exists($viewPath)) { 3     include $viewPath; 4 } else { 5     e

一步步编写PHP的Framework(十三)

  上次讲到控制器怎么样将数据传递到视图,今天我就主要说一下在程序中怎么让代码更"安全",之后就转到讲模型,再讲怎么做视图,最后再讲控制器的功能强化.       我再声明一下,我写这个文章只是让大家对PHP的框架编写有一个基本的了解,由于本人技术有限,这个文章是给PHP初学者学习的,所以高手勿喷,还有就是我现在时间也有限,所以每次可能需要两三天才能写一篇,每篇我写的时间也要控制在一个小时以内,由于边写这个文章边编代码,所以代码中可能会存在很多BUG,见谅!!        如果你是一

一步步编写PHP的Framework(十四)

   今天我说一下怎么在框架中over掉这些安全问题.       首先是SQL注入,这个如果你使用的是PDO,我觉得应该没什么问题,如果你使用的还是mysql_*等API,那么你可以在框架中实现bindParameter或者在插入数据库之前进行字符串转义.       前两天把上一篇文章写完之后,Vian在后面留言说到过SQL注入的一个解决方案,就是在在插入DB之前进行'''.addslashes($id).''',它的意思就是首先进行addslashes操作,之后再强制单引号包裹,这样它就是

一步步编写PHP的Framework(十六)

  我把模型分成了几块儿,A,B,C,D,E,F,这几块儿分别代表了什么呢?       首先A,这个Base代表的就是整个框架的基类,所有的模型文件都必须继承自这个基类:       由于B的内容需要依赖D,所以先说一下D,D首先有一个ConnectionManager,它负责管理数据库的连接和关闭还有数据库驱动的选择,这个命名自己感觉不太好,先就将就吧,既然它负责数据库的连接和关闭,肯定它就有以下方法: 1 <?php 2 public class ConnectionManager { 3

一步步编写PHP的Framework(十七)

   由于模型中D这一部分是比较基础的,所以我们先把D这一部分做了. D中最重要的是驱动类的编写,所以我们就先写驱动类,由于在驱动类中需要用到日志,所以我们先做一个简单的Logger类,这个类只有一个log的静态方法,如果debug开启,那么直接在浏览器上面输出信息,否则记录到日志中. 01 <?php 02 class Logger extends Base { 03     public static function log($param) { 04         if(is_objec