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

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

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

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

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

PHP

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

Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

Q&A

4回答

6150閲覧

【laravel】csvに出力する際に、出力される値の位置がズレているものがある。

退会済みユーザー

退会済みユーザー

総合スコア0

CSV

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

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

PHP

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

Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

0グッド

0クリップ

投稿2017/07/26 02:11

編集2022/01/12 10:55

###前提・実現したいこと
csvをDLしようとする際、必ず出力されるCSVの1行目を除く他すべての1列目が空になってしまいます。
具体的には、1列目に入るべき値が2列目に入ってしまっています。
また、一部こちらが望んだ並び順ではない並び順が出力されます。
CSVに出力されるものの並び順を確認するためにはどこをみればよいのでしょうか?

これらの問題を解決するためにご助力いただけないでしょうか。

何卒よろしくお願いいたします。

###該当のソースコード

php

1list ($titles, $value) = $this->titlesValue($type, $ids, $items); 2do { 3 $csv = storage_path().'/tmp/'.md5(uniqid(mt_rand(), true)).'.tmp'; 4 } while (file_exists($csvPath)); 5$buf = fopen($csv, 'w'); 6 fwrite($buf, "\xEF\xBB\xBF"); 7 fputcsv($buf, $titles); 8 foreach ($ids as $id) { 9 if (isset($valuess[$id])) { 10 fputcsv($buf, $valuess[$id]); 11 } 12 } 13fclose($buf); 14$file = (string)request()->input('file'); 15 return response()->download($csvPath, ($file!==''?$file:'export').'.csv')->deleteFileAfterSend(true);

php

1public function main($type) { 2 $komoji = substr($type, 0, 1); 3 $ids = $this->ids($type); 4 $items = array_map(function($c){return $c->toArray();}, call_user_func('\\App\\Models\\'.strtoupper($komoji).'item::uses')); 5return $this->download($type, $ids, $items); 6}

###追記
CSVの中身を確認しましたら、(1行目を除く)全ての1列目に入れるもののみ、全ての2列目に入っておりました。
その原因は、1列目と2列目のそれぞれのセルに該当する値を挿入するための指標であるvalueが同じ値であったためだと考えております。

php

1 public function titlesValuess($type, $ids, $items) { 2 $info = $this->info()[$type]; 3 $komoji = substr($type, 0, 1); 4 $titles = []; 5 $data = []; 6 if (request()->input($komoji.'item')) { 7 $input = array_unique(array_map('intval',(array)request()->input($komoji.'item'))); 8 foreach ($items as $i => $item) { 9 if (in_array($item['id'], $input, true)) { 10 $titles[] = $item['name']; 11 $item['index'] = count($titles) - 1; 12 $data['item'][$item['id']] = $item; 13 } 14 } 15 } 16 if (!$titles) return [$titles, []]; 17 $valuess = array_fill_keys($ids, array_fill(0, count($titles), null)); 18 return [$titles, $valuess]; 19 }
titlesValuessの$titlesにdd array:5 [▼ 0 => "A" 1 => "B" 2 => "C" 3 => "D" 4 => "E" 5 => "F" titlesValuessの$valuessにdd 0 => null 1 => "A'" 2 => "B'" 3 => "C'" 4 => "D'" 5 => "F'" 6 => "G'" ※一部合致している箇所と、合致していない箇所がある状況にあります。

###試したこと
listのあるところで「dd($value);」をかけてみたところ、上記の配列が結果として出てきました。
また、「dd($titles);」ではCSVに出力される最初の行にあたる項目名が出力されます。

###補足情報(言語/FW/ツール等のバージョンなど)
laravel 5.1

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

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

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

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

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

aro10

2017/07/26 03:12

ソースコード中で、titlesValueという仕様不明なメソッドがあり、do〜whileの条件中の$csvPathがそれ以前で代入がなかったりと、意図せぬ挙動を原因究明するのにコードが不完全では良い回答は得られないかと思います。一度見直してみては如何でしょうか
rururu3

2017/07/26 03:32

dd($titles);もやってほしいです。
退会済みユーザー

退会済みユーザー

2017/07/26 03:57

ご指摘ありがとうございます。修正させていただきました
guest

回答4

0

1行目が空欄

csvをDLしようとする際、必ず出力されるCSVの第一行目が空になってしまいます。
具体的には、1列目に入るべき値が2列目に入ってしまっています。

CSVの1行目が空という事は、1行目に改行が挿入されている事になりますので、文字列上で改行が挿入されている箇所を特定して下さい。
前方に文字列が存在する為に、fputcsv() が改行を挿入している可能性はないでしょうか。
下記コードをコメントアウトしたら、どうなりますか。

PHP

1fwrite($buf, "\xEF\xBB\xBF");

これで現象が回避できるようでしたら、CSV文字列は自前で作る処理にする事で文字列前方に BOM を置き、file_put_contents() でまとめて出力してやれば良いと思います。

1行目?1列目?

csvをDLしようとする際、必ず出力されるCSVの第一行目が空になってしまいます。
具体的には、1列目に入るべき値が2列目に入ってしまっています。

「第一行目が空」で1行目と思い込んでいましたが、2行目では「1列目に入るべき値が2列目に入ってしまって」とあります。
「1行目」と「1列目」のどちらが正しいのでしょうか。

軽く調べたところ、PHPは基本的に BOM を解釈しないようなので、fputcsv() が BOMデータを有効な文字列を判断して、1列目に入るべきデータを「2列目のデータ」と判断して挿入している可能性があります。

BOM,"Cell-1A","Cell-1B" "Cell-2A","Cell-2B" "Cell-3A","Cell-3B"

これは質問文にある状況と一致する為、「1行目の1列目が空欄になってしまう」が正解な気がしますね。
解決法は先述と同様、CSV文字列を自前で組み立てて、file_put_contents() で出力する事になります。
調べてみたところ、PHPには str_getcsv() はありますが、CSV文字列を生成する関数はないようです。

ライブラリを探すのも良いですが、それほど難しい仕様ではないので自前で作るのも良いかと思います。

2行目以降の1列目が空欄になる

1行目の1列目以外のすべての1列目が空欄になります。
1行目の1列目に「項目名」が挿入され、それがずれていることはありません。

上記の通り、現象を再確認しました。
CSVデータは下記のようになっていると思われます。

"項目A","項目B" ,"Cell-1A","Cell-1B" ,"Cell-2A","Cell-2B" ,"Cell-3A","Cell-3B"

ならば、fputcsv() 起因や BOM 起因を疑う余地はありません。

PHP

1fputcsv($buf, $titles); // ここまでは期待通りに動作している 2foreach ($ids as $id) { 3 if (isset($valuess[$id])) { 4 fputcsv($buf, $valuess[$id]); // ここで1列目に入るべきデータが2列目にずれて挿入される 5 } 6}

疑うべきは変数 $valuess の値であり、$valuess[0][0] が空欄になっていると思われます。
var_dump() で値を確認して下さい。

PHP

1var_dump($valuess);

そして、変数 $valuess を生成しているコードを見直して下さい。

Re: YYama さん

投稿2017/07/26 04:12

編集2017/07/26 05:53
think49

総合スコア18156

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

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

退会済みユーザー

退会済みユーザー

2017/07/26 05:00

ご回答ありがとうございます。 fwriteを入れたのは、fputcsvで生じるutf8の文字化けを回避するためです。 また、fwriteをコメントアウトしましたが、「列」の問題を回避することができませんでした。
think49

2017/07/26 05:08

1行目と1列目については、どういう解釈が正しいのでしょうか。
退会済みユーザー

退会済みユーザー

2017/07/26 05:12

think49さんの仰る通り、「列」でございます。
think49

2017/07/26 05:15

私が書いたのは「1行目の1列目」ですが、それで正しいしょうか。 あるいは、行数に関わらず、一律に「1列目」が空欄になるのでしょうか(2行目以降も1列目が空欄になる)。
退会済みユーザー

退会済みユーザー

2017/07/26 05:17

CSVの1列目が空欄になります。 ですので、1列目に入るものが2列目に、2列目に入るものが3列目に入るというズレが生じております。
think49

2017/07/26 05:22

何か伝わっている感じがしないのですが…。 「1列目」は理解していますが、該当する行に条件はないのでしょうか、が質問の意図です。 つまり、「全ての行の1列目が空欄になる」と解釈してよろしいでしょうか。 「1列目が空欄」ですと、私は下記CSVデータを想定します。 ,"Cell-1A","Cell-1B" ,"Cell-2A","Cell-2B" ,"Cell-3A","Cell-3B"
退会済みユーザー

退会済みユーザー

2017/07/26 05:26

失礼いたしました。 1行目の1列目以外のすべての1列目が空欄になります。 1行目の1列目に「項目名」が挿入され、それがずれていることはありません。
退会済みユーザー

退会済みユーザー

2017/07/26 05:29

セル:1A以外の2A以降が空欄になり、本来2A以降の1列目に入るべき値が2B以降の列に入っております。
think49

2017/07/26 05:46

現象を理解しましたので、親記事に追記しました。 質問文にある「CSVの第一行目が空になってしまいます」が誤解の元なので、正確に伝わるように文面を修正した方が良いと思います。 「行」と「列」は全く違います。 文章による説明に自信がないようでしたら、出力されるCSVを簡易データで良いので、書くと伝わりやすいと思います。 "項目A","項目B" ,"Cell-1A","Cell-1B" ,"Cell-2A","Cell-2B" ,"Cell-3A","Cell-3B"
退会済みユーザー

退会済みユーザー

2017/07/26 06:04

ご迷惑をおかけしました。 var_dump($valuess)で値を確認したところ、[0][0]がnullになっていましたので、$valuessのコードを修正いたします。
think49

2017/08/02 08:37

一週間経過しましたが、進捗はいかがでしょうか。 $valuess を生成しているコードは質問文中にない為、私から具体的な回答は不可能な状況です。 もし、問題が継続しているのであれば、本質問をクローズして新しく質問を立てる事を検討してみてはいかがでしょうか。
guest

0

修正依頼に近いですが、内容が長いので解答として記載します

具体的には、1列目に入るべき値が2列目に入ってしまっています。

fputcsv($buf, $valuess[$id]);

ここで出力される内容のことだと思いますので、$valuess[$id]の値がこうだけど実際CSVみたらこうですって書いてもらわないと具体的にわかりません。

また、一部こちらが望んだ並び順ではない並び順が出力されます。

これも上と同様です。

CSVに出力されるものの並び順を確認するためにはどこをみればよいのでしょうか?

CSVに出力されてるものの並び順ならCSVをテキストエディタなりで見ればいいかと。

今の質問内容のままでは、$valuess[$id]が期待してる値になっていないだけの単なるバグなので
https://teratail.com/help/avoid-asking
推奨していない質問
コードをください・デバッグしてください等の丸投げの質問
に近いと思われますので、もう少し調べてみてはいかがでしょうか。

投稿2017/07/28 02:13

rururu3

総合スコア5545

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

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

退会済みユーザー

退会済みユーザー

2017/07/28 07:54

ご回答ありがとうございます。 もう少し自分で調べてみます。 ありがとうございます。
guest

0

参考までにCSV処理をライブラリを活用して行うのであれば、以下 thephpleague/csv のライブラリが扱いやすいです。
thephpleague/csv
CSV Writer connection
Laravel5でLeague/CSVを使ってCSV作成&ディスクに保存をサクッと実装する

投稿2017/07/26 12:49

aro10

総合スコア4106

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

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

0

nullを配列から取り除いたのを出したいのでしたら

fputcsv($buf, array_filter($valuess[$id]));

で出来ますが、配列の0番目を取り除いたのを出したいのでしたら、

fputcsv($buf, array_slice($valuess[$id], 1));

で出来るかと。

質問内容変わったので追記

titlesValuessの$valuessにdd 0 => null 1 => "A'" 2 => "B'" 3 => "C'" 4 => "D'" 5 => "E'" 6 => "F'"

0 => null

このデータが有るのが仕様なのかバグかを判断して修正すればいいかと
(インデントありますが$valuessは

$valuess = [null, "A", "B", "C", "D", "E", "F"];

ってことですよね&インデックスが0といってCSV出力されるとき無視はされません。

投稿2017/07/26 06:37

編集2017/07/27 07:42
rururu3

総合スコア5545

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問