對于php來說,foreach是非常方便好用的一個語法,幾乎對于每一個PHPer它都是日常接觸最多的請求之一,那么物件是否能通過foreach來遍歷呢?
答案是肯定的,但是有個條件,那就是物件的遍歷只能獲得它的公共屬性,
// 普通遍歷
class A
{
public $a1 = '1';
public $a2 = '2';
public $a3 = '3';
private $a4 = '4';
protected $a5 = '5';
public $a6 = '6';
public function test()
{
echo 'test';
}
}
$a = new A();
foreach ($a as $k => $v) {
echo $k, '===', $v, PHP_EOL;
}
// a1===1
// a2===2
// a3===3
// a6===6
不管是方法還是受保護或者私有的變數,都無法遍歷出來,只有公共的屬性才能被遍歷出來,其實,我們之前在講設計模式時講過的迭代器模式就是專門用來進行物件遍歷的,而且PHP已經為我們準備好了相關的介面,我們只需要去實作這個介面就可以完成迭代器模式的創建了,具體的內容可以參考之前的設計模式系列文章:PHP設計模式之迭代器模式
// 實作迭代器介面
class B implements Iterator
{
private $var = [];
public function __construct($array)
{
if (is_array($array)) {
$this->var = $array;
}
}
public function rewind()
{
echo "rewinding\n";
reset($this->var);
}
public function current()
{
$var = current($this->var);
echo "current: $var\n";
return $var;
}
public function key()
{
$var = key($this->var);
echo "key: $var\n";
return $var;
}
public function next()
{
$var = next($this->var);
echo "next: $var\n";
return $var;
}
public function valid()
{
$var = $this->current() !== false;
echo "valid: {$var}\n";
return $var;
}
}
$b = new B([1, 2, 3, 4]);
foreach ($b as $k => $v) {
echo $k, '===', $v, PHP_EOL;
}
// rewinding
// current: 1
// valid: 1
// current: 1
// key: 0
// 0===1
// next: 2
// current: 2
// valid: 1
// current: 2
// key: 1
// 1===2
// next: 3
// current: 3
// valid: 1
// current: 3
// key: 2
// 2===3
// next: 4
// current: 4
// valid: 1
// current: 4
// key: 3
// 3===4
// next:
// current:
// valid:
假如今天的文章只是講之前講過的迭代器模式,那就太沒意思了,所以,咱們還要來學習一個更有意思的應用,那就是讓物件可以像陣列一樣進行操作,這個其實也是使用PHP早已為我們準備好的一個介面:ArrayAccess,
// 讓類可以像陣列一樣操作
class C implements ArrayAccess, IteratorAggregate
{
private $container = [];
public function __construct()
{
$this->container = [
"one" => 1,
"two" => 2,
"three" => 3,
];
}
public function offsetSet($offset, $value)
{
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
}
public function offsetExists($offset)
{
return isset($this->container[$offset]);
}
public function offsetUnset($offset)
{
unset($this->container[$offset]);
}
public function offsetGet($offset)
{
return isset($this->container[$offset]) ? $this->container[$offset] : null;
}
public function getIterator() {
return new B($this->container);
}
}
$c = new C();
var_dump($c);
$c['four'] = 4;
var_dump($c);
$c[] = 5;
$c[] = 6;
var_dump($c);
foreach($c as $k=>$v){
echo $k, '===', $v, PHP_EOL;
}
// rewinding
// current: 1
// valid: 1
// current: 1
// key: one
// one===1
// next: 2
// current: 2
// valid: 1
// current: 2
// key: two
// two===2
// next: 3
// current: 3
// valid: 1
// current: 3
// key: three
// three===3
// next: 4
// current: 4
// valid: 1
// current: 4
// key: four
// four===4
// next: 5
// current: 5
// valid: 1
// current: 5
// key: 0
// 0===5
// next: 6
// current: 6
// valid: 1
// current: 6
// key: 1
// 1===6
// next:
// current:
// valid:
這個介面需要我們實作四個方法:
- offsetSet($offset, $value),根據偏移量設定值
- offsetExists($offset),根據偏移量確定是否存在內容
- offsetUnset($offset),根據偏移量洗掉內容
- offsetGet($offset),根據依稀量獲取內容
這里的偏移量就是我們常說的下標,通過實作這四個方法,我們就可以像操作陣列一樣的操作物件,當然,日常開發中我們可能并不會很經常的使用包括迭代器在內的這些物件遍歷的能力,通常我們會直接去將物件轉換成陣列 (array) obj 來進行下一步的操作,不過,在java中,特別是JavaBean中會經常在類的內部有一個 List
測驗代碼:
https://github.com/zhangyue0503/dev-blog/blob/master/php/201912/source/PHP%E6%80%8E%E4%B9%88%E9%81%8D%E5%8E%86%E5%AF%B9%E8%B1%A1%EF%BC%9F.php
參考檔案:
https://www.php.net/manual/zh/language.oop5.iterations.php
關注公眾號:【硬核專案經理】獲取最新文章
添加微信/QQ好友:【xiaoyuezigonggong/149844827】免費得PHP、專案管理學習資料
知乎、公眾號、抖音、頭條搜索【硬核專案經理】
B站ID:482780532
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/257321.html
標籤:PHP
上一篇:從0到1實作一個簡單計算器
