明天咱们持续来学习 SPL 中的内容,这篇文章的内容是比较简单的对于 SPL 中所提供的一系列函数相干的内容。其实在之前的不少文章中咱们都曾经接触过一些 SPL 中提供的函数了。这次咱们就具体地再好好学习一下。
类信息相干函数
类信息相干的函数次要都是查看一些类的信息的函数,并没有什么操作类性能的函数。
类的继承、接口、个性查看
首先,咱们来看一下,如果想要取得以后类实现了哪个接口,那么咱们就间接应用一个 class_implements() 就能够了。
interface A {}interface B {}class TestA implements A,B {}var_dump(class_implements(new TestA));// array(2) {// ["A"]=>// string(1) "A"// ["B"]=>// string(1) "B"// }
能够看到,它返回的是一个数组,显示的就是咱们以后这个类对象所实现的接口名称。如果咱们查问的类没有实现任何接口,那么它返回的就是空的数组。
var_dump(class_implements(new stdClass()));// array(0) {// }
同样,咱们还能够查看某个类对象的父类。
class C{}class TestB extends C {}var_dump(class_parents(new TestB));// array(1) {// ["C"]=>// string(1) "C"// }
虽说 PHP 是单继承型的语言,但应用 class_parents() 这个函数仍然返回的是一个数组。如果类对象没有父类的话,那么也同样返回的是一个空的数组。
class TestC { use D, E;}var_dump(class_uses(new TestC));// array(2) {// ["D"]=>// string(1) "D"// ["E"]=>// string(1) "E"// }
最初,咱们还能够通过 class_uses() 函数来获取到以后类对象所应用的 trait 个性信息。
类的哈希及类ID
做过 Java 开发的同学肯定都见过所有的类都会有一个 hashCode() 办法。这个办法在 Java 中的作用就是返回一个对象的 Hash 码值。通常用于对象是否相等以及惟一的判断,在 Java 中,所有的类都会默认继承自 Object 这个基类,而这个基类中就自带这个办法。
然而,在 PHP 中,类是没有这样一个全局基类的,天然也就没有这样的办法。显然,只能靠其余的扩大工具帮咱们提供这样的能力了。好巧不巧,SPL 中正好就提供了这样的性能。
var_dump(spl_object_hash(new TestA));// string(32) "000000000ed109570000000025e36d74"$a = new TestA;var_dump(spl_object_hash($a));// string(32) "000000000ed109570000000025e36d74"var_dump(spl_object_id(new TestA));// int(2)var_dump(spl_object_id($a));// int(1)
spl_object_hash() 函数就是用于获取一个对象的 Hash 值的,它是残缺 Hash 值,不像 Java 的 hashCode() 办法返回的是数字类型的值。同样的类模板所实例化的对象返回的内容是一样的。
spl_object_id() 返回的是对象的 ID 。它的后果对于不同的 new ,也就是实例化的对象来说是不同的。如果对象始终存在,那么它的 ID 值是不会发生变化的,而对象被销毁的话,则 ID 值也会被回收并交给其它对象应用。其实间接打印对象咱们就能够看到这个 ID 值。
var_dump($a);// object(TestA)#1 (0) {// }var_dump(new TestA);// object(TestA)#2 (0) {// }
井号前面的那个数字就是咱们对象的 ID 值,也就是 spl_object_id() 所取得的内容。
获取 SPL 库中的所有可用类信息
这个函数返回的是 SPL 这个库中所有的能够应用的类名信息。
var_dump(spl_classes());// array(55) {// ["AppendIterator"]=>// string(14) "AppendIterator"// ["ArrayIterator"]=>// string(13) "ArrayIterator"// ["ArrayObject"]=>// string(11) "ArrayObject"// ["BadFunctionCallException"]=>// string(24) "BadFunctionCallException"// ["BadMethodCallException"]=>// string(22) "BadMethodCallException"// ["CachingIterator"]=>// string(15) "CachingIterator"// ["CallbackFilterIterator"]=>// string(22) "CallbackFilterIterator"// ["DirectoryIterator"]=>// string(17) "DirectoryIterator"// ["DomainException"]=>// string(15) "DomainException"// ["EmptyIterator"]=>// string(13) "EmptyIterator"// ["FilesystemIterator"]=>// string(18) "FilesystemIterator"// ["FilterIterator"]=>// string(14) "FilterIterator"// ["GlobIterator"]=>// …………………………// …………………………
能够看到,咱们后面讲过的许多类信息在这里都能够看到。
迭代器相干函数
迭代器相干的函数在上一篇文章讲迭代器的时候其实曾经呈现过了,那就是十分好用的 iterator_to_array() 这个函数。
$iterator = new ArrayIterator(['a'=>'a1', 'b'=>'b1', 'c'=>'c1']);var_dump(iterator_to_array($iterator, true));// array(3) {// ["a"]=>// string(2) "a1"// ["b"]=>// string(2) "b1"// ["c"]=>// string(2) "c1"// }
咱们能够设想成在这个函数外部,其实就是应用 foreach() 遍历了一下这个迭代器,并将所有的后果放在数组中返回回来。这个函数还有第二个参数,它的作用是让键不应用原来的键值,而是应用默认数组下标的形式排列。
var_dump(iterator_to_array($iterator, false));// array(3) {// [0]=>// string(2) "a1"// [1]=>// string(2) "b1"// [2]=>// string(2) "c1"// }
除了间接取得迭代器遍历的后果之外,咱们还能够通过一个函数间接获取迭代器外部元素的数量。
var_dump(iterator_count($iterator)); // int(3)
其实 iterator_count() 这个函数就像是 count() 函数的迭代器版本。
function printCaps($iterator){ echo strtoupper($iterator->current()), PHP_EOL; return true;}iterator_apply($iterator, "printCaps", array($iterator));// A1// B1// C1
最初这个 iterator_apply() 函数就是让咱们能够通过一个指定的回调函数来遍历一个迭代器。
主动加载相干函数
对于主动加载函数来说,咱们在最早的文章,也就是讲 Composer 的那一系列文章中就曾经接触过了。不过过后咱们只是学习了一个 spl_autoload_register() 函数。明天咱们就来多学习两个函数,不过首先还是来看看 spl_autoload_register() 函数的应用。
function autoloadA($class){ if(is_file('./autoloadA/' . $class . '.php')){ require_once './autoloadA/' . $class . '.php'; } }spl_autoload_register('autoloadA');spl_autoload_register(function($class){ if(is_file('./autoloadB/' . $class . '.php')){ require_once './autoloadB/' . $class . '.php'; }});$sky = new Sky();$sky->result();// This is Sky PHP!$planet = new Planet();$planet->result();// This is Planet PHP!
在这段测试代码中,咱们通过回调函数和匿名函数两种模式注册了两个 spl_autoload_register() 。这样当咱们应用以后文件中未定义的类时就会去这两个 autoload 中查找。在之前讲 Composer 时咱们就讲过,spl_autoload_register() 比 \_\_autolod() 好的中央就是它保护的是一个主动加载列表,相当于是多个 \_\_autoload() 的性能。咱们通过另外一个函数就能够看到以后咱们曾经注册了多少个主动加载的函数。
var_dump(spl_autoload_functions());// array(2) {// [0]=>// string(9) "autoloadA"// [1]=>// object(Closure)#3 (1) {// ["parameter"]=>// array(1) {// ["$class"]=>// string(10) "<required>"// }// }// }
当然,可能一直的注册进来也能够删除掉。
spl_autoload_unregister('autoloadA');var_dump(spl_autoload_functions());// array(1) {// [0]=>// object(Closure)#3 (1) {// ["parameter"]=>// array(1) {// ["$class"]=>// string(10) "<required>"// }// }// }
对于 spl_autoload_register() 在理论工程中的利用,也就是 Composer 中的利用,有趣味的同学能够移步之前的文章。
- 深刻学习Composer原理(一)https://mp.weixin.qq.com/s/fHWBqDu4xrixMhxh3eftkA
- 深刻学习Composer原理(二)https://mp.weixin.qq.com/s/KzRSF12WzFvHqpdHFSk_3w
- 深刻学习Composer原理(三)https://mp.weixin.qq.com/s/jkNf8_HU3swnMH4pFMyADA
- 深刻学习Composer原理(四)https://mp.weixin.qq.com/s/EEDjqzLcKaAJhQ-VWDBX8w
总结
怎么样,一路看下来是不是发现其实不少的性能大家在日常的开发学习中都曾经接触过了。这些函数就是 SPL 扩大库中所提供的性能了,其实通过这几篇文章的学习,咱们就曾经发现了,SPL 扩大库为咱们提供的都是很根底的一些 数据结构 、迭代器、设计模式 之类的性能封装,有很多货色真的比本人实现要简略不便很多,包含咱们下一篇还要持续学习的文件操作以及设计模式的实现。
测试代码:
https://github.com/zhangyue0503/dev-blog/blob/master/php/2021/01/source/6.PHP的SPL扩大库(四)函数.php
参考文档:
https://www.php.net/manual/zh/ref.spl.php