【PHP】array_filterと具体的なシチュエーション
状況
全てのデータを問い合わせた後で、例えば「金額で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));
このケースならこの書き方ができるよね?と、すぐに幾つか候補が思い浮かぶようにしたい。