美文网首页
php的类的自动加载和控制器消息转发

php的类的自动加载和控制器消息转发

作者: 鸿雁长飞光不度 | 来源:发表于2018-09-30 14:35 被阅读0次

1.类的自动加载

在php中引入文件可以使用require或者include关键字,但是如果类非常多的话,手动引入十分麻烦,所以提供了一种便利的方式,通过
spl_autoload_register函数,这个函数可以注册一个函数,用来在系统调用一个不存在的类的时候进行处理,可以在这个函数中进行处理,因为涉及到自动加载,必然有类的命名要有规则,因为命名空间是有层次的,目录结构也是有层次的,我们完全将命名空间解析成目录,然后加载文件,对于命名空间和目录不匹配的情况也可以通过自己定义映射关系找到。下面结合php的反射,模拟实现了thinkphp消息向控制的转发,动态参数注入,initialize方法。

/**
 * 文件名和类名相同,大驼峰原则
 * 命名空间名和文件夹名相同(全部小写)
 * m=index?a=index
 */

class PsrAutoLoad{

    protected static $classPaths = [

    ];

    protected static $map = [

    ];
    function __construct()
    {
        spl_autoload_register([$this,'autoload']);
    }
    //调用一个不存在的类的时候会到这里来,得到类的名字
    protected function autoload($className)
    {
        if (isset(self::$classPaths[$className])){
            $classPath = self::$classPaths[$className];
        }else{
            $classPath = $this->getClassPath($className);
            if (file_exists($classPath)){
                self::$classPaths[$className] = $classPath;
            }else{
              echo $className." Not Found"."\n";
            }
        }
        require $classPath;
    }
    //获取类的文件信息
    protected function getClassPath($className)
    {
        $nameSpace = substr($className,0,strrpos($className,'\\')); //命名空间名
        $className = substr($className,strrpos($className,'\\')+1);//类名
        if (isset(self::$map[$nameSpace])){
            $classPath =  __DIR__.DIRECTORY_SEPARATOR.self::$map[$nameSpace].DIRECTORY_SEPARATOR.$className.".php";
        }else{
            $classPath = __DIR__.DIRECTORY_SEPARATOR.str_replace('\\','/',$nameSpace).DIRECTORY_SEPARATOR.$className.".php";
        }
        return $classPath;
    }

    //手动添加映射
    public static function addMap($space,$path = null,$isOverride = false)
    {
        if (is_string($space)){
            if (is_null($path)){
                unset(self::$map[$space]);
            }else{
                if (!isset(self::$map[$space]) || $isOverride){
                    self::$map[$space] = $path;
                }
            }
        }elseif (is_array($space)){
            if (empty(self::$map) || $isOverride){
                self::$map = $space;
            }else{
                self::$map = array_merge(self::$map,$space);
            }
        }

    }
}


function index()
{
    $m = isset($_GET['m'])?$_GET['m']:'index'; //类名
    $a = isset($_GET['a'])?$_GET['a']:'index'; //方法
    new PsrAutoLoad();
    PsrAutoLoad::addMap([
        'controller' => 'app/controller'
    ]);
    $m  = '\\controller\\'.ucfirst($m); //模拟通过index入口进来访问的命名空间下的类
    $reflect = new ReflectionClass($m);
    if ($reflect->hasMethod($a)){
        $instance = new $m();
        $method = $reflect->getMethod($a);
        $params = $method->getParameters();
        if (!empty($params)){
            $dynamicParams = [];
            foreach ($params as $param){ //param 为 ReflectionParameter
               $class  =  $param->getClass();
               $val = null;
               if ($class){ //如果参数是类
                    $className = $class->getName();
                    $val = new $className();
               }else{
                    $paramName = $param->getName();
                    $val = isset($_GET[$paramName])?$_GET[$paramName]:null;
               }
               $defaultValue = $param->isDefaultValueAvailable()?$param->getDefaultValue():null;
               $dynamicParams[] = $val?$val:$defaultValue;
            }
            if ($reflect->hasMethod('__initialize')){
                call_user_func([$instance,'__initialize']); //有前置方法前置调用
            }
            $method->invokeArgs($instance,$dynamicParams);
        }else{
            $method->invoke($instance);
        }
    }else{
        echo 'Class '.$m.' method '.$a.' not found !!';
    }
}
index();

<?php
namespace controller;
use app\lib\Request;
/**
 * Created by PhpStorm.
 * User: guodong
 * Date: 2018/9/28
 * Time: 下午3:03
 */
class Index
{
    //调用每个方法前自动调用的方法
    public function __initialize()
    {
        echo '通用调用';
    }
    public function index(Request $request, $name)
    {
        var_dump($request->getParams());
        echo $name;

        echo '这是'.__CLASS__.'类的'.__METHOD__.'方法'."\n";
    }
    public function index2()
    {
        echo '这是'.__CLASS__.'类的'.__METHOD__.'方法'."\n";
    }
}
<?php

namespace app\lib;
class Request{
    protected $params = [];
    public function __construct()
    {
        $this->params = $_GET;
    }
    public function getParams()
    {
        return $this->params;
    }
}

相关文章

  • php的类的自动加载和控制器消息转发

    1.类的自动加载 在php中引入文件可以使用require或者include关键字,但是如果类非常多的话,手动引入...

  • PHP 使用总结

    自动类加载 (auto-load) 自动类加载说白了就是自动 include / require php 文件,这...

  • 自己编写PHP框架需要考虑的部分

    1. MVC2. 自动加载: PHP: 自动加载类;3. 错误处理:http://php.net/manual/z...

  • PHP 懒加载哪些事儿

    PHP自动加载 此篇文章主要介绍加载的php类的方式,以及自动加载的几种模式;题外话:大家空了可以多看看别人写的框...

  • PHP Composer详解

    PHP composer php composer的作用 composer是如何实现类的自动加载 composer...

  • php类的自动加载

    本例尝试分别从MyClass1.php和MyClass2.php文件中加载MyClass1和MyClass2类。 ...

  • PHP类的自动加载

    1、为什么需要类的自动加载 很多开发者写面向对象的应用程序时,对每个类的定义,都建立一个独立的 PHP 源文件,方...

  • php的类自动加载

    本文分为两部分:第一部分讲__autoload()函数实现的类自动加载。第二部分讲spl_autoload_reg...

  • php 类的自动加载

    spl_autoload_register() 函数可以注册任意数量的自动加载器,当使用尚未被定义的类(class...

  • php——类的自动载入

    PHP的类自动加载机制 手动加载方式像C和C++等语言,在PHP中需要使用另一个文件中的相关的类、方法时,可以使用...

网友评论

      本文标题:php的类的自动加载和控制器消息转发

      本文链接:https://www.haomeiwen.com/subject/uervoftx.html