ITの隊長のブログ

ITの隊長のブログです。Rubyを使って仕事しています。最近も色々やっているお(^ω^ = ^ω^)

助けて先輩!俺のPHPの配列の組み直しは最適なのか確認したい

スポンサードリンク

http://www.flickr.com/photos/76345376@N00/2557151889
photo by aturkus


今年初めての記事が質問になりました。


旧年からずっっっっっっっっっっと!プログラムしていますが、やればやるほど自分のレベルの低さにビビってしまって、新年早々泣きそうです(´;ω;)


んで、知り合いの先輩に質問したいので、記事にしました。


お題はこれ↓

MySQLからJoinした配列を組み直したい

概要

下記SQL文があるとします。

select
`table_name01`.`id`,
`table_name01`.`title`,
`table_name02`.`table_02`,
`table_name03`.`table_03`
from
`db_name`.`contents` AS `table_name01`
inner join `db_name`.`table_name02`
on (`table_name01`.`id` = `table_name02`.`id`)
right join `db_name`.`table01_relations_table03`
on (`table_name01`.`id` = `table01_relations_table03`.`table01_id`)
inner join `db_name`.`table_name03`
on (`table01_relations_table03`.`table03_id` = `table_name03`.`id`)
;


上のつながりはすっげーわかりにくいと思うので、図にすると下記になります。

f:id:aipacommander:20150103181429p:plain


こいつが引っ張ってくるデータはこんな感じ。

array(
	(int) 0 => array(
		'table_name01' => array(
			'id' => '3',
			'title' => '俺、ツインテールになります。1話 テイルレッドが可愛い',
		),
		'table_name02' => array(
			'table_02' => 'yahoo'
		),
		'table_name03' => array(
			'table_03' => 'TV'
		)
	),
	(int) 1 => array(
		'table_name01' => array(
			'id' => '1',
			'title' => '3DS『モンスターハンター4G』 プロモーション映像4',
		),
		'table_name02' => array(
			'table_02' => 'yahoo'
		),
		'table_name03' => array(
			'table_03' => 'モンスターハンター'
		)
	),
	(int) 2 => array(
		'table_name01' => array(
			'id' => '1',
			'title' => '3DS『モンスターハンター4G』 プロモーション映像4',
		),
		'table_name02' => array(
			'table_02' => 'yahoo'
		),
		'table_name03' => array(
			'table_03' => 'アニメ'
		)
	)
)


このデータを下記のようにしたいのです。

array(
	(int) 0 => array(
		'id' => '3',
		'title' => '俺、ツインテールになります。1話 テイルレッドが可愛い',
		'table_02' => 'yahoo'
		'table_03' => 'TV'
	),
	(int) 1 => array(
		'id' => '1',
		'title' => '3DS『モンスターハンター4G』 プロモーション映像4',
		'table_02' => 'yahoo'
		'table_03' => array(
                    (int) 0 => 'モンスターハンター',
                    (int) 1 => 'アニメ'
                )
	)
)


理由としては、sqlからもらったデータをそのまま使うとループがすごいことになるので、できれば組み替えたいのです。


また、結果を確認するとarray(1)とarray(2)の結果だけ、table_03の値以外、重複しています。実はこれも悩ませた一つで、これについては、他の連想の重複を消した上で、table_03は配列にしたい。これがめっちゃめんどくせぇ(´Д`)


その他理由として、phpを今使うにあたり、このようなjoinデータはいっぱいでてくると思うんです。なので、組み替えの練習をしているところでした。

環境

自分の出した結果(´;ω;)


一応下記のようにコードを書いたら取り出せました。。。


流れとして

  • 最初の親indexでforeach()します。
  • んで、子のindexデータの最後の葉データをarray_walk_recursive()を使って、普通の連想配列にします。
  • 普通の連想配列にしたら、最後に$result_arrayにarray_push()(配列を追加)します。
  • また、途中でtable_03以外の値が同じ連想配列はtable_03を配列化して、重複を取り除かなければいけない。。。
  • わかりにくいけど、table03の値を追加するindex番号はRecursiveIteratorIteratorを使って判断しています。
<?php
...
// 整列した配列を格納したい変数です
$result_array = array();
// $sql_dataには先程のsql結果のデータが入っています。
foreach($sql_data as $k => $v) {

	$tmp_array_save = array();
	array_walk_recursive($v, function(&$value, $key) use (&$tmp_array_save) {
		$tmp_array_save[$key] = $value;
	});

	// 初回のみ$result_arrayは連想配列ではないため、比較するとエラーになる
	// なので、配列が空であれば0なので、条件分岐でfalse(初回追加となる)
	if (count($result_array)) {

		// 返す配列にすでに存在しているかチェック
		$contents_id_array = Hash::extract($result_array, '{n}.contents_id');
		if (in_array($tmp_array_save['contents_id'], $contents_id_array)) {

			// 存在している場合は重複なので、追加
			// contents_idから逆引きして格納が必要な配列番号を探す
			$iterator = new RecursiveIteratorIterator(
			    new RecursiveArrayIterator($result_array),
			    RecursiveIteratorIterator::SELF_FIRST
			);
			// table03が追加される配列番号を格納する変数
			$add_index_number = '';
			foreach ($iterator as $iterate_key => $iterate_leaf) {
				if (is_array($iterate_leaf)) {
					$add_index_number = $iterate_key;
				}
			}
			// table03の値が重複していないかチェック、していなければ追加
			if (! in_array($tmp_array_save['table_03'], $result_array[$add_index_number])) {
				$tmp_tags_data = $result_array[$add_index_number]['table_03'];
				$result_array[$add_index_number]['table_03'] = array();
				array_push($result_array[$add_index_number]['table_03'],
					$tmp_array_save['table_03'],
					$tmp_tags_data);
			}
		} else {
			// 存在していない場合は新規追加
			array_push($result_array, $tmp_array_save);
		}
	} else {
		// 初回の追加
		array_push($result_array, $tmp_array_save);
	}
}
// 確認コード
dump($result_array);

まとめ


説明して思ったんだけど、これってすごく説明しづらくない? あと俺のコードめちゃめちゃわかりにくい・・・。


プログラムできない俺が言ってもアレなんですが、プログラムって難しい組み方しちゃいけないと思うの(´・ω・)


読み辛いコードを書くこと自体あんましよくないと思います。。。orz


助けて先輩!!!(´;ω;)