Upgrade to Pro — share decks privately, control downloads, hide ads and more …

【PHPerKaigi2021】PHPでCSVを安心して扱うために

80728f01bc074c5c2f0d4859258bd793?s=47 ICKX
March 27, 2021

 【PHPerKaigi2021】PHPでCSVを安心して扱うために

PHPerKaigi2021で発表した『PHPでCSVを安心して扱うために』の資料です。
サンプル・解説コードは https://github.com/wakabadou/phperkaigi2021 で公開しています。

80728f01bc074c5c2f0d4859258bd793?s=128

ICKX

March 27, 2021
Tweet

Transcript

  1. None
  2. • • • • • • • •

  3. • • • • • 次(予定) 今

  4. • • fopen fgetcsv fputcsv • SplFileObject • league/csv •

  5. • • • • • SplFileObject fgetcsv fputcsv league/csv •

    fw3/stream
  6. • • • • SplFileObject fgetcsv • league/csv

  7. • https://packagist.org/packages/fw3/streams • https://packagist.org/packages/fw3_for_old/streams • • • • • https://github.com/wakabadou/phperkaigi2021

  8. None
  9. • • f(?:get|put)csv • • • mb_convert_encoding • • •

  10. • fgutcsv fputcsv SplFileObject league/csv

  11. • composer require fw3/streamsとしてfw3/streamsを インストールします • 次の例のようにstream filterを登録します ※ 同一リクエスト内で一度だけ登録すればOKです

    • 後は必要なクラスをuseし、無名関数の中でSpecクラスを用いて SplFileObjectなどでCSVを処理すればOKです
  12. • 環境や案件により、ComposerやAutoloaderが使えない場合もあります • その場合は、fw3-for-old/streamsを使用してください • https://github.com/fw3-for-old/streams を開き”Code”ボタンを押下 ”Download ZIP”からアーカイブをダウンロードしてください •

    ダウンロードしたアーカイブを任意のディレクトリに展開してください • アーカイブ内のsrc/filters_require_once.phpを読み込みます require_once sprintf(‘%s/src/filters_require_once.php’, $path_to_copy_dir); として読み込んでください • 以降はuseで指定する名前空間のベンダー名をfw3からfw3_for_oldに変更すれば fw3/streamsを使って解決(事前準備)と同じ手順を適用できます Specで記述した内容を 文字列として展開 ここを置き換えます
  13. • fw3/streamsを使って解決(事前準備)を行った上で次の記述を行います • StreamFilterSpec::decorateForCsv()メソッドを利用して実行前後に必要な処理を自動適用、 確実に動作させます • 後はSpecクラスで変換する内容を定義して、SplFileObjectクラスなどいつも通りの CSV書き込み処理を記述するだけでOKです • !!注意!!

    この無名関数の中からyieldで返すことはできません •
  14. Specによる設定 Specで記述した内容を 文字列として展開 後は”いつも通りの処理”をするだけ

  15. • SpecクラスはStreamFilter用設定文字列を返すため、SplFileObjectに限らず、fputcsv関数やleague/csvでもその ままシームレスに利用できます。 • SplFileObjectの場合 • fputcsvの場合 • league/csvの場合 同一の記述でOK

    同一の記述でOK 同一の記述でOK
  16. • 現場都合で無名関数を使えないケースもあります • その場合は実行前後に必要な処理を手動で記述するだけでOKです

  17. 実行前に必要な設定 実行後に必要な設定 事前にフィルタ登録 登録済みの場合は不要です 前のページにもあった ”いつも通りの処理” 無名関数を用いたサンプルと同じ処理 無名関数版では緑色領域の 内容をクロージャーの前後で 自動実行しています。

  18. • CSV書き込みと同様、fw3/streamsを使って解決(事前準備)を行った上で次の記述を行います • StreamFilterSpec::decorateForCsv()メソッドを利用して実行前後に必要な処理を自動適用、 確実に動作させます • 後はSpecクラスで変換する内容を定義して、SplFileObjectクラスなどいつも通りの CSV読み込み処理を記述するだけでOKです • 無名関数の返り値をそのまま呼び出し元で受け取る事ができます

    • !!注意!! この無名関数の中からyieldで返すことはできません •
  19. Specによる設定 Specで記述した内容を 文字列として展開 後は”いつも通りの処理”をするだけ 返り値として 受け取れます 返り値として 受け取れます

  20. • SpecクラスはStreamFilter用設定文字列を返すため、SplFileObjectに限らず、fgutcsv関数やleague/csvでもその ままシームレスに利用できます。 • SplFileObjectの場合 • fputcsvの場合 • league/csvの場合 同一の記述でOK

    同一の記述でOK 同一の記述でOK
  21. • 現場都合で無名関数を使えないケースもあります • その場合は実行前後に必要な処理を手動で記述するだけでOKです

  22. 実行前に必要な設定 実行後に必要な設定 事前にフィルタ登録 登録済みの場合は不要です 前のページにもあった ”いつも通りの処理” 無名関数版では緑色領域の 内容をクロージャーの前後で 自動実行しています。 無名関数を用いたサンプルと同じ処理

  23. None
  24. • • https://www.php.net/manual/ja/stream.filters.php • • 詳しくは技術評論社から発売中の 『みんなのPHP 現場で役立つ最新ノウハウ!』 第7章 厳選!

    PHP活用テクニック紹介 ストリームフィルタを用いた透過的なCSV入出力 をご参照ください
  25. Spec • • • • • • •

  26. • SplFileObject fgetcsv fputcsv • • •

  27. • •

  28. • •

  29. None
  30. • explode implode • fgutcsv fputcsv SplFileObject • file_get_contents file_put_contents

    • fread fwite • popen • iconv • league/csv
  31. explode implode • file_get_contents explode • implode file_put_contents

  32. explode implode

  33. explode implode • • • • しません •

  34. explode implode • • • つらくきびしいげんじつ

  35. fgutcsv fputcsv SplFileObject • fgutcsv fputcsv SplFileObject • •

  36. fgutcsv fputcsv SplFileObject

  37. fgutcsv fputcsv SplFileObject • • • • 0x5C • “同”“ソ”

    213 ��“�¥”,213 • • CSVと直接関係はないですが「ポ」など 2バイト目が0x7C (|)な文字が含まれた事で コマンドのパイプが成立する話もあります
  38. fgutcsv fputcsv SplFileObject • fgutcsv fputcsv SplFileObject • ja_JP.UTF-8 en_US.UTF-8

  39. fgutcsv fputcsv SplFileObject • setlocale

  40. fgutcsv fputcsv SplFileObject • • OSにインストールされている • locale -a •

    Japanese_Japan.932 • • • • setlocale setlocale
  41. fgutcsv fputcsv SplFileObject • • OSにインストール • setlocale • setlocale

    • • setlocale •
  42. fgutcsv fputcsv SplFileObject

  43. file_get_contents file_put_contents • 新規にインストール • • mb_convert_encoding

  44. file_get_contents file_put_contents • •

  45. file_get_contents file_put_contents • •

  46. fread fwite • file_get_contents file_put_contents • fread fwrite • fgutcsv

  47. fread fwite

  48. fread fwite • • 実用するべきではありません •

  49. • • fread fwite • 実用するべきではない fread fwite

  50. popen • -r runオプション fgetcsv •

  51. popen

  52. popen • • • • • •

  53. popen •

  54. iconv • • fgetcsv fputcsv SplFileObject league/csv •

  55. iconv

  56. iconv •

  57. iconv • • iconv • 8.0.2-cli-alpine • • 行が無かったことになるだけで、処理は続行されます •

    • •
  58. iconv • iconv • • • •

  59. league/csv • • • mb_convert_encoding iconv filter

  60. league/csv

  61. league/csv •

  62. league/csv • • • SplFileObject Stream::getCurrentRecord() fgetcsv fgutcsv fputcsv SplFileObject

    • Q:pull request出してあげたら? A:league/csv自体の手触りを変えずに 実現する方法が思いつかない
  63. league/csv • https://github.com/thephpleague/csv/issues/339 league/csv • fgutcsv fputcsv SplFileObject

  64. • explode implode • • fgutcsv fputcsv SplFileObject • •

    file_get_contents file_put_contents • • • fread fwite • 可及的速やかに別の手段を検討しましょう
  65. • popen • • • iconv • 可及的速やかに別の手段を検討しましょう • league/csv