Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
PHPでCSVのインポート/エクスポートに立ち向かう
Search
Takashi Kanemoto
May 29, 2021
Programming
1
2.5k
PHPでCSVのインポート/エクスポートに立ち向かう
PHPカンファレンス沖縄2021の発表資料です。
https://connpass.com/event/212058/
Takashi Kanemoto
May 29, 2021
Tweet
Share
More Decks by Takashi Kanemoto
See All by Takashi Kanemoto
いりゃあせ、PHPカンファレンス名古屋2025 / Welcome to PHP Conference Nagoya 2025
ttskch
1
380
PHPとAPI Platformで作る本格的なWeb APIアプリケーション(入門編) / phpcon 2024 Intro to API Platform
ttskch
0
820
今年書いた技術記事で伸びたやつの自慢と自分の中では力作なのにさっぱり伸びなかったやつの供養 / My Tech Articles 2024
ttskch
2
140
FigmaとPHPで作る1ミリたりとも表示崩れしない最強の帳票印刷ソリューション
ttskch
47
39k
データベース/SQL超入門!完全初心者向けに世界一分かりやすく解説します
ttskch
1
6.3k
Symfony UX Autocompleteとかいう 顧客が本当に必要だったもの
ttskch
0
2.1k
就活生あるいは新人エンジニアさんへのお節介なアドバイス
ttskch
0
1.6k
symfony/pantherでWordleを解いてみた
ttskch
0
350
ついに、Webアプリでの帳票印刷のベストプラクティスを編み出しました💡
ttskch
16
20k
Other Decks in Programming
See All in Programming
「リーダーは意思決定する人」って本当?~ 学びを現場で活かす、リーダー4ヶ月目の試行錯誤 ~
marina1017
0
240
あのころの iPod を どうにか再生させたい
orumin
2
2.5k
CSC305 Summer Lecture 05
javiergs
PRO
0
110
レガシープロジェクトで最大限AIの恩恵を受けられるようClaude Codeを利用する
tk1351
2
1.1k
STUNMESH-go: Wireguard NAT穿隧工具的源起與介紹
tjjh89017
0
380
LLMOpsのパフォーマンスを支える技術と現場で実践した改善
po3rin
8
980
エンジニアのための”最低限いい感じ”デザイン入門
shunshobon
0
130
なぜ今、Terraformの本を書いたのか? - 著者陣に聞く!『Terraformではじめる実践IaC』登壇資料
fufuhu
4
650
コンテキストエンジニアリング Cursor編
kinopeee
1
700
CSC305 Summer Lecture 12
javiergs
PRO
0
110
書き捨てではなく継続開発可能なコードをAIコーディングエージェントで書くために意識していること
shuyakinjo
1
300
A Gopher's Guide to Vibe Coding
danicat
0
170
Featured
See All Featured
Optimising Largest Contentful Paint
csswizardry
37
3.4k
Fantastic passwords and where to find them - at NoRuKo
philnash
51
3.4k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
36
2.5k
Agile that works and the tools we love
rasmusluckow
329
21k
Rebuilding a faster, lazier Slack
samanthasiow
83
9.1k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
53
2.9k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
283
13k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
570
Code Review Best Practice
trishagee
70
19k
Navigating Team Friction
lara
189
15k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
VelocityConf: Rendering Performance Case Studies
addyosmani
332
24k
Transcript
/32 2021/05/29 #phpcon_okinawa @ttskch 1 PHPͰCSVͷΠϯϙʔτ/ ΤΫεϙʔτʹཱ͔ͪ͏
/32 • ϦεςΟϯάࠂͷձࣾͰWebαʔϏεΛ࡞ͬͯ·ͨ͠ • CTOͱͯ͠ࡏ੶ͨ͠8ؒͰɺࣾһ2໊ˠ60໊ɺ ച্ن5000ສԁˠ27ԯԁʹ·Ͱ 💪 💪 💪
• ຊΛॻ͍ͨΓSchooͰߨٛͨ͠Γͱ͍ͬͨ׆ಈ 2 ͖ͨͭͪ ʙ2020/03 (ג)ΧϧςοτίϛϡχέʔγϣϯζCTO 📝 blog.ttskch.com/thank-you-quartet-communications @ttskch
/32 • डୗ։ൃͱࣾ֎CTO/ٕज़ސۀத৺Ͱ׆ಈͯ͠·͢ • Symfony͕େ͖Ͱ͢ ✨ • ڈΞυϕϯτΧϨϯμʔΛ1ਓͰ15ॻ͍ͨΓ 10ສจࣈͷిࢠॻ੶Λແྉެ։ͨ͠Γ͠·ͨ͠💪💪💪
3 ͖ͨͭͪ 2020/04ʙ ϑϦʔϥϯεWebΤϯδχΞ 👨💻 https://kannade.jp @ttskch
/32 2021/05/29 #phpcon_okinawa @ttskch 4 PHPͰCSVͷΠϯϙʔτ/ ΤΫεϙʔτʹཱ͔ͪ͏
/32 • ࣮ExcelBOM͖UTF-8ͷCSVΛ։͚ΔͷͰSJISͰग़ྗ͢Δඞཁͳ͍ • league/csvΛͬͨΠϯϙʔτ/ΤΫεϙʔτͷ࣮ྫΛհ • Πϯϙʔτ/ΤΫεϙʔτʹಛԽͨ͠ttskch/bulkonyΛ͑ ͬͱ؆୯/ॊೈʹ࣮Ͱ͖Δ 5
✅͜ͷτʔΫͷཁ 10͔͠ͳ͍ͷͰαϥοͱͰ͢🙏
/32 6 ExcelBOM͖UTF-8ͷ CSVΛ։͚Δ
/32 7 ҙ֎ͱΒΕ͍ͯͳ͍ࣄ࣮ https://ja.wikipedia.org/wiki/UTF-8#όΠτॱϚʔΫͷ༻ ExcelBOM͖UTF-8ͷCSVΛ։͚Δ ٯʹݴ͏ͱɺBOM͖Ͱ͋ΕUTF-8Ͱී௨ʹ։͚Δ😳
/32 $fp = fopen('/path/to/output.csv', 'w+');ʊ fwrite($fp, "\xEF\xBB\xBF"); // ϑΝΠϧͷઌ಄ʹBOMΛૠೖ foreach
($data as $row) {ʊ fputcsv($fp, $row);ʊ }ʊ fclose($fp); 8 PHPͰग़ྗ͢Δྫ https://ja.wikipedia.org/wiki/όΠτॱϚʔΫ ϑΝΠϧͷઌ಄ʹ ”EF BB BF” ͱ͍͏όΠφϦΛՃ͢Δ͚ͩ👌 ExcelBOM͖UTF-8ͷCSVΛ։͚Δ
/32 $fp = fopen('/path/to/output.csv', 'w+');ʊ fwrite($fp, "\xEF\xBB\xBF"); // ϑΝΠϧͷઌ಄ʹBOMΛૠೖ foreach
($data as $row) {ʊ fputcsv($fp, $row);ʊ }ʊ fclose($fp); 9 PHPͰग़ྗ͢Δྫ https://ja.wikipedia.org/wiki/όΠτॱϚʔΫ ϑΝΠϧͷઌ಄ʹ ”EF BB BF” ͱ͍͏όΠφϦΛՃ͢Δ͚ͩ👌 ExcelBOM͖UTF-8ͷCSVΛ։͚Δ
/32 $fp = fopen('/path/to/output.csv', 'w+');ʊ fwrite($fp, "\xEF\xBB\xBF"); // ϑΝΠϧͷઌ಄ʹBOMΛૠೖ foreach
($data as $row) {ʊ fputcsv($fp, $row);ʊ }ʊ fclose($fp); 10 PHPͰग़ྗ͢Δྫ https://ja.wikipedia.org/wiki/όΠτॱϚʔΫ ϑΝΠϧͷઌ಄ʹ ”EF BB BF” ͱ͍͏όΠφϦΛՃ͢Δ͚ͩ👌 ExcelBOM͖UTF-8ͷCSVΛ։͚Δ
/32 • ExcelͰ։͍ͯΒ͏ͨΊ͚ͩʹSJISͰग़ྗ͢Δඞཁͳ͍ • UTF-8͔ΒSJISʹม͢ΔͱSJISʹଘࡏ͠ͳ͍จࣈ͕ ? ʹͳΔ • SJIS͔ΒͷΠϯϙʔτͬͱհͳͷͰɺ
ΞϓϦ͕ు͍ͨCSVΛΠϯϙʔτʹ͏߹ಛʹBOM͖UTF-8Ұ 11 ✅ BOM͖UTF-8Λੵۃతʹ͓͏ ExcelBOM͖UTF-8ͷCSVΛ։͚Δ ※ SJISͷCSVΛ҆શʹѻ͓͏ͱ͢Δͱߟྀ͢Δ͜ͱ͕৭ʑ͋Γ·͢ʢεϥΠυͷ࠷ޙͰࢀߟURLΛ͝հ͠·͢ʣ
/32 12 league/csvΛͬͨ Πϯϙʔτ/ΤΫεϙʔτͷ࣮ྫ
/32 • ۙΑ͘ΘΕ͍ͯΔɺCSVΛ؆୯ʹѻ͏ͨΊͷPHPϥΠϒϥϦ • fgetcsvͱ͔ΛͬͯࣗྗͰϨΠϠʔͷίʔυΛॻ͔ͳͯ͘ɺ CSVΛ͍͍ײ͡ʹநԽͯ͘͠ΕΔ 13 league/csvͱ league/csvΛͬͨΠϯϙʔτ/ΤΫεϙʔτͷ࣮ྫ
/32 $csv = Reader::createFromPath('/path/to/input.csv');ʊ $csv->setHeaderOffset(0); // ϔομʔ͕0ߦͰ͋Δ͜ͱΛએݴ $rows = $csv->getRecords();ʊ
foreach ($rows as $row) {ʊ // ࣮ࡍͷΠϯϙʔτॲཧ } 14 Πϯϙʔτͷ࣮ྫ league/csvΛͬͨΠϯϙʔτ/ΤΫεϙʔτͷ࣮ྫ
/32 $csv = Reader::createFromPath('/path/to/input.csv');ʊ $csv->setHeaderOffset(0); // ϔομʔ͕0ߦͰ͋Δ͜ͱΛએݴ $rows = $csv->getRecords();ʊ
foreach ($rows as $row) {ʊ // ࣮ࡍͷΠϯϙʔτॲཧ } 15 Πϯϙʔτͷ࣮ྫ league/csvΛͬͨΠϯϙʔτ/ΤΫεϙʔτͷ࣮ྫ શσʔλͷྻͰͳ͘ 1ߦͣͭऔಘͰ͖ΔΠςϨʔλͳͷͰ লϝϞϦ
/32 $csv = Reader::createFromPath('/path/to/input.csv');ʊ $csv->setHeaderOffset(0); // ϔομʔ͕0ߦͰ͋Δ͜ͱΛએݴ $rows = $csv->getRecords();ʊ
foreach ($rows as $row) {ʊ // ࣮ࡍͷΠϯϙʔτॲཧ } 16 Πϯϙʔτͷ࣮ྫ league/csvΛͬͨΠϯϙʔτ/ΤΫεϙʔτͷ࣮ྫ ϔομʔߦͷҐஔΛએݴͨ͠ͷͰ [ 'ྻ໊' => '', 'ྻ໊' => '', : ] ͱ͍͏ܗࣜͷྻσʔλ͕ಘΒΕΔ ͜ΕΛͬͯΠϯϙʔτॲཧΛॻ͘
/32 $csv = Writer::createFromPath('php://temp');ʊ $csv->insertOne(['ྻ1', 'ྻ2', 'ྻ3']); // Ұߦૠೖ $csv->insertAll($data);
// ೋ࣍ݩྻͰෳߦ·ͱΊͯૠೖ // ग़ྗ࣌ʹBOMΛՃ͢ΔΑ͏ઃఆ $csv->setOutputBOM("\xEF\xBB\xBF");ʊ $csv->output('μϯϩʔυ.csv'); 17 ΤΫεϙʔτͷ࣮ྫ league/csvΛͬͨΠϯϙʔτ/ΤΫεϙʔτͷ࣮ྫ
/32 $csv = Writer::createFromPath('php://temp');ʊ $csv->insertOne(['ྻ1', 'ྻ2', 'ྻ3']); // Ұߦૠೖ $csv->insertAll($data);
// ೋ࣍ݩྻͰෳߦ·ͱΊͯૠೖ // ग़ྗ࣌ʹBOMΛՃ͢ΔΑ͏ઃఆ $csv->setOutputBOM("\xEF\xBB\xBF");ʊ $csv->output('μϯϩʔυ.csv'); 18 ΤΫεϙʔτͷ࣮ྫ league/csvΛͬͨΠϯϙʔτ/ΤΫεϙʔτͷ࣮ྫ ࢦఆͨ͠ϑΝΠϧ໊Ͱ_ μϯϩʔυͤ͞ΔͨΊͷ HTTPϨεϙϯεΛૹग़
/32 • ಛʹΠϯϙʔτɺ • ೖྗσʔλͷόϦσʔγϣϯ • Πϯϙʔτ࣮ߦલʹը໘ͰϓϨϏϡʔ ͳͲ͕ඞཁʹͳΔͱ్ʹΔ͜ͱ͕૿͑ͯͻͨ͢Βେม😓 19 Ͱɺ·ͩ·ͩࣗલͰ࣮͖͢͜ͱ͕ଟ͍…
league/csvΛͬͨΠϯϙʔτ/ΤΫεϙʔτͷ࣮ྫ
/32 20
/32 21 Ή͠Ζ͜͜Λָ͍ͨ͠…😓
/32 22 ttskch/bulkony
/32 • PHPΞϓϦʹΠϯϙʔτ/ΤΫεϙʔτػೳΛ࣮͢Δࡍʹ ͍ͭॻ͍͍ͯͨ͋Ε͜ΕΛϥΠϒϥϦʹΓग़͠·ͨ͠ • ⚡BOM͖UTF-8ͰͷΤΫεϙʔτ • ⚡ϝϞϦޮʹྀͨ͠Πϯϙʔτ/ΤΫεϙʔτͷΛఏڙ •
⚡Πϯϙʔτ༰ͷόϦσʔγϣϯͷΛఏڙ • ⚡Πϯϙʔτ༰ͷϓϨϏϡʔػೳͷΛఏڙ 23 ttskch/bulkonyͱ ttskch/bulkony
/32 use Ttskch\Bulkony\Export\Exporter;ʊ $exporter = new Exporter();ʊ $rowGenerator = new
App\RowGenerator(); // ࣗ࡞Ϋϥε // ϑΝΠϧγεςϜʹग़ྗ $exporter->export('/path/to/output.csv', $rowGenerator);ʊ // HTTPϨεϙϯεΛૹग़ $exporter->exportAndOutput('users.csv', $rowGenerator); 24 ར༻ΠϝʔδʢΤΫεϙʔτʣ ttskch/bulkony
/32 use Ttskch\Bulkony\Export\Exporter;ʊ $exporter = new Exporter();ʊ $rowGenerator = new
App\RowGenerator(); // ࣗ࡞Ϋϥε // ϑΝΠϧγεςϜʹग़ྗ $exporter->export('/path/to/output.csv', $rowGenerator);ʊ // HTTPϨεϙϯεΛૹग़ $exporter->exportAndOutput('users.csv', $rowGenerator); 25 ར༻ΠϝʔδʢΤΫεϙʔτʣ ttskch/bulkony ͜ͷΫϥεʹCSVߦͷੜखॱΛॻ͘👨💻 ※ ৄࡉREADMEΛ͝ࢀর͍ͩ͘͞🙏
/32 use Ttskch\Bulkony\Import\Importer;ʊ $importer = new Importer();ʊ $rowVisitor = new
App\RowVisitor(); // ࣗ࡞Ϋϥε // CSVͷͲͷηϧʹόϦσʔγϣϯΤϥʔ͕͋Δ͔ɺ // ΠϯϙʔτʹΑͬͯͲ͜ͷ͕ߋ৽͞ΕΔ͔ɺͷใ͕ಘΒΕΔ $preview = $importer->preview('/path/to/input.csv', $rowVisitor);ʊ // ͦΕΛը໘ʹදࣔ͢ΕϓϨϏϡʔػೳ render('some.template', ['preview' => $preview]); 26 ར༻ΠϝʔδʢΠϯϙʔτʣ ttskch/bulkony
/32 use Ttskch\Bulkony\Import\Importer;ʊ $importer = new Importer();ʊ $rowVisitor = new
App\RowVisitor(); // ࣗ࡞Ϋϥε // CSVͷͲͷηϧʹόϦσʔγϣϯΤϥʔ͕͋Δ͔ɺ // ΠϯϙʔτʹΑͬͯͲ͜ͷ͕ߋ৽͞ΕΔ͔ɺͷใ͕ಘΒΕΔ $preview = $importer->preview('/path/to/input.csv', $rowVisitor);ʊ // ͦΕΛը໘ʹදࣔ͢ΕϓϨϏϡʔػೳ render('some.template', ['preview' => $preview]); 27 ར༻ΠϝʔδʢΠϯϙʔτʣ ttskch/bulkony ͜ͷΫϥεʹߦ͝ͱͷΠϯϙʔτ όϦσʔγϣϯͷϩδοΫΛॻ͘👨💻 ※ ৄࡉREADMEΛ͝ࢀর͍ͩ͘͞🙏
/32 28 ΑΖ͚͠ΕͬͯΈ͍ͯͩ͘͞😇 https://github.com/ttskch/bulkony
/32 29 ·ͱΊ
/32 • ࣮ExcelBOM͖UTF-8ͷCSVΛ։͚ΔͷͰSJISͰग़ྗ͢Δඞཁͳ͍ • league/csvΛͬͨΠϯϙʔτ/ΤΫεϙʔτͷ࣮ྫΛհ • Πϯϙʔτ/ΤΫεϙʔτʹಛԽͨ͠ttskch/bulkonyΛ͑ ͬͱ؆୯/ॊೈʹ࣮Ͱ͖Δ 30
✅͜ͷτʔΫͷཁ
/32 • SJISͷCSVΛจࣈԽ͚ͤͣʹಡΈॻ͖͢Δํ๏ʹ͍ͭͯɺ PHPerKaigi 2021ͷए༿ষ͞Μͷηογϣϯ͕େมࢀߟʹͳΓ·͢ • https://youtu.be/pc6ov8HWt1A 31 📝ؔ࿈͢Δ͓͢͢Ίใ
/32 32 @ttskch ʘThanks!ʗ