最近、仕事でデータベースを使ったERPの構築ばかりしています。
それもサーバーでPHPしか使えないので、PHP+MySQLの環境なんですよね。
Webサイトであれば、王道の構成なので、この環境に慣れておくのって悪くないかもしれないと自分を言い聞かせながら仕事に勤しんでいます。
データベースからのレスポンスは多くの場合二次元配列になっているので、取得したデータをさらにPHPで加工する時に、いろいろと技を覚えておくと仕事がはかどるので、今回はその取得したデータの調理方法をブログに書き残しておきます。
こんがりおいしく仕上げましょう。
二次元配列から一次元配列を作る
サンプルでユーザーデータのようなデータを取得した場合に、
名前の一覧や、年齢一覧のようなデータを算出したい場合などに使えるデータ調理法です。
この章で扱うデータ
// データベースからの取得データ
$database_response = [
[
"name" => "foo",
"age" => 15,
"pref" => "tokyo",
],
[
"name" => "bar",
"age" => 22,
"pref" => "osaka",
],
[
"name" => "test",
"age" => 30,
"pref" => "hokkaido",
],
];
任意の値を抜き出す
データベースから取得した二次元配列のデータの中で、特定の値のみ抜き出して、別の配列を作成したい場合には、次のように処理します。
// array_columnを使って、子階層の"name"の値を取得
$result = array_column($database_response, "name");
結果を出力
print_r($result);
> Array
> (
> [0] => foo
> [1] => bar
> [2] => test
> )
残念ながら仕事で与えられたPHPのバージョンが、php5.4だったので、array_columnはver5.5からの新機能のため、上記コードが使えませんでした。
そんな場合は以下のように取得します。
$result = array_map(function($element) {return $element["name"];}, $database_response);
array_columnをarray_mapに置き換えて無名関数で対象のkey値を返しています。
上記で返ったデータをarray_mapで配列に格納するという少し回りくどい処理ですが、なれると比較的楽な方法ですね。
取得したデータのスキーマを取得
データベースから取得したデータで、どういう値が入っているのか判断するために、key値にあたるスキーマ(schema)の一覧を取得したい場合の調理法は以下のとおりです。
// 最初のデータのkey値を抜き出す
$keys = array_keys($database_response[0]);
結果を出力
print_r($keys);
> Array
> (
> [0] => name
> [1] => age
> [2] => pref
> )
2つの二次元配列のデータの差分データを見つける方法
複数の類似データベースがある場合、データを検索して、得られた結果を比較する時に使える技です。
この章で扱うデータ
// DBから得た結果(例)
$result1 = [
['id' => 1, 'name' => 'Alice', 'email' => 'alice@example.com'],
['id' => 2, 'name' => 'Bob', 'email' => 'bob@example.com']
];
$result2 = [
['id' => 1, 'name' => 'Alice', 'email' => 'alice@example.com'],
['id' => 3, 'name' => 'Charlie', 'email' => 'charlie@example.com']
];
差分一覧を取得
2つのデータベースから取得するデータが同じ場合に以下の調理法で、差分が取得できます。
// 比較関数を使って差分を取得
$diff = array_udiff($result1, $result2, function($a, $b) {
return strcmp(serialize($a), serialize($b));
});
結果を出力
print_r($diff);
> Array
> (
> [1] => Array
> (
> [id] => 2
> [name] => Bob
> [email] => bob@example.com
> )
> )
取得したデータが違うので、特定のカラムの値のみを比較したい場合
// DBから得た結果(例)
$result1 = [
['id' => 1, 'name' => 'Alice', 'email' => 'alice@example.com' , "flg" => 1],
['id' => 2, 'name' => 'Bob', 'email' => 'bob@example.com' , "flg" => 0]
];
$result2 = [
['id' => 1, 'name' => 'Alice', 'mail' => 'alice@example.com'],
['id' => 3, 'name' => 'Charlie', 'mail' => 'charlie@example.com']
];
このように、スキーマのkey値も違うし、スキーマの内容も違っている場合、idとnameとemail(mail)の値のみで違うものを取得したい場合はどうすればいいでしょう?
比較対象の配列をそれぞれ作り出す
そんな場合は、同じスキーマになるようにデータを作り出します。
$data1 = array_map(function($e){
return [
"id" => $e["id"],
"name" => $e["name"],
"email" => $e["email"],
];
}, $result1);
$data2 = array_map(function($e){
return [
"id" => $e["id"],
"name" => $e["name"],
"email" => $e["mail"],
];
}, $result2);
そして、先ほどと同じように比較処理
$diff = array_udiff($data1, $data2, function($a, $b) {
return strcmp(serialize($a), serialize($b));
});
結果を出力
最初と全く同じ値が返りました。
print_r($diff);
> Array
> (
> [1] => Array
> (
> [id] => 2
> [name] => Bob
> [email] => bob@example.com
> )
> )
二次元配列の任意のkey値の合計や平均を求める
数値を含むデータの場合は、合計や平均などを調理する必要があります。
この章で扱うデータ
$database_response = [
[
"name" => "foo",
"parchace" => 980,
],
[
"name" => "bar",
"parchace" => 1500,
],
[
"name" => "test",
"parchace" => 2980,
],
];
合計値
$sum = array_sum(array_map(function($e){
return $e["parchace"];
}, $database_response));
実行結果
print_r($sum);
> 5460
平均値
平均を求めるには、合計値をデータ件数で割ってあげればいいだけです。
$avarage = array_sum(array_map(function($e){
return $e["parchace"];
}, $database_response)) / count($database_response);
実行結果
print_r($avarage);
> 1820
おまけ
たま〜に使いたくなることがある配列調理方法を備忘録しておきます。
2つの一次元配列をkey,valueの連想配列に置き換える
$keys = ["a","b","c"];
$values = [1,2,3];
// key = valueの連想配列に結合
$obj = array_combine($keys, $values);
// 結果表示
print_r($obj);
> Array
> (
> [a] => 1
> [b] => 2
> [c] => 3
> )
あとがき
このブログ記事を読む人、PHPエンジニア以外にいないよな〜と思いながら、「これは、備忘録!」と思い込んで書き上げました。
上記みたいな基本関数を使って処理しなくても、全てfor文を使えば難なくできてしまいます。
それでも、関数を使ってスマートにプログラミングを調理したくなるのは、プログラマーの性でもあります。
なので、このブログを読んで楽しいと感じてもらえた人は、同じ感性を持っている人ということですね。
仲良くしましょう!
0 件のコメント:
コメントを投稿