单入口初级框架的编写入门

项目做多了,自然会多多少少的接触各种框架。一个框架可以写的很简单,也可以写的很复杂,国内比较知名的框架是TP,也有超轻量级的框架speedPHP.

这里,将一个非常框架的编写思路,做个简单记录,想写框架的可以在看了一个简单框架思路后,也尝试自己写一个框架(虽然不会有很大的实用价值,但是还是可以锻炼一些思维的)。

1.需要定义一些常量,一般定义框架或者核心文件的路径,比如:

Define(XPHP_PATH,__DIR__);

作为变量的扩充,可以增加一些其他路径的定义。这里首先定义了框架的核心目录,就是定义文件当前的路径。

2.需要定义自动加载的路径,在框架里面,自动加载是一个非常重要的函数,自动加载使得框架很容易扩充系统本身的类和方法。

   set_include_path(XPHP_PATH.Controller . PATH_SEPARATOR . get_include_path());

   set_include_path(XPHP_PATH.Model . PATH_SEPARATOR . get_include_path());

   set_include_path(XPHP_PATH.View . PATH_SEPARATOR . get_include_path());

 把mvc的文件夹分别写到当前目录下面。

3.写个自动加载函数。因为在上面,系统会自动去寻找目录。

    function loader($file) {

    include $file . ".php";

   }

     spl_autoload_register('loader');

   这里用了SPL函数,实际上如果简单,并不需要接入外部开发的情况下,可以直接用__autoload 自动加载函数。这样,已经默认将include的路径里面的文件全部加载到了当前文件夹,可以随时进行调用。 否则需要对文件一个一个的去include(当引用文件上百个,是一个非常麻烦的事情)

4.因为已经把我们需要的文件全部引入到了当前文件。首页被访问的时候,需要对路由进行分发访问,在老的php文件中,直接通过访问php文件的方式获取访问接口,但是我们现在开发的是单入口,就需要参数来进行调度了.

  最简单的参数调度,我们假设访问路径设置为index.php?c=test&a=index的方式,本意是访问到testController控制器里面的index方法(当然也可以设置其他的路由解析方法,这里我们用了默认的路由解析方法)

parse_str($_SERVER["QUERY_STRING"], $arr); 用这个函数,把后面的变量重组到一个数组中。

这样ca编程了$arr[c]$arr[a]俩个变量

5.我们已经从外部的访问里,得到了路由访问的意图,就是想访问test控制器里面的index方法。设置下$a = $arr[a];$c =$arr[c]

$controller =  new  $c(); 

 $c->$a();

这里直接将变量作为参数,进行实例化,这样外部传入的俩个变量,直接变为了控制对应控制器的action的操作。

6.一般为了安全起见,会对每个非入口直接访问对应的php会加上一个警告

   If(!definded(XPHP)) header(Location://);

  这样访问任何没有授权的目录的文件的时候,都会自动跳转到默认的首页访问。

7.基本的路由解析和分发,还有自动加载完成了,基本上一般我们使用的框架模式,就是这种。然后会对功能进行各种拓展。

  我们需要写三个额外的基础方法一般是ControllerBase;ModelBase,ViewBase。这三个基础方法,主要封装我们框架的一些共性使用。

然后在开发的每种文件里继承自己对应的基类,就可以开始进行开发。

8.基本的雏形设置后,如果需要引入数据库,一般需要增加额外的config.php文件,一般用来配置数据库和一些设置。然后同时需要引入mysqlDb.class.php (这个类基本是封装一些常用的mysql操作类)因为我们本身框架很简陋,我们仅仅需要封装简单的CURD功能就可以(TP封装了大量的自身方法,方便入门的同时,也加重了PHP执行的负担)

9.最后,由于我们在访问的时候,经常会有各种访问错误(访问错误需要进行友好的提示)PHP本身的提示是不友好的,很容易暴露我们使用的PHP版本等信息。需要加入一个错误控制,(当然,也可以用错误捕捉try..catchset_error_handle(‘’该函数的用法和SPL函数一样。

10.这样,一个初步的MVC框架模型已经出来了。如果仅仅是测试使用,你已经可以将其用在自己内部访问的项目上。

下面是一个MVC样例:(代码放在一个文件里)

<?php
//定义版本号
define('XPHP_VERSION', 1);
//打印开发函数
function p($val) {
    echo "<pre>" . print_r($val, true) . "</pre>";
    exit;
}
/**
 * PHP脚本执行后退出时候执行的函数
 */
function endExc() {
    return '';
}
/**
 * 输出字段映射转换
 * 
 */
function  tranfer($str1,$str2) {
     $arr1 =  explode(",",$str1) ;
     $arr2 =  explode(",",$str2) ;
      $ct = count($arr1);
     
     for($i=0;$i<$ct;$i++) {
        $rtarr[]= $arr1[$i].' as '.$arr2[$i];        
     }
     $rtstr = join($rtarr,",");
    return   $rtstr;
}

//定义核心目录与路径
define('SYS_PATH', dirname(__FILE__) . "\\");
define("XPHP_PATH", SYS_PATH . 'xphp\\');
//将核心目录写入默认路径
set_include_path('sys/xphp' . PATH_SEPARATOR . get_include_path());
//自动加载函数(没有指定路径的情况下 会自动从include的路径中对文件进行加载)
function loader($file) {
    include $file . ".php";
}
spl_autoload_register('loader');
register_shutdown_function('endExc');
//set_error_handler('errFun');
//解析路由器
parse_str($_SERVER["QUERY_STRING"], $arr);
if (@$arr['c']) {
    $c = $arr['c'] . "Controller";
} else {
    $c = 'BaseController';
}
if (@$arr['a']) {
    $a = $arr['a'];
} else {
    $a = 'index';
}
//全局变量设置数据库
$_Xconfig = array(
    'DBHOST' => 'localhost',
    'DBNAME' => 'mysql',
    'DBUSER' => 'root',
    'DBPWD' => 'root',
);

$config = array(
    'test'=>'12'
    
);
//递归合并配置
function     MergeRecursive(&$arr,&$arr2) {       
      foreach($arr2 as  $key=>$value ) {
            if(isset($arr[$key])&&ia_array($value)&&is_array($arr[$key])) {
               $arr[$key] = MergeRecursive($arr[$key],$arr2[$key]);
	    } else {
                $arr[$key] = $value;
	     }
     }   
     }

MergeRecursive($_Xconfig,$config);

//路由分发
$xphp = new $c();
$xphp->$a();
/**
 * 基础框架类
 */
class BaseController {
    public function index() {
        echo "Welcom To  XPHP World";
    }
    public function test() {
        $model = new BaseModel();
        $model->test();        
    }
}
/**
 * 基础model,链接mysql
 */
class BaseModel {
    public function test() {
        global   $_Xconfig;
        $host = $_Xconfig['DBHOST'];
        $dbuser = $_Xconfig['DBUSER'];
        $pwd = $_Xconfig['DBPWD'];
        $sqlModel = new MysqlDbModel();
        $xcon = $sqlModel->xconnect($host,$dbuser,$pwd);
        //字段映射
        $str = tranfer("host,user","ip,name");    
        $arr = $sqlModel->select("select $str from mysql.user limit 1");
       print_r($arr);
       $funName =__FUNCTION__;
        BaseView::display($funName);
    }
    public function add() {      
    }

}
/**
 * 基础模板引擎设置
 */
class  BaseView  {
    
    public static function   display($pathname) {
        @require  'view//'.$pathname.".php";
    }   
}

/**
 * 基础的mysql数据操作model
 * 
 */
class MysqlDbModel {
    public $xcon = '';
    /**
     * 数据库的连接
     * @param type $hostname
     * @param type $username
     * @param type $passwrod
     * @return type
     */
    public function xconnect($hostname, $username, $password) {       
        //在php5.5以后继续使用该方法会提示一个不安全的警告错误,如果继续使用,需要@将该行错误关闭
        $this->xcon = @mysql_connect($hostname, $username, $password);
        return @mysql_connect($hostname, $username, $password);
    }

    /**
     * 对不同的数据库连接进行执行
     * @param type $sql
     * @param type $xcon
     */
    public function query($sql) {
        $res = mysql_query($sql, $this->xcon);
        return $res;
    }

    /**
     * 读取多行数据进行列表查询
     * 返回对应的数组
     * @param type $sql
     * @return type
     */
    public function select($sql) {
        $rtArr = array();
        $res = $this->query($sql);
        while ($list = mysql_fetch_assoc($res)) {
            $rtArr[] = $list;
        }
        return $rtArr;
    }
    /**
     * 关闭数据连接的时候进行使用
     * 
     */
    public function close() {
        mysql_close($this->xcon);
    }
}


转载于:https://my.oschina.net/xiongyuanliang/blog/529798

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值