php spl标准库简介(SPL是Standard PHP Library(PHP标准库)(直接看代码实例,特别方便)

时间:2024-09-02 20:33:20

php spl标准库简介(SPL是Standard PHP Library(PHP标准库)(直接看代码实例,特别方便)

一、总结

直接看代码实例,特别方便易懂

thinkphp控制器利眠宁不支持(说明差文件引入么),但是view里面支持(也就是原生php支持),

二、php spl标准库简介

SPL简介

SPL是用于解决典型问题(standard problems)的一组接口与类的集合。

SPL是Standard PHP Library(PHP标准库)的缩写。
目前在使用中,SPL更多地被看作是一种使object(对象)模仿array(数组)行为的interfaces和classes
php spl标准库简介(SPL是Standard PHP Library(PHP标准库)(直接看代码实例,特别方便)

SPL的常用数据结构

什么是数据结构?

  • 数据结构是计算机存储、组织数据的方式。是指相互之间存在的一种或多种特定关系的数据元素的集合。
  • 解决的是软件开发过程中的数据如何存储的问题

数据结构之双向链表

双向链表简介

php spl标准库简介(SPL是Standard PHP Library(PHP标准库)(直接看代码实例,特别方便)

  • Bottom:节点,第一个节点称Bottom
  • Top:最后添加的链表的节点称Top
  • 链表指针:可以指向任意节点;
  • 当前节点:链表指针指向的节点称为当前节点;
  • 节点细化成节点名称,和节点数据;

php spl标准库简介(SPL是Standard PHP Library(PHP标准库)(直接看代码实例,特别方便)

php spl标准库简介(SPL是Standard PHP Library(PHP标准库)(直接看代码实例,特别方便)

数据结构之SplDoublyLinkedList

SplDoublyLinkedList类提供了一个双向链表的主要功能
当前节点操作:

  • rewind:将链表的当前指针指向第一个元素
  • current:链表当前指针,当节点被删除后,会指向空节点
  • prev:上一个
  • next:下一个

增加节点操作:

  • push 在双向链表的结尾处将元素压入
  • unshift 前置双链表元素,预备值在双链表的开始

删除节点操作:

  • pop 从双向链表的结尾弹出一个节点,不会改变指针位置
  • shift从双向链表的开头弹出一个节点,不会改变指针位置

定位操作:

  • bottom 返回当前双向链表的第一个节点的值,当前指针不变
  • top返回当前双向链表的最后一个节点的值,当前指针不变

特定节点操作:

  • offsetExists 理解为key是否存在
  • offsetGet将key节点拿出来
  • offsetSet把数据刷新
  • offsetUnset删除

代码实现双向链表
SplDoublyLinkedList.php

<?php
/**
*SplDoublyLinkedList 类学习
*/
$obj = new SplDoublyLinkedList();
$obj -> push(1);//把新的节点添加到链表的顶部top
$obj -> push(2);
$obj -> push(3);
$obj -> unshift(10);//把新节点添加到链表底部bottom
print_r($obj);
$obj ->rewind();//rewind操作用于把节点指针指向Bottom所在节点 $obj -> prev();//使指针指向上一个节点,靠近Bottom方向
echo 'next node :'.$obj->current().PHP_EOL;
$obj -> next();
$obj -> next();
echo 'next node :'.$obj->current().PHP_EOL; $obj -> next();
if($obj -> current())
echo 'current node valid'.PHP_EOL;
else
echo 'current node invalid'.PHP_EOL;
$obj ->rewind();
//如果当前节点是有效节点,valid返回true
if($obj->valid())
echo 'valid list'.PHP_EOL;
else
echo 'invalid list'.PHP_EOL;
print_r($obj);
echo 'pop value :'.$obj -> pop().PHP_EOL;
print_r($obj);
echo 'next node :'.$obj ->current().PHP_EOL;
$obj ->next();//1
$obj ->next();//2
$obj -> pop();//把top位置的节点从链表中删除,并返回,如果current正好指>向top位置,那么调用pop之后current()会失效
echo 'next node:'.$obj -> current().PHP_EOL;
print_r($obj); $obj ->shift();//把bottom位置的节点从链表中删除,并返回
print_r($obj);

数据结构之堆栈

堆栈简介

先进后出 first in last out

继承自SplDoublyLinkedList类的SplStack类
操作:

  • push压入堆栈
  • pop弹出堆栈

    代码示例

<?php
$stack = new SplStack(); $stack -> push('a');
$stack -> push('b');
$stack -> push('c');//入栈 print_r($stack);
echo 'bottom:'.$stack -> bottom().PHP_EOL;
echo "top:".$stack->top().PHP_EOL;
//堆栈的offset=0,是TOP所在位置(即栈的末尾),offset=1是top位置节点靠近bottom位置的相连节点
$stack -> offsetSet(0,'C'); print_r($stack); //双向链表的rewind和堆栈的rewind,相反,堆栈的rewind使得当前指针指向top所在位置,而双向链表调用之后指向bottom所在位置
$stack -> rewind(); echo 'current:'.$stack->current().PHP_EOL; $stack ->next();//堆栈的next操作使指针指向靠近bottom位置的下一个节点,而双向链表是靠近top的下一个节点
echo 'current:'.$stack ->current().PHP_EOL; //遍历堆栈 $stack -> rewind();
while ($stack->valid()) {
echo $stack->key().'=>'.$stack->current().PHP_EOL;
$stack->next();//不从链表中删除元素
} //删除堆栈数据
$popObj = $stack -> pop();//弹出最后一个元素,并删除该节点
echo 'pop object:'.$popObj.PHP_EOL;
print_r($stack);

数据结构之队列

  • 队列和堆栈刚好相反,最先进入队列的元素会最新走出队列
  • 继承自SplDoublyLinkedList类的SplQueue类

    代码示例

<?php

$obj = new SplQueue();

$obj -> enqueue('a');
$obj -> enqueue('b');
$obj -> enqueue('c');
print_r($obj); echo 'bottom:'.$obj -> bottom().PHP_EOL; echo 'top:'.$obj -> top().PHP_EOL;
//队列里的offset=0是指向bottom位置,offset=1是top方向相连的节点
$obj -> offsetSet(0,'A');
valid()
print_r($obj);
//队列里的rewind使得指针指向bottom所在位置的节点
$obj -> rewind();
echo 'current:'.$obj->current().PHP_EOL; while ($obj ->valid()) { echo $obj ->key().'=>'.$obj->current().PHP_EOL;
$obj->next();//
}
//dequeue操作从队列中提取bottom位置的节点,并返回,同时从队列里面删除该元素
echo 'dequeue obj:'.$obj->dequeue().PHP_EOL; print_r($obj);

SPL的常用迭代器

迭代器概述

php spl标准库简介(SPL是Standard PHP Library(PHP标准库)(直接看代码实例,特别方便)

php spl标准库简介(SPL是Standard PHP Library(PHP标准库)(直接看代码实例,特别方便)

ArrayIterator

  • 熟悉使用seek()跳过元素
  • 熟悉使用asort,ksort排序
<?php

$fruits =  array(
'apple'=>'apple value',
'orange' => 'orange value',
'grape' => 'grape value',
'pear' => 'pear value'
); print_r($fruits);//打印数组
echo '*******user fruits directly'.PHP_EOL;
foreach ($fruits as $key => $value) {
# code...
echo $key.':'.$value.PHP_EOL;
}
//使用ArrayIterator遍历数组
$obj = new ArrayObject($fruits);
$it = $obj -> getIterator();//获得迭代器
echo '*******user ArrayIterator in for'.PHP_EOL;
foreach ($it as $key => $value) {
# code...
echo $key.':'.$value.PHP_EOL;
}
echo '*******user ArrayIterator in while'.PHP_EOL;
$it -> rewind();//调用current之前一定要先调用rewind
while ($it -> valid()) {
echo $it -> key().':'.$it->current().PHP_EOL;
$it -> next();//这个必须加上,要不然死循环
} //跳过某些元素进行打印
echo '*******user seek before while'.PHP_EOL;
$it ->rewind();
if($it->valid()){
$it->seek(1);//跳过第一个元素
while ($it -> valid()) {
echo $it -> key().':'.$it->current().PHP_EOL;
$it -> next();//这个必须加上,要不然死循环
}
}
echo '*******user ksort'.PHP_EOL;
$it->ksort();//对key字典排序
foreach ($it as $key => $value) {
# code...
echo $key.':'.$value.PHP_EOL;
}
echo '*******user asort'.PHP_EOL;
$it->asort();//对value字典排序
foreach ($it as $key => $value) {
# code...
echo $key.':'.$value.PHP_EOL;
}

AppendIterator

能陆续遍历几个迭代器

  • -按顺序迭代几个不同的迭代器,例如,希望在一次循环中迭代访问两个或多个组合
<?php

$array_a = new ArrayIterator(array('a','b','c','d'));

$array_b = new ArrayIterator(array('e','f','e','g'));

$it = new AppendIterator();
$it ->Append($array_a);
//通过append方法把迭代器对象添加到AppendIterator对象中
$it -> append($array_b);
foreach ($it as $key => $value) {
# code...
echo $value.PHP_EOL;
}

MultipleIterator

一个迭代器,依次遍历所有附加的迭代器

  • 用于把多个Iterator里面的数据组合成一个整体来访问
<?php
ini_set('display_errors', '1');
error_reporting(E_ALL);
$id_iter = new ArrayIterator(array('01','02','03')); $name_iter = new ArrayIterator(array('张三','李四','王五')); $age_iter = new ArrayIterator(array('21','22','23')); $mit = new MultipleIterator (MultipleIterator::MIT_KEYS_ASSOC); $mit -> attachIterator($id_iter,'ID'); $mit -> attachIterator($name_iter,'name');
$mit -> attachIterator($age_iter,'age'); foreach ($mit as $key => $value) {
# code...
print_r($value);
}

FilesystemIterator

遍历文件系统

<?php
//显示当前目录下的所有文件、大小、创建时间 $it = new FileSystemIterator('.');
date_default_timezone_set('PRC');
foreach ($it as $key => $file_info){
# code...
printf('%s\t%s\t%8s\t%s\n',
date('Y-m-d H:i:s',$file_info->getMTime()),
$file_info->isDir() ? "<dir>" : '',
number_format($file_info->getsize()),
$file_info->getFileName()
);
}

SPL基础接口

接口简介

  • 理解Countable、OuterIterator、RecursiveIterator和SeekableIterator接口的概念
  • 掌握Countable接口的使用
    SPL的基础接口里面定义了最常用的接口
  • Countable继承了该接口的类可以直接调用count()得到元素的个数
  • OuterIterator如果想对迭代器进行一定的处理之后再返回,可以用这个接口
  • RecursiveIterator可以对多层结构的迭代器进行迭代,比如遍历一棵树
  • SeekableIterator可以通过seek方法定位到集合里面的某个特定的元素

Countable接口

类实现 Countable 可被用于 count() 函数.

<?php
//Example One, BAD :( class CountMe
{ protected $_myCount = 3; public function count()
{
return $this->_myCount;
} } $countable = new CountMe();
echo count($countable); //result is "1", not as expected
echo $countable->count;//result is "3"
//Example Two, GOOD :) class CountMe implements Countable
{ protected $_myCount = 3; public function count()
{
return $this->_myCount;
} } $countable = new CountMe();
echo $countable->count();//result is "3"
echo count($countable); //result is "3" as expected
?>

OuterIterator接口

  • OuterIterator如果想对迭代器进行一定的处理之后再返回,可以用这个接口
  • IteratorIterator类是OuterIterator的实现,扩展的时候可以直接继承IteratorIterator
<?php

/**
*
*/
class outerImpl extends IteratorIterator
{ public function current()
{
# code...
return parent::current().'_tail';
}
public function key()
{
return 'pre_'.parent::key();
}
} $array = ['value1','value2','value3','value4']; $outerObj = new outerImpl(new ArrayIterator($array)); foreach ($outerObj as $key => $value) {
# code...
echo '++'.$key.'-'.$value.PHP_EOL;
}

RecursiveIterator接口

  • 可以对多层结构的迭代器进行迭代,比如遍历一棵树
  • 所有具有层次结构特点的数据都可以用这个接口遍历,如文件夹
  • 关键方法
    • hasChildren方法可以用于判断当前节点是否存在子节点
    • getChildren方法用于得到当前节点子节点的迭代器
  • SPL中实现该接口的类
  • RecursiveArrayIterator,RecuriveCachingIterator等以Recurive开头的类都可以进行多层次结构化遍历

SeekableIterator接口

  • SeekableIterator
    • 可以通过seek方法定位到集合里面的某个特定的元素
    • seek方法的参数是元素的位置,从0开始计算
  • SPL中实现该接口的类
    • ArrayIterator、DirectoryIterator、FilesystemIterator、GlobIterator、RecursiveArrayIterator、RecursiveDirectoryIterator

SPL函数的使用

使用spl_autoload_register装载类

<?php

/**
* libs/Test.class.php
*/
class Test
{ function __construct()
{
# code...
echo 'loading class libs/Test.class.php\n';
}
} /**
* autoload.php
*/
//设置autoload寻找php定义的类文件的扩展名,多个扩展名用逗号分隔,前面的扩展名优先匹配
spl_autoload_extensions('.class.php,.php');
//设置autoload寻找PHP定义的类文件的目录,多个目录用PATH_SEPARATOR进行分隔
set_include_path(get_include_path().PATH_SEPARATOR.'libs/');
//提示PHP使用autoload机制查找类定义
spl_autoload_register();
new Test();

__autoload装载类

<?php

function __autoload($class_name){
//定义autoload函数,可以在不调用spl_autoload_register函数的情况下完成类的装载
echo '__autoload class :'.$class_name.PHP_EOL;
require_once 'libs/'.$class_name.'.php';//装载类
}
//定义一个替换__autoload函数的类文件装载函数
function classLoader($class_name){
echo 'classloader() load class : '.$class_name.PHP_EOL;
require_once 'libs/'.$class_name.'.php';//装载类
}
//传入定义好的装载类的函数的名称替换__autoload函数
spl_autoload_register('classLoader'); new Test();

自定义__autoload函数装载类

<?php

//定义一个替换__autoload函数的类文件装载函数
function classLoader($class_name){
echo 'classloader() load class : '.$class_name.PHP_EOL; //当我们不用require_once或require载入类文件的时候,而想通过系统查找include_path来装载类时,必须显式调用spl_autoload函数,参数是类的名称来重启类文件的自动查找(装载)
set_include_path('libs/');
spl_autoload($class_name);
}
//传入定义好的装载类的函数的名称替换__autoload函数
spl_autoload_register('classLoader'); new Test();

SPL函数调用过程

php spl标准库简介(SPL是Standard PHP Library(PHP标准库)(直接看代码实例,特别方便)

SPL其他函数

php spl标准库简介(SPL是Standard PHP Library(PHP标准库)(直接看代码实例,特别方便)

SPL的文件处理类

php spl标准库简介(SPL是Standard PHP Library(PHP标准库)(直接看代码实例,特别方便)

<?php

date_default_timezone_set('PRC');

$file = new SplFileInfo('tmp.txt');

echo 'file is created at '.date('Y-m-d H:i:s',$file->getCTime()).PHP_EOL;

echo 'file is modifyed at '.date('Y-m-d H:i:s',$file->getMTime()).PHP_EOL;

echo 'file size is '.$file->getSize().'bytes'.PHP_EOL;

//读取文件里的内容
$fileObj = $file -> openFile('r'); while ($fileObj ->valid()) {
# code...
echo $fileObj->fgets();
}
//销毁对象
$fileObj = null;
$file = null;