从零开始写自己的PHP框架系列教程[前言]

我觉得程序员进步的理由:多看->多写->多总结

我自我介绍下,我不是程序员,但是我爱编程,作为业余程序员自己写框架让人感到兴奋的,目前有很多框架(js有jQuery、Express、socket.io.js等;PHP有phpword、Yii、laravel;html里面有bootstrap、bootcss、normal)。为了让别人称我为“大师”,我写框架来试试。

框架(framework)是一个基本概念上的结构,用于去解决或者处理复杂的问题。这个广泛的定义使用的十分流行,尤其在软件概念,框架也能用于机械结构。

话不多说,直接说重点:

框架适用范围:中小型网站建设、功能实现等,一个简单,缩小版的thinkphp框架

框架结构:

-核心目录

---[core.php]框架加载文件

------[cache.php]缓存文件

------[config.php]配置文件

------[controller.php]控制文件

------[hook.php]钩子文件

------[model.php]模型文件

------[route.php]路由文件

------[storage.php]储存文件

------[mysql.php]数据文件

------[template.php]模板文件

大概就是这几个类,我的思维就从这几个类开始,一步一步来写,首先设置目录,我是这样设计的:

首先要说的就是PHP的命名空间:

知识点:命名空间是一种封装事物的方法。在很多地方都可以见到这种抽象概念,对于目录中的文件来说,它就扮演了命名空间的角色。

代码案例:

namespace my\name; // 参考 "定义命名空间" 小节

class MyClass {}
function myfunction() {}
const MYCONST = 1;

$a = new MyClass;
// 参考 "全局空间" 小节
$c = new \my\name\MyClass; 

知识点在空间中的运用:

我们这里主要运用在PHP的spl_autoload_register(点击就可以看到该函数的介绍)函数中,这里我们直接上代码

function auto_load($class) {
    static $fileList = array();
  //定义命名空间对应的路径
    $prefixes =array(
        'framework' => realpath(__DIR__.'/../').DIRECTORY_SEPARATOR,
        'controller'=>realpath(__DIR__).'/../extend'.DIRECTORY_SEPARATOR,
        'model'=>realpath(__DIR__).'/../extend'.DIRECTORY_SEPARATOR,
        'hook'=>realpath(__DIR__).'/../extend'.DIRECTORY_SEPARATOR,
        'admin' => ROOT_PATH,
        '*' => ROOT_PATH,
        
    );
    //分割命名空间
    $class = ltrim($class, '\\');
    if (false !== ($pos = strrpos($class, '\\')) ){
        $namespace = substr($class, 0, $pos);
        $className = substr($class, $pos + 1);
        
        //循环自动加载的目录
        foreach ($prefixes as $prefix => $baseDir){
            if ( '*'!==$prefix && 0!==strpos($namespace, $prefix) ) continue;

            //根据namespace分割路径和文件名字
            $fileDIR = $baseDir.str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR;
            
            if( !isset($fileList[$fileDIR]) ){
                $fileList[$fileDIR] = array();
                foreach(glob($fileDIR.'*.php') as $file){
                    $fileList[$fileDIR][] = $file;
                }
            }
            
            $fileBase = $baseDir.str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR.$className;
            foreach($fileList[$fileDIR] as $file){
                if( false!==stripos($file, $fileBase) ){
                    require $file;
                    return true;                
                }
            }                            
        }           
    }
    return false;
}

有了这个自动加载函数我们就可以在定义命名空间后自动加载对应目录的文件

 

其次要说的就是实例化对象:

知识点:类的实例化就是对象。类可以大致分为一个是静态描述,另外一个是动态描述,当然还有抽象类等。我们这里不介绍

代码案例:

<?php
class Person
{
    //下面是人的成员属性
    var $name; //人的名字
    var $sex; //人的性别
    var $age; //人的年龄
 
    //下面是人的成员方法
    function say() { //这个人可以说话的方法
        echo "这个人在说话";
    }
 
    function run() { //这个人可以走路的方法
        echo "这个人在走路";
    }
}
 
$p1=new Person();
$p2=new Person();
$p3=new Person();
?>

以上代码就是实例化的过程,静态方法及静态方法可以点击链接查看

为什么我们这里要讲类呢?如果你使用过thinkphp 你肯定知道M方法或者R方法,我们这里就要自定义这种方法,下面直接上函数

function obj($class, $layer = 'model'){
    static $objArr = array();
        //这里的参数$class就是命名空间
    $param = explode('/', $class, 2);
    $paramCount = count($param);
    switch ($paramCount) {
        case 1:
            $app = APP_NAME;
            $module = $param[0];
            break;
        case 2:
            $app = $param[0];
            $module = $param[1];
            break;
    }
        //转换成小写字符
    $app = strtolower($app);

    
        //路径拼接
    $class = "\\{$app}\\{$module}";
    
    if(!class_exists($class)){
        $class = "\\app\\{$app}\\{$layer}\\{$module}".ucfirst($layer);;
    }
    

    if(isset($objArr[$class])){
        return $objArr[$class];
    }
    
    if(!class_exists($class)){
        throw new \Exception("Class '{$class}' not found'", 500);
    }

    $obj = new $class();
    $objArr[$class] = $obj;
    return $obj;
}

这样就实现了空间上方法的调用,好了知识点我们讲完了,下一节就开始写框架核心

 

 

posted @ 2017-10-21 19:24  一碗范特西  阅读(313)  评论(0编辑  收藏  举报