[PHP]複数のカテゴリからなるオプションの組み合わせを、全通り取得する方法

タイトルだけだと意味がわからないと思うので例をあげますね*1

「カテゴリ」と「オプション」の定義

例えば自動車。

自動車を購入しようとするとき、車種、排気量、色、トランスミッション、駆動方式など、いくつかの選択基準がありますよね?
これがタイトルの「カテゴリ」に当たる部分です。

そして、それぞれの選択基準に複数の選択肢があります。これがタイトルの「オプション」の部分。
これから話すことのために、これを配列にしてみます。

$data = array(
	0 => array(
		'Category' => '車種',
		'Option' => array(
			0 => 'セダン',
			1 => 'ワンボックス',
		),
	),
	1 => array(
		'Category' => '排気量',
		'Option' => array(
			0 => '3ナンバー',
			1 => '5ナンバー',
			2 => '軽自動車',
		),
	),
	2 => array(
		'Category' => '色',
		'Option' => array(
			0 => '白',
			1 => '黒',
			2 => '赤',
		),
	),
	3 => array(
		'Category' => 'トランスミッション',
		'Option' => array(
			0 => 'オートマチック',
			1 => 'マニュアル',
		),
	),
	4 => array(
		'Category' => '駆動方式',
		'Option' => array(
			0 => '2WD',
			1 => '4WD',
		),
	),
);

ちなみにこれ、CakePHPでCategoryにhasManyでOptionをアソシエーションした時の出力を参考に書きました。正確にはCategoryとOptionの中身も配列になりますが説明に不要なので省略してあります。

オプションの組み合わせを全通り取得する

自動車を選ぶときに、各カテゴリから1つずつオプションを選択していくと、2x3x3x2x2 = 72通りの選択が可能です。
これを取得する方法をメモしたいというのがこの記事の趣旨です(ようやくここまで来た)。

多分これ、きちんとプログラミングを学んだ方なら初歩的な処理だと思うのですが、僕の場合は独学でここまで来たので、こういう基礎的なロジックパターンが頭に入っていないんですよね。ですから、これを実現するのには少し骨が折れました。

今の僕にとって再帰処理を頭に描くのは、まだすんなりいかない感じですが、なんとか完成したソースがこちらです。
$dataは先程の配列です。


function saiki($categoryKey = 0, $spec = '') {
	global $data;	// 先程定義した配列だと思ってください。
	if (!empty($data[$categoryKey]['Option'])) {
		foreach ($data[$categoryKey]['Option'] as $option) {
			// ここで自分自身(saiki関数)を呼ぶ処理です。引数の$specに取得したカテゴリとオプションを加えて渡します。
			saiki($categoryKey + 1, $spec.$data[$categoryKey]['Category'].":".$option."/");
		}
	} else {
		// カテゴリの最後までたどったらechoします。
		echo $spec.'<br />';
	}
	
}

と、こんな感じになりました。
実際に動かして確認したい方もいると思うので、動くサンプルを用意してみました*2

サンプルソース:saiki.zip

配列にカテゴリやオプションを加えて試してみてね。

応用について

アパレル関係のオーダーメイドECサイトの案件で、今回の処理を応用してオプションの全通りの組み合わせの商品を扱えるシステムを制作しました。

上記の処理を応用すると、オプションごとに振られた規定桁数のコードを組み合わせて商品コードや画像名を生成したり、オプションごとの金額を加算して組み合わせによって金額を変えるといったことも可能です。

また、処理を変えることで、例えば特定のカテゴリーから複数のオプションを選択したりすることも可能だと思います。
応用次第で色々な事に使えそうですね。

あとがき

なぜ恥を晒してこの記事を書こうと思ったかというと、この処理を書くにあたってディレクトリ探査や総当りの再帰処理のサンプルソースがとても参考になったからです。

ソースがあればそれを頭の中で想像して動かすことができるので、理解がしやすいですよね。
なので、僕も拙いながらここに残しておくことで誰かの役に立てたらいいなと思った次第です。*3

また、こうして記事にしたことで頭が整理できたのもよかったです。
再帰に対する苦手意識も少しは克服できました^^

  1. 僕がもう少しモノを知っていれば、もっと端的に説明できるのかもしれませんが、数学?とか理系の話が大嫌いだったのでうまく説明できません。ご勘弁を。 []
  2. 僕の環境で動いたので大丈夫だと思うのですが、おかしな所があったらご指摘ください []
  3. 自分でも記事を書いたことを忘れた頃に検索したりすると結構自分の記事がヒットして、なるほど?ってなることも多いんですよね笑 []
スポンサーリンク
336x280_1
336x280_1

シェアする

  • このエントリーをはてなブックマークに追加

フォローする

スポンサーリンク
336x280_1