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
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Takashi Kanemoto
May 29, 2021
Programming
1
2.6k
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
API Platformを活用したPHPによる本格的なWeb API開発 / api-platform-book-intro
ttskch
1
160
30分でDoctrineの仕組みと使い方を完全にマスターする / phpconkagawa 2025 Doctrine
ttskch
5
1.2k
いりゃあせ、PHPカンファレンス名古屋2025 / Welcome to PHP Conference Nagoya 2025
ttskch
1
520
PHPとAPI Platformで作る本格的なWeb APIアプリケーション(入門編) / phpcon 2024 Intro to API Platform
ttskch
0
1.2k
今年書いた技術記事で伸びたやつの自慢と自分の中では力作なのにさっぱり伸びなかったやつの供養 / My Tech Articles 2024
ttskch
2
190
FigmaとPHPで作る1ミリたりとも表示崩れしない最強の帳票印刷ソリューション
ttskch
48
43k
データベース/SQL超入門!完全初心者向けに世界一分かりやすく解説します
ttskch
2
7.8k
Symfony UX Autocompleteとかいう 顧客が本当に必要だったもの
ttskch
0
2.2k
就活生あるいは新人エンジニアさんへのお節介なアドバイス
ttskch
0
1.7k
Other Decks in Programming
See All in Programming
Migration to Signals, Signal Forms, Resource API, and NgRx Signal Store @Angular Days 03/2026 Munich
manfredsteyer
PRO
0
170
ロボットのための工場に灯りは要らない
watany
12
3.2k
PHPで TLSのプロトコルを実装してみる
higaki_program
0
520
Nuxt Server Components
wattanx
0
140
Redox OS でのネームスペース管理と chroot の実現
isanethen
0
460
OTP を自動で入力する裏技
megabitsenmzq
0
130
今こそ押さえておきたい アマゾンウェブサービス(AWS)の データベースの基礎 おもクラ #6版
satoshi256kbyte
1
200
我々はなぜ「層」を分けるのか〜「関心の分離」と「抽象化」で手に入れる変更に強いシンプルな設計〜 #phperkaigi / PHPerKaigi 2026
shogogg
2
630
テレメトリーシグナルが導くパフォーマンス最適化 / Performance Optimization Driven by Telemetry Signals
seike460
PRO
2
180
LM Linkで(非力な!)ノートPCでローカルLLM
seosoft
0
250
Ruby and LLM Ecosystem 2nd
koic
1
1.3k
AI Assistants for Your Angular Solutions
manfredsteyer
PRO
0
160
Featured
See All Featured
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
0
170
A Modern Web Designer's Workflow
chriscoyier
698
190k
Chasing Engaging Ingredients in Design
codingconduct
0
150
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
2
180
Visualization
eitanlees
150
17k
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
1.9k
sira's awesome portfolio website redesign presentation
elsirapls
0
200
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
1
310
How STYLIGHT went responsive
nonsquared
100
6k
The #1 spot is gone: here's how to win anyway
tamaranovitovic
2
1k
Thoughts on Productivity
jonyablonski
75
5.1k
Git: the NoSQL Database
bkeepers
PRO
432
67k
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!ʗ