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
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
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
30分でDoctrineの仕組みと使い方を完全にマスターする / phpconkagawa 2025 Doctrine
ttskch
5
1k
いりゃあせ、PHPカンファレンス名古屋2025 / Welcome to PHP Conference Nagoya 2025
ttskch
1
490
PHPとAPI Platformで作る本格的なWeb APIアプリケーション(入門編) / phpcon 2024 Intro to API Platform
ttskch
0
1k
今年書いた技術記事で伸びたやつの自慢と自分の中では力作なのにさっぱり伸びなかったやつの供養 / My Tech Articles 2024
ttskch
2
180
FigmaとPHPで作る1ミリたりとも表示崩れしない最強の帳票印刷ソリューション
ttskch
47
42k
データベース/SQL超入門!完全初心者向けに世界一分かりやすく解説します
ttskch
1
7.3k
Symfony UX Autocompleteとかいう 顧客が本当に必要だったもの
ttskch
0
2.2k
就活生あるいは新人エンジニアさんへのお節介なアドバイス
ttskch
0
1.6k
symfony/pantherでWordleを解いてみた
ttskch
0
380
Other Decks in Programming
See All in Programming
AI前提で考えるiOSアプリのモダナイズ設計
yuukiw00w
0
220
なるべく楽してバックエンドに型をつけたい!(楽とは言ってない)
hibiki_cube
0
130
2年のAppleウォレットパス開発の振り返り
muno92
PRO
0
190
AgentCoreとHuman in the Loop
har1101
5
200
LLM Observabilityによる 対話型音声AIアプリケーションの安定運用
gekko0114
2
410
フロントエンド開発の勘所 -複数事業を経験して見えた判断軸の違い-
heimusu
7
2.7k
QAフローを最適化し、品質水準を満たしながらリリースまでの期間を最短化する #RSGT2026
shibayu36
2
4.1k
Claude Codeの「Compacting Conversation」を体感50%減! CLAUDE.md + 8 Skills で挑むコンテキスト管理術
kmurahama
1
820
余白を設計しフロントエンド開発を 加速させる
tsukuha
7
2k
【卒業研究】会話ログ分析によるユーザーごとの関心に応じた話題提案手法
momok47
0
180
Kotlin Multiplatform Meetup - Compose Multiplatform 외부 의존성 아키텍처 설계부터 운영까지
wisemuji
0
180
ThorVG Viewer In VS Code
nors
0
750
Featured
See All Featured
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
34k
YesSQL, Process and Tooling at Scale
rocio
174
15k
The Invisible Side of Design
smashingmag
302
51k
Stop Working from a Prison Cell
hatefulcrawdad
273
21k
Side Projects
sachag
455
43k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
231
22k
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
280
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
110
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
170
Build your cross-platform service in a week with App Engine
jlugia
234
18k
Tell your own story through comics
letsgokoyo
1
800
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.6k
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!ʗ