PHP - 使用 array_filter 讓你的程式碼更簡潔易讀

早上看到了這一篇關於 PHP 技巧的文章:Improving readability using array_filter - murze.be 中文翻譯大概可以說是,用 array_filter 使之更具有可讀性。看到也實際測試了一下,覺得不錯,因此作了一些實驗,也發現一些小坑,所以順便作一下記錄。

以往要在 PHP 的 class 中實作 toArray() method 我們會寫類似的程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Address
{
private $name;
private $city;
private $street_line1;
private $street_line2;
...

public function toArray()
{
$address = [
'name' => $this->name,
'city' => $this->city,
'street_line1' => $this->street_line1,
];

if ($this->street_line2 != '') {
$address['street_line2'] = $this->street_line2;
}
...
}
}

member data 不多的時候,看起來還好。但再多幾個,上面判斷是否為空白的 if 判斷式就會變得非常多,很不好看,也不簡潔。文章內提供的方法就是使用 array_filter 改寫。改寫後的程式碼像這樣。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Address
{
private $name;
private $city;
private $street_line1;
private $street_line2;
...

public function toArray()
{
return array_filter([
'name' => $this->name,
'city' => $this->city,
'street_line1' => $this->street_line1,
'street_line2' => $this->street_line2,
...
]);
}
}

整體看起來簡潔多了。使用的就是 array_filter PHP: array_filter - Manual 的特性。當 array_filter 的第二個參數不帶入 callback function 時,預設的處理方法:「當遇到成員內容為空值或為 null 時,不輸出」。

因此,在使用的時候也要特別小心。舉例來說,假設 street_line1, street_line2 是空字串,則輸出就會只有 name 及 city:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Address
{
private $name = 'User 1';
private $city = 'Taipei';
private $street_line1 = '';
private $street_line2 = '';
...

public function toArray()
{
...
}
}

$address = new Address();
print_r($address->toArray());

// Array
//(
// [name] => User 1
// [city] => Taipei
//)

而如果直接輸出不存在的 member 也是。如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Address
{
private $name = 'User 1';
private $city = 'Taipei';
// private $street_line1 = '';
// private $street_line2 = '';
...

public function toArray()
{
...
}
}

$address = new Address();
print_r($address->toArray());

// Array
//(
// [name] => User 1
// [city] => Taipei
//)

還有,遇到直接是 null 的時候也是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Address
{
private $name = 'User 1';
private $city = 'Taipei';
private $street_line1 = null;
private $street_line2 = null;
...

public function toArray()
{
...
}
}

$address = new Address();
print_r($address->toArray());

// Array
//(
// [name] => User 1
// [city] => Taipei
//)

array_filter 遇到空字串、null、不存在時的這些特性就要特別注意。像是無論如何就算是空字串也要輸出佔一個位置的,就要在額外特別處理了。

看到這樣的運用並且實際作實驗的感覺還蠻有趣的。跟 Improving readability using array_filter - murze.be 作者一樣,第一次發現 array_filter 可以這樣用。

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器