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でResult型やってみよう
Search
higaki
July 19, 2025
Technology
780
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
PHPでResult型やってみよう
PHPConference関西2025の登壇資料です。
補足資料
https://zenn.dev/higaki/articles/my-php-result-type
higaki
July 19, 2025
More Decks by higaki
See All by higaki
PHPで tarballを実装してみる
higaki_program
0
21
PHPで TLSのプロトコルを実装してみるをもう一度しゃべりたい
higaki_program
0
380
PHPで TLSのプロトコルを実装してみる
higaki_program
0
890
PHPでResult型を なるべく使いやすい形で実装する
higaki_program
2
430
aspidaで型安全にREST APIのバックエンドを呼び出したい
higaki_program
0
810
Other Decks in Technology
See All in Technology
DMMブックスのNext.js化を加速させるAI活用 / Migrating DMM Books to Next.js with AI
kentarom
1
330
Genie Code ワークショップ 応用編 / Genie-Code-Workshop-advanced
databricksjapan
PRO
0
280
こんなアーキテクチャ図は嫌だ BEYOND THE TIME: 半年後の自分へ贈る15のメッセージ / 15 of Anti-pattern in AWS Architecture Diagrams
naospon
2
190
DGX Sparkを2台使って いろいろ動かす話
sonoda_mj
1
120
Instana&Bob トラブルシュートハンズオン
mayamasaki68
0
110
Amazon S3 Tablesに全部任せてみた結果——コンパクション/スナップショット管理は本当に手放せるか
shigeruoda
0
290
Kiro Crewしか勝たん!?
miu_crescent
PRO
0
160
Bet AI Day 2026丨How We Bet AI: AIとともに働く場をつくる
layerx
PRO
1
2k
データエンジニアリングワークショップ:Auto LoaderとSparkで学ぶデータパイプライン構築
databricksjapan
PRO
0
120
書籍『生成AIの安全性入門』の入門
wataoka
0
190
本番に近いテストをもっと手軽に - Postmanで広がるAPIテストの世界 / Expanding the World of API Testing with Postman
yokawasa
1
240
【Oracle AI Spotlight ウェビナー】AWSか、Azureか、Google Cloudか。その議論にオラクルを含める意義。
oracle4engineer
PRO
1
210
Featured
See All Featured
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
760
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
270
New Earth Scene 8
popppiees
3
2.5k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.9k
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
11k
Building Applications with DynamoDB
mza
96
7.2k
Evolving SEO for Evolving Search Engines
ryanjones
0
280
Reality Check: Gamification 10 Years Later
codingconduct
0
2.3k
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
890
WCS-LA-2024
lcolladotor
0
820
Transcript
PHPでResult型やってみよう @PHPカンファレンス関西2025 ひがき
話すこと • Result型とは • 各種エラーハンドリングの例 • PHPでどう実装する?(今日は省略) • 使いどころ
Result型とは??
Result型 とある処理が「成功」したこと、あるいは「失敗」したことを表現する 関数結果にアクセスする前に、関数が成功したか失敗したかのチェックが必要 try-catchの例外処理に頼らないエラーハンドリング PHPではデフォルトで実装されていない
fn divide(a: f64, b: f64) -> Result<f64, String> { if
b == 0.0 { Err("ゼロで割ることはできません ".to_string()) } else { Ok(a / b) } } // 呼び出し側 let result = divide(10.0, 0.0); if result.is_ok() { println!("結果: {:?}", result.unwrap()); } else { println!("エラー: {:?}", result.unwrap_err()); } /** * @return Result<float, string> */ function divide(float $a, float $b): Result { if ($b == 0.0) { return new Err("ゼロで割ることはできません "); } return new Ok($a / $b); } // 呼び出し側 $result = divide(10.0, 0.0); if ($result->isOk()) { echo "結果: " . $result->unwrap() . "\n"; } else { echo "エラー: " . $result->unwrapErr() . "\n"; } Rust PHP(僕の実装)
fn divide(a: f64, b: f64) -> Result<f64, String> { if
b == 0.0 { Err("ゼロで割ることはできません ".to_string()) } else { Ok(a / b) } } // 呼び出し側 let result = divide(10.0, 0.0); if result.is_ok() { println!("結果: {:?}", result.unwrap()); } else { println!("エラー: {:?}", result.unwrap_err()); } /** * @return Result<float, string> */ function divide(float $a, float $b): Result { if ($b == 0.0) { return new Err("ゼロで割ることはできません "); } return new Ok($a / $b); } // 呼び出し側 $result = divide(10.0, 0.0); if ($result->isOk()) { echo "結果: " . $result->unwrap() . "\n"; } else { echo "エラー: " . $result->unwrapErr() . "\n"; } Rust PHP(僕の実装)
fn divide(a: f64, b: f64) -> Result<f64, String> { if
b == 0.0 { Err("ゼロで割ることはできません ".to_string()) } else { Ok(a / b) } } // 呼び出し側 let result = divide(10.0, 0.0); if result.is_ok() { println!("結果: {:?}", result.unwrap()); } else { println!("エラー: {:?}", result.unwrap_err()); } /** * @return Result<float, string> */ function divide(float $a, float $b): Result { if ($b == 0.0) { return new Err("ゼロで割ることはできません "); } return new Ok($a / $b); } // 呼び出し側 $result = divide(10.0, 0.0); if ($result->isOk()) { echo "結果: " . $result->unwrap() . "\n"; } else { echo "エラー: " . $result->unwrapErr() . "\n"; } Rust PHP(僕の実装)
各種エラーハンドリングの例 ※説明のために愉快なコードも出てきますが🙏
1. try-catch 2. nullable 3. union型 4. Result 4つの例
1. try-catch 2. nullable 3. union型 4. Result 4つの例
function completePayment(ProcessingPayment $payment): CompletedPayment { if ($payment->amount <= 0) {
throw new PaymentAmountRuleError("Payment amount must be positive"); } return new CompletedPayment($payment->amount); } // 呼び出し側 try { $result = completePayment($payment); // ... 支払い完了時の処理 } catch (PaymentAmountRuleError $e) { // ... 支払金エラー時の処理 }
function completePayment(ProcessingPayment $payment): CompletedPayment { if ($payment->amount <= 0) {
throw new PaymentAmountRuleError("Payment amount must be positive"); } return new CompletedPayment($payment->amount); } // 呼び出し側 try { $result = completePayment($payment); // ... 支払い完了時の処理 } catch (PaymentAmountRuleError $e) { // ... 支払金エラー時の処理 }
よくあるPHPの例外処理 • 複数のエラーパターンを例外で表現可能 • フローが複雑になりがち(GOTOみたい) try-catch
1. try-catch 2. nullable 3. union型 4. Result 4つの例
function completePayment(ProcessingPayment $payment): ?CompletedPayment { if ($payment->amount <= 0) {
return null; } return new CompletedPayment($payment->amount); } // 呼び出し側 $result = completePayment($payment); if ($result === null) { // ... 支払金エラー時の処理 } // ... 支払い完了時の処理
function completePayment(ProcessingPayment $payment): ?CompletedPayment { if ($payment->amount <= 0) {
return null; } return new CompletedPayment($payment->amount); } // 呼び出し側 $result = completePayment($payment); if ($result === null) { // ... 支払金エラー時の処理 } // ... 支払い完了時の処理
稀によく見る • シンプルで軽量 • PHP 7.1〜 • エラーの詳細情報が得られない • 複数のエラーパターンを区別できない
nullable
1. try-catch 2. nullable 3. union型 4. Result 4つの例
function completePayment(ProcessingPayment $payment): CompletedPayment|PaymentAmountRuleError { if ($payment->amount <= 0) {
return new PaymentAmountRuleError("Payment amount must be positive"); } return new CompletedPayment($payment->amount); } // 呼び出し側 $result = completePayment($payment); if ($result instanceof PaymentAmountRuleError) { // ... 支払金エラー時の処理 } // ... 支払い完了時の処理
function completePayment(ProcessingPayment $payment): CompletedPayment|PaymentAmountRuleError { if ($payment->amount <= 0) {
return new PaymentAmountRuleError("Payment amount must be positive"); } return new CompletedPayment($payment->amount); } // 呼び出し側 $result = completePayment($payment); if ($result instanceof PaymentAmountRuleError) { // ... 支払金エラー時の処理 } // ... 支払い完了時の処理
成功も失敗も同列で扱う • 複数のエラーパターンを型で表現可能 • PHP 8.0 〜 • どの型が成功か失敗の判断が必要 union型
1. try-catch 2. nullable 3. union型 4. Result 4つの例
/** * @return Result<CompletedPayment, PaymentAmountRuleError> */ function completePayment(ProcessingPayment $payment): Result
{ if ($payment->amount <= 0) { return new Err(new PaymentAmountRuleError("Payment amount must be positive")); } return new Ok(new CompletedPayment($payment->amount)); } // 呼び出し側 $result = completePayment($payment); if ($result->isErr()) { return match (true) { $result->unwrapErr() instanceof PaymentAmountRuleError::class => // ... 支払金エラー時の処理 } } // ... 支払い完了時の処理
/** * @return Result<CompletedPayment, PaymentAmountRuleError> */ function completePayment(ProcessingPayment $payment): Result
{ if ($payment->amount <= 0) { return new Err(new PaymentAmountRuleError("Payment amount must be positive")); } return new Ok(new CompletedPayment($payment->amount)); } // 呼び出し側 $result = completePayment($payment); if ($result->isErr()) { return match (true) { $result->unwrapErr() instanceof PaymentAmountRuleError::class => // ... 支払金エラー時の処理 } } // ... 支払い完了時の処理
関数結果にアクセスする前に、関数が成功したか失敗したかのチェックが必要 • 複数のエラーパターンを型で表現可能 • 成功と失敗が明示的 • PHPStanなどの静的解析がないと辛い Result
PHPでどう実装する? (本日は省略)
zennの記事を見てください🙏 時間の関係で本日は省略します >< https://zenn.dev/higaki/articles/my-php-result-type
使いどころ
使いどころ 🤔 そもそも我々が対処すべきエラーハンドリング • ⭕ビジネス例外 • ❌技術的例外 技術的例外に関しては、アプリケーションのフレームワークに対応を任せることができ、ビジネス例 外に関しては、クライアントにあらかじめ対処するコードを組み込んでおくことができます。 「PHPの例外処理の参考になる資料」
asumikam: プロダクトコードと OSSに学ぶ例外処理の選択肢 — キャッチするのか、投げっぱなしにするのか プログラマが知るべき 97のこと: 21 - 技術的例外とビジネス例外を明確に区別する
使いどころ 😆 ビジネスロジックに取り入れていく • ビジネス例外の対応にResult型を取り入れる ◦ 技術的例外は例外を投げっぱなす • 予期されるエラーに対して効果的な場合は Result型でエラーハンドリングする
• 他の手法の方が適切なシステム・処理は多々ある 「Result型を取り入れない場所の参考になるブログ」 Kentaro Inomata: 鉄道指向プログラミング(の安易な利用)に反対する
• Takuma Kajikawa ◦ try-catchを使わないエラーハンドリング!? PHPでResult型の考え方を取り 入れてみよう • asumikam ◦
プロダクトコードとOSSに学ぶ例外処理の選択肢 — キャッチするのか、投 げっぱなしにするのか • Kentaro Inomata ◦ 鉄道指向プログラミング(の安易な利用)に反対する • プログラマが知るべき97のこと ◦ 21 - 技術的例外とビジネス例外を明確に区別する 参考
自己紹介 ひがき 🍊PHPConference愛媛2026 実行委員長🐘 2026年9月 or 10月 愛媛県松山市 ペチコン愛媛開催予定!! LIKE:筋トレ・ポーカー
旧 新