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

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

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

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

CakePHP

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Q&A

解決済

2回答

2956閲覧

CakePHPで3次元配列をCSVファイルに書き出しダウンロードさせたい

GrassfieldK

総合スコア50

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

CakePHP

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

0グッド

1クリップ

投稿2017/04/20 01:49

編集2017/04/20 02:17

目的

ほとんどタイトルのとおりです。
現在、データベースから取得したデータが3次元連想配列に格納されており、それをCSVファイルに書き出したいです。

わからない点

Webでいろいろと検索してみたところ、2次元配列をCSVに書き出す方法はいろいろあっても3次元配列を書き出す方法については見当たりませんでした。

もちろん、その2次元配列を書き出す方法を応用すれば、目的は達成できるとは思い、色々と試してはみましたがうまく行きません。

また、そもそもテーブルは2次元なのにクエリの実行結果が3次元配列に格納されているというのがおかしいのかなと思いましたが、
自分の書いているコードではどうしても3次元連想配列に格納されるようです。

極端に複雑でなければどんなロジックでも構いませんので、解決策をご存知の方、ぜひご教授お願いいたします。

参考にしたサイト

具体的なコードなど

実際に扱っているコードの一部を編集したものなので、もしかするとコード内容とdebug()内容に矛盾があるかもしれませんが、イメージとして捉えていただければありがたいです…

  • ExportTableModel.php

php

1 function select(){ 2 $sql = <<<EOD 3 SELECT 4 * 5 FROM 6 table1 7 INNER JOIN 8 table2 9 ON table1.id = tabe2.id 10EOD; 11 return $this->query($sql, false); // この取得方法だと3次元連想配列に格納される -> 何か別の方法がある? 12 }
  • ExportTableController.php

php

1 2class ExportTableController extends AppController { 3 public $uses = array('ExportTableModel'); 4 public $components = array('Common'); 5 6 public $autoLayout = false; 7 8 public function index() { 9 $table = $this->ExportTableModel->export(); // 上記のfunctionを実行 10 $this->set(compact("table")); 11 } 12 } 13}
  • index.ctp(ほとんど載せる意味ないですね…)

php

1<?php 2 $assoc_data = array( 3 array('name' => '佐藤', 'address' => '東京都', 'old' => '29歳'), 4 array('name' => '田中', 'address' => '千葉県', 'old' => '31歳'), 5 array('name' => '鈴木', 'address' => '北海道', 'old' => '54歳') 6 ); 7 $csv_header = array( 8 9 ); 10 11 header('Content-Type: application/octet-stream'); 12 header('Content-Disposition: attachment; filename=data.csv'); 13 14 $stream = fopen('php://output','w'); 15 fputcsv($stream, $csv_header); 16 17 foreach($table as $key => $assoc_row){ 18 $numeric_row = array(); 19 foreach ($csv_header as $header_name){ 20 mb_convert_variables('SJIS-win', 'UTF-8', $assoc_row[$header_name]); 21 $numeric_row[] = $assoc_row[$header_name]; 22 } 23 fputcsv($stream, $numeric_row); 24 } 25?>
  • debug($table)
array( (int) 0 => array( 'table1' => array( 'id_1' => '001', 'family_name' => 'yamada' ), 'table2' => array( 'id_1' => '001', 'id_2' => '001', 'first_name' => 'taro' ) ), (int) 0 => array( 'table1' => array( 'id_1' => '001', 'family_name' => 'yamada' ), 'table2' => array( 'id_1' => '001', 'id_2' => '002', 'first_name' => 'jiro' ) ) )

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

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

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

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

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

guest

回答2

0

ベストアンサー

CakePHP のバージョンは 2系でしょうか?
であれば、バーチャルフィールドを使用するのが良いと思います。
https://book.cakephp.org/2.0/ja/models/virtual-fields.html#sql

具体的には、ExportTableModel.php の selectメソッドを以下のように変更してみてください。

php

1 function select(){ 2 3 $this->virtualFields['id_2'] = 0; 4 $this->virtualFields['first_name'] = 0; 5 6 $sql = <<<EOD 7 SELECT 8 table1.id_1, 9 table2.id_2 AS table1__id_2, 10 table1.family_name, 11 table2.first_name AS table1__first_name 12 FROM 13 table1 14 INNER JOIN 15 table2 16 ON table1.id_1 = tabe2.id_1 17EOD; 18 return $this->query($sql, false); 19 }

これで、返される配列は以下のような構造になるはずです。

array( (int) 0 => array( 'table1' => array( 'id_1' => '001', 'id_2' => '001', 'family_name' => 'yamada' 'first_name' => 'taro' ) ), (int) 1 => array( 'table1' => array( 'id_1' => '001', 'id_2' => '002', 'family_name' => 'yamada' 'first_name' => 'jiro' ) ) )

3次元配列のままではありますが、以下のように、ほぼ2次元配列と同じイメージでCSVファイルを作成できます。

php

1$handle = fopen('test.csv', 'w'); 2 3foreach ($result as $row) { 4 fputcsv($handle, $row['table1']); 5}

投稿2017/04/21 03:05

編集2017/04/21 03:23
KiyoshiMotoki

総合スコア4791

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

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

GrassfieldK

2017/05/09 05:22

丁寧なご回答ありがとうございます! 2つ目のコードがとても扱いやすく、ベストアンサーに選びました。 いただいたコードを参考にした(というかほぼコピペですが)ところ、なんとか目的を達成することができました。後々きちんと理解しておこうと思います。ありがとうございました。
guest

0

配列の階層が深い所にあるデータを取得する場合、 Hash::get() が便利です。

php

1// ドット区切りで表現 2$csv_header = [ 3 'table1.id_1', 4 'table1.family_name', 5 ....以下省略 6]; 7foreach($table as $key => $assoc_row){ 8 $numeric_row = array(); 9 foreach ($csv_header as $index => $header_name){ 10 $col = Hash::get($assoc_row, $header_name); 11 mb_convert_variables('SJIS-win', 'UTF-8', $col); 12 $numeric_row[$index] = $col; 13 } 14 fputcsv($stream, $numeric_row); 15 } 16

投稿2017/04/21 01:46

okinaka3

総合スコア304

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

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

GrassfieldK

2017/05/09 05:23

返事が遅くなってしまい申し訳ないです。 まだ経験が浅く、Hashを扱う勇気が出ませんでした…とはいえ、便利なものは使えるようにならないといけないので、ある程度慣れてきたらいただいたコードを読み返してみようとおもいます。 ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問