質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

CakePHP

CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

Q&A

解決済

3回答

3876閲覧

DBから取得したデータを綺麗に整形したい【php7.0】【cakePHP3.3】

tato.aoki

総合スコア33

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

CakePHP

CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

0グッド

1クリップ

投稿2016/09/22 16:24

編集2016/09/22 16:47

###DBから取得したデータを綺麗に整形したい
MySQLテーブル内にあるCategoryテーブルからデータを取得してきれいな配列を作成したいと思っています。

###Categoryテーブルの内容

idnameparent
1スマートフォンNULL
2ガラケーNULL
3iOS1
4Android1
6iPhone6s3
7iPhone73
8GalaxsyS64
9GalaxsyS74
10Gara-K12
11Gara-K22
【id】 ・・・・・・・AutoInsertmentされた値 【name】・・・・カテゴリの名称 【parent】・・・属する親カテゴリのid(一つ上の階層)

###生成したい配列

[ (int) 0 => 'スマートフォン', (int) 1 => ' iOS', (int) 2 => ' iPhone6s', (int) 3 => ' iPhone7', (int) 4 => ' Android', (int) 5 => ' GalaxsyS6', (int) 6 => ' GalaxsyS7', (int) 7 => 'ガラケー', (int) 8 => ' Gara-K1', (int) 9 => ' Gara-K1' ]

【補足】
DBから取得したデータに含まれるParentを使って配列を並べ替え階層がわかるようにインデント(半角スペースで表現)を入れた配列を作りたい

###SHOW CREATE TABLE文

sql

1CREATE TABLE `Category` ( 2 `id` int(11) NOT NULL AUTO_INCREMENT, 3 `name` text NOT NULL, 4 `parent` int(11) DEFAULT NULL, 5 PRIMARY KEY (`id`) 6) ENGINE=MyISAM AUTO_INCREMENT=11 DEFAULT CHARSET=utf8

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/09/22 16:31 編集

SHOW CREATE TABLE LIKE 'tablename' で得られるCREATE文を提示してください。 あと、Autoincreament なのに、id に重複があります。
tato.aoki

2016/09/22 16:50

早速、ありがとうございます。質問を編集いたしましたので確認いただければ幸いでございます
guest

回答3

0

php

1<?php 2 3class MobileModel 4{ 5 6 public $id = null; 7 public $name = null; 8 public $parent = null; 9 public $children = []; 10 11} 12 13$arr = [ 14 ['id' => 1, 'name' => 'スマートフォン', 'parent' => 0] 15 , ['id' => 2, 'name' => 'ガラケー', 'parent' => 0] 16 , ['id' => 3, 'name' => 'iOS', 'parent' => 1] 17 , ['id' => 4, 'name' => 'Android', 'parent' => 1] 18 , ['id' => 5, 'name' => 'iPhone6s', 'parent' => 3] 19 , ['id' => 6, 'name' => 'iPhone7', 'parent' => 3] 20 , ['id' => 7, 'name' => 'GalaxsyS6', 'parent' => 4] 21 , ['id' => 8, 'name' => 'GalaxsyS7', 'parent' => 4] 22 , ['id' => 9, 'name' => 'Gara-K1', 'parent' => 2] 23 , ['id' => 10, 'name' => 'Gara-K2', 'parent' => 2] 24]; 25 26$arrModels = []; 27foreach ($arr as $val) { 28 $objMobile = new MobileModel(); 29 $objMobile->id = $val['id']; 30 $objMobile->name = $val['name']; 31 $objMobile->parent = $val['parent']; 32 if (isset($arrModels[$val['parent']])) { 33 $arrModels[$val['parent']]->children[] = $objMobile; 34 } 35 $arrModels[$val['id']] = $objMobile; 36} 37 38$res = []; 39foreach ($arrModels as $model) { 40 if (!empty($model->children) && $model->parent == '0') { 41 $res[] = $model; 42 } 43} 44 45$GLOBALS['answer'] = []; 46 47function format($arr, $gen = 0) 48{ 49 foreach ($arr as $v) { 50 $GLOBALS['answer'][] = str_repeat(' ', $gen * 4) . $v->name; 51 if (count($v->children)) { 52 format($v->children, $gen + 1); 53 } 54 } 55 return $GLOBALS['answer']; 56} 57 58var_dump(format($res));
array(10) { [0]=> string(21) "スマートフォン" [1]=> string(7) " iOS" [2]=> string(16) " iPhone6s" [3]=> string(15) " iPhone7" [4]=> string(11) " Android" [5]=> string(17) " GalaxsyS6" [6]=> string(17) " GalaxsyS7" [7]=> string(12) "ガラケー" [8]=> string(11) " Gara-K1" [9]=> string(11) " Gara-K2" }

できるだけ簡単なロジックを使おうとしましたが、$GLOBALS とか出てくるのは美しくないですね…
クラスに処理をまとめて、結果配列はプロパティに持った方が、綺麗だと思いますね。
あとは、CakePHP の作法に合わせて見てください。

投稿2016/09/22 18:25

編集2016/09/22 18:29
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tato.aoki

2016/09/23 17:05

回答ありがとうございます。 とても早くサンプルを作っていただき助かりました。 今回はCakePHP側で処理を行いましたが、やはりご教授いただいたようにPHPでのロジックを組み立てる能力は必須だと思いますのでソースコードを参考に勉強させていただきます。 とても参考になる回答、ありがとうございました。
guest

0

階層モデルについてはテーブルの構造を調整し、プロシージャを利用することで簡単に処理できます
詳細についてはこちらを参照してください

理論的にはなんやかんやわかりづらいですが、わからなくてもプロシージャが処理してくれます
以下サンプル

  • テーブル作成、データ投入

SQL

1CREATE TABLE tel_tbl(id INT NOT NULL PRIMARY KEY,name VARCHAR(20),parent_id INT NULL,level INT NOT NULL,l INT NOT NULL,r INT NOT NULL); 2INSERT INTO tel_tbl(id,name,parent_id) VALUES(1,'スマートフォン',NULL),(2,'ガラケー',NULL),(3,'iOS',1),(4,'Android',1),(6,'iPhone6s',3),(7,'iPhone7',3),(8,'GalaxsyS6',4),(9,'GalaxsyS7',4),(10,'Gara-K1',2),(11,'Gara-K2',2);
  • プロシージャ作成

SQL

1DROP PROCEDURE IF EXISTS SET_LR; 2DELIMITER // 3CREATE PROCEDURE SET_LR() 4BEGIN 5DECLARE a INT DEFAULT 0; 6DECLARE done INT DEFAULT 0; 7DECLARE CUR CURSOR FOR 8SELECT id FROM tel_tbl WHERE level=0 ORDER BY parent_id ASC,id DESC; 9DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1; 10UPDATE tel_tbl SET level=0,l=0,r=0; 11UPDATE tel_tbl SET level=1,l=(SELECT @a:=@a+1 FROM (SELECT @a:=0) AS sub),r=@a:=@a+1 12WHERE parent_id IS NULL 13ORDER BY id; 14OPEN CUR; 15REPEAT 16FETCH CUR INTO a; 17IF NOT done THEN 18SET @id=a; 19SET @sql='UPDATE tel_tbl as a1,tel_tbl as a2,tel_tbl as a3 SET a1.l=a2.l+1,a1.r=a2.l+2,a1.level=a2.level+1,a2.r=a2.r+2,a3.r=a3.r+2 WHERE a1.parent_id=a2.id AND a2.l<a3.r AND a1.id=?'; 20PREPARE stmt from @sql; 21EXECUTE stmt USING @id; 22SET @sql='UPDATE tel_tbl as a1,tel_tbl as a2,tel_tbl as a3 SET a3.l=a3.l+2 WHERE a1.parent_id=a2.id AND a2.l<a3.l and a3.id!=a1.id AND a1.id=?'; 23PREPARE stmt from @sql; 24EXECUTE stmt USING @id; 25END IF; 26UNTIL done END REPEAT; 27CLOSE CUR; 28END 29// 30DELIMITER ; 31
  • プロシージャを実行しlevel、l、rの更新

※tel_dbにデータ投入の度にCALLする

SQL

1CALL SET_LR();
  • 試しに表示

SQL

1SELECT * FROM tel_tbl ORDER BY id ASC;
  • 命題のデータ表示

SQL

1SELECT id,CONCAT(REPEAT(' ',(level-1)*4),name) AS name FROM tel_tbl ORDER BY l ASC,id ASC;

投稿2016/09/23 01:02

yambejp

総合スコア114771

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2016/09/23 01:24

ちなみに、MySQLにおける変数の使用の仕方について 今回のサンプルのようなやり方は保証されていないようです。 99%問題ないとはおもいますが、だめだった場合もうちょい別の工夫が必要です
tato.aoki

2016/09/23 17:01

回答ありがとうございます。 MySQL側での処理について今後学んでいこうと思います。 とても参考になる回答、ありがとうございました。
guest

0

ベストアンサー

ちょっと方向性が違うかもしれませんが、Cakephpにはツリー構造のデータを扱うTreeBehaviorというのがあります。

Cakephp3のマニュアル(まだ英語しかない)
※本質的にはCakephp2と変わっていないので、日本語で概要をつかみたいなら、Cakephp2のマニュアルでもいいと思います。

※マニュアルのクイックツアーにあるように、Cakephp3ではfind('treeList')とやると同じような配列を生成してくれるようです。

使うとなると、テーブル構造を変えたりする必要があるので、
このテーブルのデータを編集する機能などをつけたり、複雑な検索をfindでしたいので、あればやる価値はあると思います。ただし、使うシーンが限られているなら自前実装でいいと思います。

投稿2016/09/22 22:19

編集2016/09/22 22:56
popobot

総合スコア6586

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tato.aoki

2016/09/23 17:03

回答ありがとうございます。 CakePHPでの処理に関してドキュメントを見落としていました。 最終的にはご教授いただいた方法で解決いたしましたのでベストアンサーに選ばせて頂きました。 とても参考になる回答、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問