【PHP】array_filterと具体的なシチュエーション

php

状況

全てのデータを問い合わせた後で、例えば「金額で100円以下とそうでないものとを分けたい」「一覧データで表示非表示を分けたい」などの状況を考える。

array_filter

foreachでも書けるが、array_filterを使ってみる。
フィルタリング(array_filter)とは、条件に合致するものだけを選別し、条件外のものを除外すること。フィルタリング自体はコールバック関数で行う。

array_filterは、コールバック関数を第二引数に与えない場合、配列の要素でtrueのものだけをもとの配列に返す。例えば、以下の$productでarray_filterを使った場合、is_hiddenを除いた配列を返す。
ここで返すのは、empty()、つまり空、null、falseの場合(例えば、false、null、’ '、’0’、0のものは返さない)。

$product = [
            "id" => 1,
            "name" => 'cookie',
            "price" => 150,
            "is_hidden" => 0
       ];
array_filter($product );

書き方

array_filterの書き方としては、function(スコープの内外から)、アロー関数で書く方法などがある。ここでは、アロー関数を見ていく。

アロー関数

例えば、以下の通り。

$filterd = array_filter($product , fn($v) => $v['is_hidden'] == false);

デフォルト($v)は、$productのvalueだけを使用。$v['is_hidden’] == falseで条件を指定、この条件に合致した配列だけ返される。デフォルトはvalueだけを使用するが、keyを使いたい場合には、mode(ARRAY_FILTER_USE_BOTH(値とキーの両方)やARRAY_FILTER_USE_KEY(キーだけ))を設定する。

また、アロー関数にすれば、use()を使わずにそのままスコープ外の変数を使える。フィルタリングするとキーがずれるが、連番にしたい場合にはスプレッド演算子を使用する(あるいは、array_values())。

販売商品の金額で、100円以下のものとそうでないものとを分けたい

冒頭のケースで、具体的に見ていく。以下の商品があるとする。

$products = 
    [
        [
            "id" => 1,
            "name" => 'cookie',
            "price" => 150,
            "is_hidden" => 0
        ],
        [
            "id" => 2,
            "name" => 'ice',
            "price" => 200,
            "is_hidden" => 1
        ],
        [
            "id" => 3,
            "name" => 'gum',
            "price" => 50,
            "is_hidden" => 0
        ],
    ];

これをarray_filterのアロー関数でフィルタリングする。

// 例1
$less = array_filter($products , fn($v) => $v['price'] < 100);
$more = array_filter($products , fn($v) => $v['price'] > 100);

// 例2
$border = 100;
$less = array_filter($products , fn($v) => $v['price'] < $border);
$more = array_filter($products , fn($v) => $v['price'] > $border);

// 例3
$border = 100;
$less = array_filter($products , fn($v,$k) => $v['price'] < $border ,ARRAY_FILTER_USE_BOTH ); 
$more = array_filter($products , fn($v,$k) => $v['price'] > $border ,ARRAY_FILTER_USE_BOTH );

//キー0からの連番にしたい場合
$less = [...array_filter($products , fn($v) => $v['price'] < $border)];  
$more = [...array_filter($products , fn($v) => $v['price'] > $border)];  

$less = array_values(array_filter($products , fn($v) => $v['price'] < $border));  
$more = array_values(array_filter($products , fn($v) => $v['price'] > $border));  

一覧データについて、表示、非表示で分けたい

// 例1
$show = array_filter($products , fn($v) => $v['is_hidden'] == true);
$hidden = array_filter($products , fn($v) => $v['is_hidden'] == false);

// 例2
$displayed = true;
$show = array_filter($products , fn($v) => $v['is_hidden'] != $displayed);
$hidden  = array_filter($products , fn($v) => $v['is_hidden'] == $displayed);

// 例3
$displayed = true;
$show = array_filter($products , fn($v,$k) => $v['is_hidden'] != $displayed, ARRAY_FILTER_USE_BOTH ); 
$hidden = array_filter($products , fn($v,$k) => $v['is_hidden'] == $displayed, ARRAY_FILTER_USE_BOTH );

//キー0からの連番にしたい場合
$show = [...array_filter($products , fn($v) => $v['is_hidden'] != $displayed)];  
$hidden = [...array_filter($products , fn($v) => $v['is_hidden'] == $displayed)];  

$show = array_values(array_filter($products , fn($v) => $v['is_hidden'] != $displayed));  
$hidden = array_values(array_filter($products , fn($v) => $v['is_hidden'] == $displayed));  

このケースならこの書き方ができるよね?と、すぐに幾つか候補が思い浮かぶようにしたい。

php, programming

Posted by 異世界攻略班