• PHP spl_autoload和class_exsits使用技能


    本文章的PHP使用版本:5.4.7

    PHP建议使用:
    spl_autoload_register
    那么写了一种实现

    文件路径

    • core
      • core.php
      • ChildrenClass.php
      • ParentClass.php
    • test
      • index.php

    core.php:

    
    <?php
    
    /**
     * Created by PhpStorm.
     * User: http://blog.csdn.net/cor_twi
     * Date: 2016/02/25
     * Time: 11:23
     */
    
    
    
    spl_autoload_register(function ($classId)
    {
        $dirname            = dirname(__FILE__);
        $classIdParts       = explode("\", $classId);
        $classIdLength      = count($classIdParts);
        $className          = ($classIdParts[$classIdLength - 1]);
        $defaultNameSpace   = substr(strrchr($dirname,"\"),1); 
        $namespace          = $classIdLength==1? $defaultNameSpace : $classIdParts[0];
    
        for ($i = 1; $i < $classIdLength-1; $i++) {
            $namespace .= '/' . $classIdParts[$i];
        }
        $path = dirname(__FILE__) . "/../" . $namespace . "/" . $className . '.php';
        $realPath = realpath($path);
        #print "autoload:realPath:" .  $realPath."
    ";
    
        if (file_exists($realPath)) {
    
            if(!class_exists($className,false)){
                $ret = include($realPath);
                print "spl_autoload_  autoload:$className is loaded : result = $ret 
    ";
            }
            else
                print "spl_autoload_ autoload:$className is already loaded
    ";
    
        }
    });

    ChildrenClass.php:

    <?php
    namespace CORE;
    use COREParentClass;
    /**
     * Created by PhpStorm.
     * User: http://blog.csdn.net/cor_twi
     * Date: 2016/02/22
     * Time: 9:55
     */
    class ChildrenClass extends ParentClass
    {
        private $varPro_;
        public  function __construct($var01,$var02)
        {
            parent::__construct($var01,$var02);
            $this->varPro_ = "ChildrenClass";
        }
    
    }

    ParentClass.php:

    <?php
    
    /**
     * Created by PhpStorm.
     * User: http://blog.csdn.net/cor_twi
     * Date: 2016/02/22
     * Time: 9:40
     */
    namespace CORE;
    class ParentClass
    {
        public static $variable01;
        public static $variable02;
        protected  $varPro;
        /**
         *constructor
         */
        public function __construct($var1,$var2){
            self::$variable01 = $var1;
            self::$variable02 = $var2;
            $this->varPro = "ParentClass";
        }
    }

    index.php:

    <?php
    /**
     * Created by PhpStorm.
     * User: http://blog.csdn.net/cor_twi
     * Date: 2016/03/05
     * Time: 16:06
     */
    require('../core/core.php');
    
    use COREParentClass;
    use COREChildrenClass;
    
    print "Section01------------------------
    
    ";
    
    
    
    print "
    Section02------------------------
    
    ";
    
    $instance01 = new ChildrenClass('aa','vv');
    $instance02 = new ParentClass('bb','uu');
    
    print "
    Section03------------------------
    
    ";
    print "Class Load Test-----------------------
    ";
    
    if(!class_exists('ChildrenClass')){
        print "
    ************
    Warning : in Section 03 : 
    Class ChildrenClass is not loaded
    ";
    }
    
    $interfaces = class_implements("ParentClass");
    
    print_r($interfaces);
    if(isset($interfaces['ParentClass'])){
        print "OK,PASS";
    }
    else{
        print "NO,IT'S NOT";
    }
    
    
    print "
    Section04------------------------
    
    ";
    if(!class_exists('ChildrenClass')){
        print "
    ************
    TEST : in Section 04 : 
    Class ChildrenClass is not loaded
    ";
    }
    
    $rc =  new ReflectionClass('ChildrenClass');
    try {
        if($rc->implementsInterface('ParentClass')){
            print 'imples';
        }
        print 'parent class:' . $rc->getParentClass();
    }catch(ReflectionException $e){
    
    }

    然后输出结果是:

    J:xamppphpphp.exe E:phpStormWorksphp01	estindex.php
    Section01------------------------
    
    
    Section02------------------------
    
    spl_autoload_  autoload:ParentClass is loaded : result = 1 
    spl_autoload_  autoload:ChildrenClass is loaded : result = 1 
    
    Section03------------------------
    
    Class Load Test-----------------------
    
    ************
    Warning : in Section 03 : 
    Class ChildrenClass is not loaded
    spl_autoload_  autoload:ParentClass is loaded : result = 1 
    
    Warning: class_implements(): Class ParentClass does not exist and could not be loaded in E:phpStormWorksphp01	estindex.php on line 29
    
    Call Stack:
        0.0008     131888   1. {main}() E:phpStormWorksphp01	estindex.php:0
        0.0042     147400   2. class_implements() E:phpStormWorksphp01	estindex.php:29
    
    NO,IT'S NOT
    Section04------------------------
    
    
    ************
    TEST : in Section 04 : 
    Class ChildrenClass is not loaded
    spl_autoload_  autoload:ChildrenClass is loaded : result = 1 
    
    Fatal error: Uncaught exception 'ReflectionException' with message 'Class ChildrenClass does not exist' in E:phpStormWorksphp01	estindex.php on line 46
    
    ReflectionException: Class ChildrenClass does not exist in E:phpStormWorksphp01	estindex.php on line 46
    
    Call Stack:
        0.0008     131888   1. {main}() E:phpStormWorksphp01	estindex.php:0
        0.0079     147816   2. ReflectionClass->__construct() E:phpStormWorksphp01	estindex.php:46
    
    
    Process finished with exit code 255
    

    总结:
    class_implements()
    ReflectionClass()
    class_exists()
    $interfaces = class_implements(‘CORETestImpl’);
    对于当前版本来说:
    这几个类的名字必须写use 的短语 as 的也不行:
    例如:class_exists(‘COREParentClass’)
    $interfaces[‘COREInterf’]
    namespace前面的无所谓
    但是interfaces[‘COREInterf’] 前面的有所谓!!!

    总结
    对于写了namespace的类文件来说,你有两个选择
    要么use namespace要么new 和 instanceof 的时候使用namespace,否则出现Fatal error: Class ‘TestImpl’ not found in 即便它正确触发spl_autoload。【原因见后面<Reason>】
    要么用namespace前缀来使用这个类符号
    如果没有写namespace的呢
    没有写namespace的类文件,可以随意使用他的类名字,自动触发spl_autoload注册的函数。
    对于类或者接口,class_exsits()和interface_exsits()都如果有他们有namespace需要使用它才能返回正确的结果。
    对于class_implements()、ReflectionClass()和implementsInterface(),如果类或者接口具有namespace必须使用带namespace的名称符号来作为参数,否则你将看到:Fatal error: Cannot redeclare class NAMESPACEXXXXClass in
    原因未知:是个bug,经过测试PHP7也有这个问题PHP或许不承认他是个BUG。而且加载器无法检查出来已经被加载。如果你改成class_implements(‘XXXXClass’,false);那么就是[PHP 5.4.7]Warning: class_implements(): Class ChildrenClass does not exist in (即使你写了use)

    PHP7:的报错是
    PHP Fatal error: Cannot declare class COREChildrenClass, because the name is already in use in E:phpStormWorksphp01coreChildrenClass.php on line 29
    PHP Stack trace:
    PHP 1. {main}() E:phpStormWorksphp01 estindex.php:0
    PHP 2. class_implements() E:phpStormWorksphp01 estindex.php:93
    PHP 3. spl_autoload_call() E:phpStormWorksphp01 estindex.php:93

    <Reason>:由现象倒推而来,所有的PHP版本,对于有namespace的类或者接口,它是以 带namespace的形式autoload的,不管你写不写use

    如果用include_once(),那么不在本文研究范围之内

    写的时候手贱文章弄没有了一次,重写之。
    测试结论仅供参考。
    附上spl_autoload_实现:

    <?php
    
    /**
     * Created by PhpStorm.
     * User: http://blog.csdn.net/cor_twi
     * Date: 2016/02/25
     * Time: 11:23
     */
    
    
    
    spl_autoload_register(function ($classId)
    {
        $dirname            = dirname(__FILE__);
        $classIdParts       = explode("\", $classId);
        $classIdLength      = count($classIdParts);
        $className          = ($classIdParts[$classIdLength - 1]);
        $defaultNameSpace   = substr(strrchr($dirname,"\"),1); //here is core
        $namespace          = $classIdLength==1? $defaultNameSpace : $classIdParts[0];
    
        for ($i = 1; $i < $classIdLength-1; $i++) {
            $namespace .= '/' . $classIdParts[$i];
        }
        $path = dirname(__FILE__) . "/../" . $namespace . "/" . $className . '.php';
        $realPath = realpath($path);
        #print "autoload:realPath:" .  $realPath."
    ";
    
    
        if(class_exists($classId,false)||interface_exists($classId,false)){
    //如果代码能进来这个函数说明没有被加载,便不会执行到这里,无法阻止Fatal error: Cannot redeclare class
            print "spl_autoload_  preCheck:$className | $classId | is already loaded
    ";
        }
    
    
        if (file_exists($realPath)) {
    
            if(class_exists($className,false)||interface_exists($className,false)){
    
                print "spl_autoload_  autoload:$className | $classId | is already loaded
    ";
            }
            else{
                print "spl_autoload_  autoload: try to load $className | $classId |
    ";
                if ( false ===  include($realPath))
                    print "spl_autoload_  autoload:$className | $classId | failed to be loaded
    ";
                else
                    print "spl_autoload_  autoload:$className | $classId | is loaded
    ";
            }
    
    
        }
    });
  • 相关阅读:
    11.爱吃皮蛋的小明(斐波那契数列)
    10.二叉树最大宽度和高度
    9.二叉树的序遍历
    8.递归第一次
    6.数的计算(递归算法)
    5.十进制转m进制
    数论——快速幂(C++)
    最短路径——SPFA算法(C++)
    最小环——Floyd变种算法(C++)
    数论——质因数分解(C++)
  • 原文地址:https://www.cnblogs.com/slankka/p/9158530.html
Copyright © 2020-2023  润新知