课程:https://www.imooc.com/video/2511/0
测试结果来自php7.3+。
SPL含义:Standard PHP Library 标准PHP类库
1、SPL数据结构
stack overflow error 堆栈溢出错误
链表使用数据队列的原理,在类对象调用上可谓“纷繁复杂”。不管链表底层实现原理,直接继承 spldoublylinkedlist 使用就行。在实际中
SplStack、SplQueue继承自双向链表(类:SplDoublyLinkedList),这里序列形象赖于 Obj->push()方法添加 所打印的序列。
a.SplDoublyLinkedList双向链表
官方接口
class SplDoublyLinkedList implements Iterator, Countable, ArrayAccess, Serializable {
-add($index, $newval)
-push($value)/pop() --尾部 +-end
-unshift($value)/shifts() --顶部 +-beginning
-top() --尾部 end
-bottom() --开头 beginning
-count()
-isEmpty()
-setIteratorMode($mode)
-getIteratorMode()
-offsetExists($index)
-offsetGet($index)
-offsetSet($index, $newval)
-offsetUnset($index) --删除指定索引,并重新连接[排序]
-rewind() --back to the start
-current()
-key() --current的index
-next()
-prev()
-valid()
-serialize()
-unserialize(string $serialized)
-__serialize()
-__unserialize(array $data)
}
SplDoublyLinkedList:0SplDoublyLinkedList.php
SplDoublyLinkedList:
SplDoublyLinkedList Object
(
[flags:SplDoublyLinkedList:private] => 0
[dllist:SplDoublyLinkedList:private] => Array
(
)
)
is valid ? bool(false)
push:1-2-3; unshift:10:
SplDoublyLinkedList Object
(
[flags:SplDoublyLinkedList:private] => 0
[dllist:SplDoublyLinkedList:private] => Array
(
[0] => 10 --unshift一个10
[1] => 1 --push添加1,2,3从顶部-->底部
[2] => 2
[3] => 3
)
)
44current:--next node:
49rewind, current:10,
next, node:1,
next, node:2
62current pop?:3 --pop固定的底部删除3
current:2
push:X; unshift:Y: --底部加X,顶部Y
current pop:X --pop固定的底部删除X
68current:2
SplDoublyLinkedList Object
(
[flags:SplDoublyLinkedList:private] => 0
[dllist:SplDoublyLinkedList:private] => Array
(
[0] => Y
[1] => 10
[2] => 1
[3] => 2
)
)
offsetGet: 3 == 2; top:2; bottom:Y
SplDoublyLinkedList Object
(
[flags:SplDoublyLinkedList:private] => 0
[dllist:SplDoublyLinkedList:private] => Array
(
[0] => Y
[1] => 10
[2] => 1
[3] => 2
)
)
rewind顺序打印:
Y,10,1,2, --打印从顶部到底部
0
b.SplQueue队列、Slack栈
SplQueue 1SplQueue.php 与SplDoublyLinkedList基本相同:
SplQueue:
SplQueue Object
(
[flags:SplDoublyLinkedList:private] => 4
[dllist:SplDoublyLinkedList:private] => Array
(
)
)
is valid ? bool(false)
push:1-2-3; unshift:10:
SplQueue Object
(
[flags:SplDoublyLinkedList:private] => 4
[dllist:SplDoublyLinkedList:private] => Array
(
[0] => 10
[1] => 1
[2] => 2
[3] => 3
)
)
44current:--next node:
49rewind, current:10,
next, node:1,
next, node:2
62current pop?:3
current:2
push:X; unshift:Y:
current pop:X
68current:2
SplQueue Object
(
[flags:SplDoublyLinkedList:private] => 4
[dllist:SplDoublyLinkedList:private] => Array
(
[0] => Y
[1] => 10
[2] => 1
[3] => 2
)
)
offsetGet: 3 == 2; top:2; bottom:Y
SplQueue Object
(
[flags:SplDoublyLinkedList:private] => 4
[dllist:SplDoublyLinkedList:private] => Array
(
[0] => Y
[1] => 10
[2] => 1
[3] => 2
)
)
rewind顺序打印:
Y,10,1,2,
4
SplStack 2SplStack.php
SplStack:
SplStack Object
(
[flags:SplDoublyLinkedList:private] => 6
[dllist:SplDoublyLinkedList:private] => Array
(
)
)
is valid ? bool(false)
push:1-2-3; unshift:10:
SplStack Object
(
[flags:SplDoublyLinkedList:private] => 6
[dllist:SplDoublyLinkedList:private] => Array
(
[0] => 10
[1] => 1
[2] => 2
[3] => 3
)
)
44current:--next node:
49rewind, current:3, --rewind到尾部
next, node:2, --next从底部到顶部
next, node:1
62current pop?:3
current:1
push:X; unshift:Y:
current pop:X
68current:1
SplStack Object
(
[flags:SplDoublyLinkedList:private] => 6
[dllist:SplDoublyLinkedList:private] => Array
(
[0] => Y
[1] => 10
[2] => 1
[3] => 2
)
)
offsetGet: 3 == Y; top:2; bottom:Y
SplStack Object
(
[flags:SplDoublyLinkedList:private] => 6
[dllist:SplDoublyLinkedList:private] => Array
(
[0] => Y
[1] => 10
[2] => 1
[3] => 2
)
)
rewind顺序打印:
2,1,10,Y, --打印从底部开始到顶部
6
c.SplDLL.0|SplQueue.4|SplStack.6小结
SplDoublyLinkedList::setIteratorMode 参数:
There are two orthogonal sets of modes that can be set:
◦ The direction of the iteration 迭代的方向(either one or the other):
◦SplDoublyLinkedList::IT_MODE_LIFO (Stack style) 2
◦SplDoublyLinkedList::IT_MODE_FIFO (Queue style) 0
◦ The behavior of the iterator 迭代器的行为(either one or the other):
◦SplDoublyLinkedList::IT_MODE_DELETE (Elements are deleted by the iterator 元素被迭代器删除) 1
◦SplDoublyLinkedList::IT_MODE_KEEP (Elements are traversed by the iterator 元素由迭代器遍历) 0
The default mode is: SplDoublyLinkedList::IT_MODE_FIFO | SplDoublyLinkedList::IT_MODE_KEEP
Iteration Direction
SplDoublyLinkedList::IT_MODE_LIFO
The list will be iterated in a last in, first out order, like a stack.
该列表将按“最后入,先出”的顺序迭代,就像栈一样。 [First in, First out.先进先出]
SplDoublyLinkedList::IT_MODE_FIFO
The list will be iterated in a first in, first out order, like a queue.
该列表将按照先入先出的顺序迭代,就像队列一样. [LIFO: Last in, First out.后进先出]
const IT_MODE_LIFO = 2;
const IT_MODE_FIFO = 0;
const IT_MODE_DELETE = 1;
const IT_MODE_KEEP = 0;
官方接口:
class SplQueue extends SplDoublyLinkedList {
-enqueue($value) --入列 add to queue
-dequeue() --出列 dequeue a node
}
class SplStack extends SplDoublyLinkedList {
-esetIteratorMode($mode) --设置迭代模式(方向)
}
上面来自关联接口:phpstorm//stubs/SPL/SPL_c1.php 和php官网。
从C++学习基础归来,可以看到:系统分配堆、先进后出,自定义new栈、随进随出【先入必先出、不然找不到;并且执行段结束了】。
即堆[Slack]是系统指定的逆序列,堆[Heap]是随进随出的正序列。
异同点:
rewind()、next()、prev() ==> 双链表和queue是start在上、slack在下
top\bottom\add\push\pop等相同
2、迭代器
a.ArrayIterator 数组转换链表
This iterator allows to unset and modify values and keys while iteratingover Arrays and Objects. 这个迭代器允许在遍历数组或对象时,取消设置、修改值和键。
5ArrayIterator.php
//example 1; 普通数组迭代
$fruits = array(
"apple" => "yummy",
"orange" => "ah ya, nice",
"grape" => "wow, I love it!",
"plum" => "nah, not me"
);
$obj = new ArrayObject( $fruits );
$it = $obj->getIterator();
echo "Iterating over: " . $obj->count() . " values\n";
while( $it->valid() )
{
echo $it->key() . "=" . $it->current() . "\n";
$it->next();
}
foreach ($it as $key=>$val)
echo $key.":".$val."\n";
//example 2: 两数组健值组合[array_combine]
$fruits = array(
"apple" => "yummy",
"orange" => "ah ya, nice",
"grape" => "wow, I love it!",
"plum" => "nah, not me"
);
$veg = array("potato" => "chips", "carrot" => "soup");
$grocery = array($fruits, $veg);
$obj = new ArrayObject( $grocery );
$it = new RecursiveIteratorIterator( new RecursiveArrayIterator($grocery));
foreach ($it as $key=>$val)
echo $key.":".$val."\n";
b.AppendIterator 迭代器合并
An Iterator that iterates over several iterators one after the other. 一个在多个迭代器拼接的新迭代器[array_merge_recursive],允许重复值。
6AppendIterator.php
//array_merge_recursive
$array_a = array(
"apple" => "yummy",
"orange" => "ah ya, nice",
"grape" => "wow, I love it!",
"plum" => "nah, not me"
);
$array_b = array("potato" => "chips", "plum" => "soup");
$it = new AppendIterator();
$it->append(new ArrayIterator($array_a));
$it->append(new ArrayIterator($array_b));
foreach($it as $key => $value){
echo $key. ': '. $value;
}
/*
apple: yummy
orange: ah ya, nice
grape: wow, I love it!
plum: nah, not me
potato: chips
plum: soup
*/
c.MultipleIterator 对照分组迭代器
An Iterator that sequentially iterates over all attached iterators.一个迭代器按顺序遍历所有附加迭代器的迭代器。
7MultipleIterator.php
//键值同步分离
$it1 = new ArrayIterator(array(1,2,3,4,5)); //对照只列出前3个
$it2 = new ArrayIterator(array(4,5,6));
$multipleIterator = new MultipleIterator(MultipleIterator::MIT_NEED_ALL|MultipleIterator::MIT_KEYS_ASSOC);
$multipleIterator->attachIterator($it1, 1);
$multipleIterator->attachIterator($it2, 'second');
foreach ($multipleIterator as $key => $value) {
echo "Key"; var_dump($key);
echo "Value"; var_dump($value);
echo "---next---\n";
}
/*
Keyarray(2) {
[1]=>
int(0)
["second"]=>
int(0)
}
Valuearray(2) {
[1]=>
int(1)
["second"]=>
int(4)
}
---next---
Keyarray(2) {
[1]=>
int(1)
["second"]=>
int(1)
}
Valuearray(2) {
[1]=>
int(2)
["second"]=>
int(5)
}
---next---
Keyarray(2) {
[1]=>
int(2)
["second"]=>
int(2)
}
Valuearray(2) {
[1]=>
int(3)
["second"]=>
int(6)
}
---next---
*/
d.FileSystemIterator 文件浏览迭代器: 列表|文本内容
This abstract iterator filters out unwanted values. This class should be extended toimplement custom iterator filters. The FilterIterator::accept()must be implemented in the subclass. 这个抽象的迭代器过滤掉不需要的值。应该扩展这个类来实现自定义迭代器过滤器。必须在子类中实现FilterIterator::accept()。
8FileSystemIterator.php
//文件夹迭代
$it = new FilesystemIterator('.');
foreach ($it as $fInfo){
print_r([
'mt'=>date('Y-m-d H:i:s', $fInfo->getMTime()),
'fs'=>$fInfo->getSize()
]);
}
## 逐行迭代读取文件
// $file = new \SplFileInfo('tree.php');
// $fileObj = $file->openFile('r');
$fileObj = new \SplFileObject('tree.php', 'r'); //与上面等价
while($fileObj->valid()){
echo $fileObj->fgets();
}
//关闭文件对象
$fileObj = null;
$file = null;
3、迭代器接口
a. Iterator 基础迭代接口
作为口标准:
//Traversable可否认的[接口,以检测是否可以使用foreach遍历类]
Iterator extends Traversable {
abstract public current( void) : mixed
abstract public key( void) : scalar
abstract public next( void) : void
abstract public rewind( void) : void
abstract public valid( void) : bool
}
class myIterator implements Iterator {
private $position = 0;
private $array = array(
"firstelement",
"secondelement",
"lastelement",
);
public function __construct() {
$this->position = 0;
}
public function rewind() {
$this->position = 0;
}
public function current() {
return $this->array[$this->position];
}
public function key() {
return $this->position;
}
public function next() {
++$this->position;
}
public function valid() {
return isset($this->array[$this->position]);
}
}`
b. Countable 类可计数接口
Classes implementing Countable can be used with the count()function. 实现Countable的类可以与count()函数一起使用。
class CountMe implements Countable
{
public function count(){ return 3;}
}
echo count(new CountMe()); //3
c.OuterIterator 类迭代接口
extends IteratorIterator => parent::current(),parent::key()
Classes implementing OuterIterator can be used to iterateover iterators. 实现OuterIterator的类可用于在迭代器上迭代。
class OuterTmpl extends IteratorIterator
{
public function current(){
return (parent::current() * parent::current()).'_**_'. parent::key();
}
public function key(){
return 'key? '. (parent::key() * 2);
}
}
$array = [1,3,5,7,9];
$outerObj = new OuterTmpl(new ArrayIterator($array));
foreach($outerObj as $key => $value){
echo $key. ': '. $value, PHP_EOL;
}
4、其他函数
sql_autoload_register 注册函数
注册给定的函数作为 __autoload 的实现。
把类放到系统调用区。
spl_autoload_extensions(".php, .inc");
set_include_path(get_include_path() . PATH_SEPARATOR .'libs/');
var_dump( get_include_path() );
spl_autoload_register();
var_dump(new test());
var_dump(new PEople()); //类名加载不区分大小写,这里类名*文件名*小写【大写加载不了,还不清楚】
function ClassLoader($class_name){
echo "ClassLoader load class: ". $class_name. "<br/>";
set include_path("libs/");
spl_autoload($class_name); //须要显示调用
}
spl_autoload_register("ClassLoader"); //或数组['类名/类实例'=>'方法']
class_implements($class)
返回指定的类实现的所有接口
iterator_apply($it, callable $function[, array $args])
为迭代器中的每个元素调用一个函数[array_walk]
$it = new ArrayIterator(["Apples", "Bananas", "Cherries"]);
iterator_apply($it, function (Iterator $iterator) {
echo strtoupper($iterator->current()), PHP_EOL;
return TRUE;
}, array($it));
foreach($it as $key => $value){
echo $key. ': '. $value, PHP_EOL;
}
iterator_count($it)
返回迭代长度
iterator_to_array($it[, $use_keys = true])
将迭代器中的元素拷贝到数组
实例测试代码上传:
https://github.com/cffycls/cluster/tree/master/html/spl
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。