4、对象工具

    4.1、PHP与包

    低版本的PHP5,我们可以通过包结构的文件系统来组织类。

    require_once ‘util/xujiajun1.php’;

    require_once ‘util2/xujiajun2.php’;

    PHP5.3命名空间引入

    example:

    4.2、类函数和对象函数

    PHP提供了一系列强大的函数来检测和对象

    查找类
    example:

    1. $className = "superu";
    2. if (!class_exists($className))
    3. {
    4. throw new Exception("No such class $className");
    5. }
    6. //当然,我们无法确定该类的构造方法是否需要参数。在这个级别的安全上,应该求助反射api

    PHP有很多用于检测对象类型的基本工具。首先,可以使用get_class()函数检查对象的类,他接受任何对象作为参数。

    example:

    1. $person = new Xujiajun();
    2. if(get_class($person) == "Xujiajun")
    3. {
    4. print "$person is a Xujiajun object\n";
    5. }

    我们有时候只想确定一个类的类型,比如只想知道是不是Person这个类的,我们不关心是不是Xujiajun还是Superu。
    为此,PHP提供了instanceof这个操作符。

    example:

    1. $person = new Person();
    2. if($person instanceof Person)
    3. {
    4. echo "$person is a Person object\n";
    5. }

    我们如果需要知道类中的方法,怎么办?PHP提供了get_class_methods()函数得到一个类中的所有方法列表。

    1. <?php
    2. class Xujiajun
    3. {
    4. public function getAge()
    5. {
    6. # code...
    7. }
    8. public function getFullName()
    9. {
    10. # code...
    11. }
    12. }
    13. $p = new Xujiajun();
    14. var_dump(get_class_methods($p));
    15. array(2) {
    16. [0] =>
    17. string(6) "getAge"
    18. [1] =>
    19. string(11) "getFullName"
    20. }

    注意:只有声明成public的方法才会显示哦。

    如果我们要检测某一个方法是否存在,用以上这个get_class_method当然可以做到:

    其实PHP有更加专业的工具:method_existsis_callable,

    example:

    1. //is_callable()
    2. if (is_callable(array($p, "getAge"))) {
    3. echo $p->getAge(); // 18
    4. }
    5. //method_exists()
    6. if (method_exists($p, "getAge")) {
    7. echo $p->getAge();// 18
    8. }

    注意以上两者区别:如果getAge方法改成private、protected,is_callable返回是false,而method_exists返回true

    了解类属性
    我们既然可以查询类的方法,当然我们也可以查询类的属性。PHP提供了get_class_vars函数,参数接收类名。

    example:

    1. class Xujiajun
    2. {
    3. public $age = "18";
    4. }
    5. var_dump(get_class_vars('Xujiajun'));
    6. //输出结果
    7. array(1) {
    8. 'age' =>
    9. string(2) "18"
    10. }

    了解继承

    类函数也允许我们绘制继承关系。我们可以用get_parent_class()来找到一个类的父类。参数为一个类名或者对象。

    example:

    1. class Person
    2. {
    3. }
    4. class Xujiajun extends Person
    5. {
    6. }
    7. var_dump(get_parent_class(new Xujiajun));//string(6) "Person"

    另外也可以用is_subclass_of来检测类是否是另一个类的派生类。它需要一个子类对象(或者类)和父类的名字。

    example:

    1. var_dump(is_subclass_of('Xujiajun', 'Person'));//bool(true)

    比如现在我们要字符串动态调用某一个方法:

    其实,我们可以通过PHP提供的call_user_func()达到相同目的。

    example:

    1. class Xujiajun
    2. {
    3. public function getAge($age = 0)
    4. {
    5. return 18;
    6. }
    7. }
    8. var_dump(call_user_func(array(new Xujiajun,'getAge')));//18
    9. //加参数
    10. var_dump(call_user_func(array(new Xujiajun,'getAge'),2));//20

    当然 call_user_func_array() 更加好用,使用上相同,参数支持数组传参。

    4.3、反射API
    4.3.1、入门

    PHP中的反射API就像Java中的java.lang.reflect包一样。它由一系列可以分析属性、方法和类内置类组成。

    反射API部分列参考

    类 |描述
    ————-|————————————————-
    Relection|为类的摘要信息提供静态函数export()
    RelectionClass|类信息和工具
    RelectionMethod|类方法信息和工具
    RelectionParameter|方法参数信息
    RelectionProperty|类属性信息
    RelectionFunction|函数信息和工具
    RelectionExcetion|错误类
    RelectionExtension|PHP扩展信息

    利用这些反射API的类,可以运行访问对象、函数和脚本中的扩展信息。反射API非常强大,我们应该经常使用API而少使用类和对象函数。

    example:

    php class Person { public function getName() { } } class Xujiajun extends Person { public $age = "18"; public function getAge($arg = 0) { return 18+$arg; } } $reflector = new ReflectionClass('Xujiajun'); $properties = Reflection::export($reflector); var_dump($properties); //输出类似 Class [ <user> class Xujiajun extends Person ] { @@ /private/var/www/demo/foo.php 11-25 - Constants [0] { } - Static properties [0] { } - Static methods [0] { } - Properties [1] { Property [ <default> public $age ] } - Methods [2] { Method [ <user> public method getAge ] { @@ /private/var/www/demo/foo.php 16 - 19 - Parameters [1] { Parameter #0 [ <optional> $arg = 0 ] } } Method [ <user, inherits Person> public method getName ] { @@ /private/var/www/demo/foo.php 5 - 8 } } }
    从例子中可以看出,Relection::export()提供了Xujiajun这个类的几乎所有信息。
    如果我们直接var_dump()一个对象的话,前提要实例化它,而且也不会有细节提供。可见,反射API提供了更高层次的功能。

    4.3.2、类检测

    example:

    1. interface Person
    2. }
    3. $reflector = new ReflectionClass('Person');
    4. var_dump($reflector->isInterface());//bool(true)
    4.3.3、检查方法

    ReflectionClass我们用来检查类,那么检查类中的方法可以用RelectionMethod

    获取RelectionMethod对象的方式有两种:

    0、从RelectionClass::getMethods()获得RelectionMethod对象数组

    1、如果是特定的类方法,RelectionClass::getMethod()接受一个方法名作为参数并返回相应的RelectionMethod对象。

    example:

    1. class Xujiajun
    2. {
    3. public function getName()
    4. {
    5. }
    6. }
    7. $reflector = new ReflectionClass('Xujiajun');
    8. $methods = $reflector->getMethods();
    9. var_dump($methods[0]->isPublic());//bool(true)
    4.3.4、检查方法参数

    在PHP5中声明类方法时可以限制参数中对象类型,因此检查方法的参数变得非常必要。

    example:

    1. class Person
    2. {
    3. public function __construct(Exception $a)
    4. {
    5. }
    6. public function getName()
    7. {
    8. }
    9. }
    10. $reflector = new ReflectionClass('Person');
    11. $methods = $reflector->getMethod('__construct');
    12. $params = $methods->getParameters();
    13. foreach ($params as $key => $param) {
    14. echo argData($param);//$a must be a Foo object
    15. }
    16. function argData(ReflectionParameter $arg)
    17. {
    18. $details = "";
    19. $name = $arg->getName();
    20. $class = $arg->getClass();
    21. if (!empty($class)) {
    22. $className = $class->getName();
    23. $details .= "\$$name must be a $className object\n";
    24. }
    4.3.5、使用反射API