標籤:php spl
<?php ****************************************PHP進階程式員必修課*******************************************************
//SPL:PHP標準庫,Standand PHP Library 解決常見問題的一組介面與類的集合
/*
問題:數學建模/資料結構,解決資料如何儲存的問題
元素便利,資料如何查看的問題
常用方法的統一調用(通用方法,自訂遍曆)
類定義的自動裝載
*/
/*
SPL的基本架構
資料結構 基礎介面 基礎函數
迭代器 異常 其它
*/
/*SPL的常用資料結構
雙向鏈表 堆棧 隊列 堆 降序堆 升序堆 優先順序隊列 定長數組 對象容器
*/
//雙向鏈表
微博使用者A <--關注--> 微博使用者B <--關注--> 微博使用者C //如果是單向的,則為單向鏈表
註:最先添加到列表當中的節點:Bottom/head
最後添加到列表當中的節點:Top,也稱為尾部
鏈表指標:是當前關注的節點的標識,可以指向任意節點
當前節點:鏈表指標指向的節點
節點的組成:節點名稱key/offset 節點資料value
SqlDoublyLinkedList類
操作:
當前節點操作:rewind(第一個節點),current(當前節點),next(下一個節點),prev(前一個節點)
增加節點操作:push,array_unshift
刪除節點操作:pop,shift
定位操作: bottom,top
特定節點操作:offsetExists,offsetGet,offsetSet,offsetUnset
雙向鏈表在SPL中的實現:PHP -f SqlDoublyLinkedList.php可以在cmd中測試
$obj=new SqlDoublyLinkedList();
$obj->push(1); //將1推入鏈表,也就是添加到頂部top
$obj->push(2);
$obj->push(3);
$obj->unshift(10); //反向將10推入鏈表,也就是10將索引值0佔據,也就是添加到底部botton
$obj->rewind(); //調用rewind後,才會有指標,也就是才有current(當前指標的節點值),將指標指向bottom
$obj->next(); //指標向後移動一次
$obj->prev(); //指標向前移動一次
echo "current:".$obj->current(); //擷取當前節點的值
if($obj->current){ //判斷是否移動完畢
echo "current node valid\n";
}else{
echo "current node invalid\n";
}
if($obj->valid()){ //可以直接用內建函數判斷是不是指標移動完畢(判斷節點是否有效)
echo "valid list \n";
}
$obj->pop(); //刪除離top最近的節點
$obj->shift(); //刪除bottom所在位置的節點
雙向鏈表總結:兩頭皆可操作
//堆棧 算是雙向鏈表的衍生
3號圓盤 |
5號圓盤 |
7號圓盤 |
SqlStack類繼承自SqlDoublyLinkedList類
操作:
push:壓入堆棧(存入)
pop: 退出堆棧(取出)
代碼實現:
$Stack = new SqlStack();
$stack->push(‘a‘); //加入a,b,c
$stack->push(‘b‘);
$stack->push(‘c‘);
print_r($stack);
echo $stack->bottom;
echo $stack->top;
echo $stack->offsetSet(0,‘C‘); //堆棧的offset=0是top所在的位置,offset=1是靠近top所在的節點,而在雙向鏈表中相反!!!
//將offset=0的索引值對應的value設為C
$stack->rewind();
$stack->current(); //rewind()之後,堆棧指向top位置,雙向鏈表指向底部bottom
$stack->next(); //會指向靠近bottom的方向
//遍曆堆棧
$stck->rewind();
while($stck->valid()){
echo $stack->key()."=>".$stack->current()."\n";
$stack->next();
}
//刪除堆棧資料
$popobj = $stack->pop();
echo "被刪除的元素".$popobj;
堆棧總結:只能從top操作,很多函數如next,prev指向的方向與雙向鏈表相反
//隊列:排隊打飯一樣,先到先打,與堆棧恰恰相反
SqlQueue類也繼承自SqlDoublyLinkedList類
enqueue:進入隊列
dequeue:退出隊列
代碼實現:
$obj = new SqlQueue();
$obj->enqueue(‘a‘); //將abc加入到隊列
$obj->enqueue(‘b‘);
$obj->enqueue(‘c‘);
echo "bottom: ".$obj->bottom."\n";
echo "top: ".$obj->top."\n";
$obj->offsetSet(0,‘A‘); //隊列裡面0為bottom
$obj->rewind(); //隊列裡面指向bottom
遍曆隊列
while($obj->valid()){
echo %$obj->key()."=>".$obj->current()."\n";
$obj->next();
}
//刪除
$delobj=>$obj->dequeue();
隊列小結:一切以先來先出為原則。
/***************************************************************************************************************************
資料結構大總結:
雙向鏈表,堆棧,隊列的關係:
堆棧:先進後出
隊列:先進先出
雙向鏈表:兩頭都可以進出
****************************************************************************************************************************/
//******************************************SPL的常用迭代器************************************************************
迭代器概念:通過某種統一的方式遍曆鏈表或者數組的元素的過程叫做迭代遍曆,而這種統一的便利工具我們叫做迭代器。
PHP中的迭代器是通過Iterator介面定義的
常用的迭代器一:ArrayIterator-------------------------------------------------------------------------(用於遍曆數組)
1: freach與while語句通過ArrayIterator遍曆數組
2:seek跳過某些元素
3:ArrayIterator()進行排序
代碼實現:
$fruits = array(
"apple"=>‘apple value‘,
"orange"=>‘orange value‘,
"grape"=>‘grape value‘,
"plum"=>‘plum value‘,
);
//一般遍曆
foreach($fruits as $key=>$value){
echo $key.":".$value."\n";
}
//使用ArrayIterator迭代器遍曆數組(相當於普通迴圈的詳細化)
$obj = new ArrayObject($fruits);
$it = $obj->getIterator();
foreach($it as $key=>$value){
echo echo $key.":".$value."\n";
}
//使用while之前需要調用rewind()
$it->rewind();
while($it->valid()){
echo $it->key().":".$it->value()."\n";
$it->next();
}
//跳過某些元素進行列印
$it->rewind();
if($it->valid()){
$it->seek(1); //跳過position=1的元素
while($it->valid()){
echo $it->key().":".$it->current()."\n";
$it->next;
}
}
//排序列印
$it->ksort(); //按照key字母排序
foreach($it as $key=>$value){
echo $key.":".$value."\n";
}
//使用value排序
$it->asort();
foreach($it as $key=>$value){
echo $key.":".$value."\n";
}
常用的迭代器二:AppendIterator----------------------------------------------------------------------(按照順序迭代訪問幾個不同的迭代器)
代碼實現:
$array_a = new ArrayIterator(array(‘a‘,‘b‘,‘c‘));
$array_b = new ArrayIterator(array(‘d‘,‘e‘,‘f‘));
$it = new AppendIterator();
$it->append($array_a);
$it->append($array_b);
foreach($it as $key=>$value){
echo $value."\n";
}
/*a
b
c
d
e
f*/
常用的迭代器三:MultipleIterator----------------------------------------------------------------------(將多個Iterator裡面的資料群組合成為一個整體來訪問)
代碼實現:
$idIter = new ArrayIterator(array(‘01‘,‘02‘,‘03‘));
$nameIter = new ArrayIterator(array(‘張三‘,‘李四‘,‘王五‘));
$ageIter = new ArrayIterator(array(‘21‘,‘23‘,‘25‘));
$mit = new MultipleIterator(MultipleIterator::MIT_KEY_ASSOC);
$mit->attachIterator($idIter,"ID");
$mit->attachIterator($nameIter,"NAME");
$mit->attachIterator($ageIter,"AGE");
foreach($mit as $value){
print_r($value);
}
/*
array(
[ID]=>01,
[NAME]=>張三,
[AGE]=>22
)
array(
[ID]=>02,
[NAME]=>李四,
[AGE]=>23
)
array(
[ID]=>03,
[NAME]=>王五,
[AGE]=>25
)
*/
常用的迭代器四:FilesystemIterator----------------------------------------------------------------------(遍曆檔案系統)
代碼實現:
date_default_timezone_get(‘PRC‘);
$it = new FilesystemIterator(‘.‘); //.表示目前的目錄
foreach ($it as $finfo){
printf("%s\t%s%8s\t%s\n",
date("Y-m-d H:i:s",$finfo->getMTime())."\n", //列印出當前檔案夾下的所有檔案的格式化時間
$finfo->isDir()?<DIR>":"", //判斷是否是目錄
number_format($finfo->getSize()), //將檔案大小格式化,每3位加逗號
$finfo->getFileName()
);
}
//******************************************SPL的基礎介面************************************************************
1:理解Countable/OuterIterator/RecursiveIterator/SeekableIterator等4個介面的概念
2:熟練掌握Countable介面的使用
Countable:繼承該介面的類可以直接調用count得到元素的個數
OuterIterator:如果想對迭代器進行一定的處理之後再返回,可以使用這個介面
RecursiveIterator:可以對多層結構的迭代器進行迭代,比如遍曆一棵樹
SeekableIterator:通過seek方法定位到集合裡面的某一個特定元素
******************************************Countable介面*****************************************************
count(array(‘name‘=>‘Peter‘,‘id‘=>‘2‘))
date_default_timezone_get(‘PRC‘)
$array=array (
array(‘name‘=>‘Jonathon‘,‘id‘=>‘2‘),
array(‘name‘=>‘SEM‘,‘id‘=>‘2‘),
array(‘name‘=>‘Tom‘,‘id‘=>‘2‘)
)
echo count($array); //3 自數組個數
echo count($array[1]); //2 第二個子數位元素個數
class CountMe implements Countable {
protected $_myCount=3;
public function count(){
return $this->_myCount;
}
}
$obj = new CountMe();
echo count($obj); //不加implements Countable時顯示1,加後顯示為3!!!!!!!!!!
******************************************OuterIterator介面*****************************************************
如果想對迭代器進行一定的處理之後再返回,可以用這個介面
IteratorIterator類時OuterIterator類的實現,擴充的時候可以直接繼承IteratorIterator
代碼實現:
date_default_timezone_get(‘PRC‘);
$array=[‘Value1‘,‘Vlaue2‘,‘Vlaue3‘,‘Vlaue4‘];
$outerObj = new OuterImpl(new Arrayi($array);
forach($outerObj as $key=>$value){
echo "++".$key."-".$vale."\n"; //$key會顯示成Pre_0,$value會顯示成Value1_tail
}
class OuterImpl extends IteratorIterator{
public function current(){ //value
return parent::current().‘_tail‘;
}
public function key(){ //key
return "Pre_".parent::key();
}
}
******************************************RecursiveIterator介面*****************************************************
見doc的一張圖,粗講。
******************************************SeekableIterator介面*****************************************************
見doc的一張圖,粗講。
//******************************************SPL函數的使用************************************************************
1:
Autoload:為了初始化PHP中的類對象,需要通過一定的方法尋找類的定義。通常情況下,類會定義在一個單獨的檔案中。
Aotuload就是PHP找到這些類檔案的方法。
class Test{
public function __construct(){
echo "Loading Class libs/Test.php\n";
}
}
<?php
spl_autoload_extensions(‘.class.php,.php‘); //會自動載入Test.class.php,也可以設定為.php,兩者也可俱在
set_include_path(get_include_path().PATH_SEPARATOR."libs/"); //將類的位置這隻在libs/下
//設定autoload尋找定義的類檔案的目錄,多個目錄用_PATH_SEPARATOR進行分割。
spl_autoload_register(); //PHP使用Autoload機制尋找類定義
new Test();
?>
2:
__autoload裝載類
function __autoload($class_name){
echo "__autoload class :".$class_name."\n";
require_once("libs/".$class_name.‘.php‘);
}
//也可以自訂一個類似__autoload方法
function classLoader($class_name){
echo "classLoader class :".$class_name."\n";
require_once("libs/".$class_name.‘.php‘);
}
spl_autoload_register(‘classLoader‘); //這樣也就將__autoload方法重新命名了,將__autoload方法頂替了
new Test();
註:還可以將require_once替換成set_include_path頂替,代碼實現如下:
function classLoader($class_name){
echo "classLoader class :".$class_name."\n";
set_include_path("libs/");
spl_autoload($class_name); //當我們不用require或者require_once載入類檔案的時候,而是想通過系統尋找include_path來裝載類時,必須顯式調用spl_autoload函數,參數是類的名稱來重啟類檔案的自動尋找
}
spl_autoload_register(‘classLoader‘);
new Test();
*************************************
總結:類載入的基本流程,參見doc文檔一圖。
*************************************
//******************************************SPL的檔案處理類庫************************************************************
兩個類庫
實現代碼:
date_default_timezone_get("PRC");
$file = new SqlFileInfo("tmp.txt");
echo "File is created at".date("Y-m-d H:i:s",$file->getCTime())."\n"; //查看檔案的資訊
echo "File is modified at".date("Y-m-d H:i:s",$file->getMTime())."\n";
//讀取裡面的內容
$fileObj = $file->openFile("r"); //以讀的方式開啟一個檔案
while($fileObj->valid()){
echo $fileObj->fgets(); //fget擷取檔案裡面的一行資料
}
$openObj = null; //用於關閉開啟的檔案
$file null;
這裡檔案的讀入方式是物件導向的,比fopen之類的函數要簡潔,提倡使用!
****************************************************************************************************************
課程總結:略
****************************************************************************************************************
?>
本文出自 “枷羅部落格” 部落格,請務必保留此出處http://sun231013.blog.51cto.com/8558055/1576803
SPL(PHP標準庫)-----------------------個人筆記