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
例外を投げるのをやめてみないか? あるいは受け入れてみないか? - How to use ex...
Search
uzulla
January 13, 2024
Programming
5
1.2k
例外を投げるのをやめてみないか? あるいは受け入れてみないか? - How to use exceptions other than throwing
at: PHPカンファレンス北海道 2024
date: 2024-01-13
talker: uzulla
uzulla
January 13, 2024
Tweet
Share
More Decks by uzulla
See All by uzulla
バイブスあるコーディングで ~PHP~ 便利ツールをつくるプラクティス
uzulla
1
340
PHPer's Guide to Daemon Crafting Taming and Summoning
uzulla
2
1.6k
似たもの同士のPerlとPHP
uzulla
1
240
More Context, Better Code. 既存コードやOAS等をコンテキストとしてLLMに与える事で、よりよいコード生成を行う話
uzulla
1
170
あなたのアプリ、ログはでてますか?あるいはログをだしてますか? (Funabashi.dev用 軽量版)
uzulla
3
270
セッションのトークセッション / Traps for PHP session features in growing web apps
uzulla
2
180
Crafting a Own PHP - ウキウキ手作りミニマリストPHP
uzulla
5
2.6k
PHPerが ISUCONでやるべき事
uzulla
1
1.4k
開発生産性は上がらない - N Ways to Reduce Development Productivity
uzulla
1
310
Other Decks in Programming
See All in Programming
AWS Serverless Application Model入門_20250708
smatsuzaki
0
130
AIエージェント開発、DevOps and LLMOps
ymd65536
1
350
SOCI Index Manifest v2が出たので調べてみた / Introduction to SOCI Index Manifest v2
tkikuc
1
110
AI時代のドメイン駆動設計-DDD実践におけるAI活用のあり方 / ddd-in-ai-era
minodriven
23
9k
decksh - a little language for decks
ajstarks
4
21k
ゲームの物理
fadis
5
1.5k
GitHub Copilotの全体像と活用のヒント AI駆動開発の最初の一歩
74th
8
3.2k
Flutterと Vibe Coding で個人開発!
hyshu
1
270
A Gopher's Guide to Vibe Coding
danicat
0
170
自作OSでDOOMを動かしてみた
zakki0925224
1
1.4k
ソフトウェアテスト徹底指南書の紹介
goyoki
1
110
AHC051解法紹介
eijirou
0
620
Featured
See All Featured
4 Signs Your Business is Dying
shpigford
184
22k
Automating Front-end Workflow
addyosmani
1370
200k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
8
900
Raft: Consensus for Rubyists
vanstee
140
7.1k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
36
2.5k
How GitHub (no longer) Works
holman
315
140k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
229
22k
Designing for Performance
lara
610
69k
Building Applications with DynamoDB
mza
96
6.6k
Six Lessons from altMBA
skipperchong
28
4k
Done Done
chrislema
185
16k
Speed Design
sergeychernyshev
32
1.1k
Transcript
ྫ֎Λ͛ΔͷΛΊͯΈͳ͍͔ʁ ͋Δ͍ड͚ೖΕͯΈͳ͍͔ʁ — PHP Conference hokkaido 2024 — uzulla
ࣗݾհ — id: uzulla — ৭ʑͰੜܭΛཱ͍ͯͯ·͢ — PHPͰΦϨΦϨFWΛ࡞ͬͨΓɺ ͬͨΓͯ͠·͢ —
ͭ·Γ अಓͳPHP Λॻ͍͍ͯ· ͢(ʁʁʁ) — ʁʮԦಓͱʁʁʁʯ ࢲʮब৬ͰཱͭΑ͏ͳ…ʯ
DISCLAIMER — अಓͳਓؒͷτʔΫͰ͢(2) — ࢀߟʹ͢Δͱ͖ʹɺνʔϜઌഐͱ૬ஊ͠·͠ΐ͏ — ݹདྷΑΓʮྫ֎੍ޚߏʹ͔ͭͬͯͳΒͳ͍ʯ http://somabo.de/talks/200705_chicago_spl_update.pdf 101pࢀর —
ͳͷͰ अಓͰ͢(3ճ) — ղΒͣʹ͔ͭ͏ͷʮ৮Δͳةݥɺ͚ͲҙʯͰ͢ — ͋Δ͍ʮղΔ͕ԶΒͳ͍ʯʹͳΔͣͰ͢
(৺ͷɺ͋Δ͍ಠࣗղऍɺ͘͠ݴ͍༁) ʮ͔ͤͯɺѱ༻ෆՄthrowtry/catchογϣʁ ɹGOTOېࢭΈ͍ͨͳΜογϣʁ ɹException objectͷऔΓѻ͍ࣗ༝ογϣʁʯ
15͔͕࣌ؒ͠ͳ͍ͷͰ ଈअಓ ʂ — PHPͷExceptionɺnewͨ͠ΠϯελϯεͰ͢ɻ — ͭ·ΓɺValueͳͷͰ — returnͰ͖Δ͠ —
ҾʹͰ͖Δ͠ — ྻʹ٧ΊΔ͜ͱͰ͖·͢ — ʮ͜Εศརʹ ѱ༻ ׆༻Ͱ͖ΔΑφʂʂʂʯ
ʮྫ֎Λ֦ு͠ɺೖ͢Δϋφ γʯ
<?php // ҰԠɺී௨ͷಠࣗྫ֎͜Μͳܗঢ় class SomeException extends RuntimeException { public function
__construct( string $message, int $code = 0, Throwable $previous = null, ) { parent::__construct($message, $code, $previous); } }
<?php declare(strict_types=1); // ෳͷྫ֎Λॴ༗Ͱ͖Δྫ֎ class UserEditException extends RuntimeException { public
function __construct( string $message, int $code = 0, Throwable $previous = null, public array $exceptions = [] ) { parent::__construct($message, $code, $previous); } }
<?php declare(strict_types=1); class InvalidEmailException extends RuntimeException { }
<?php declare(strict_types=1); $exceptions = []; if (filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) { $exceptions[]
= new InvalidEmailException('Invalid email address'); } if (strlen($_POST['password']) <= 8) { $exceptions[] = new InvalidPasswordException( "too short", InvalidPasswordException::SHORT ); // ͜ΕޙͰઆ໌͠·͢ } if (preg_match("/\n/u",$_POST['password'])) { $exceptions[] = new InvalidPasswordException( "lf not allowed", InvalidPasswordException::AVOID_LF ); // ͜ΕޙͰઆ໌͠·͢ } if (count($exceptions) > 0) { throw new UserEditException('Invalid input', 0, null, $exceptions); }
ʮ…͜Εɺͳʹ͕͏Ε͍͠ͷʁʯ — ྫ֎ͬͯɺجຊҰ͔ͭ͛͠ΒΕͳ͍ΜͰ͢Α(ॏཁ) — try/catchͱthrowɺGOTOΈ͍ͨͳͷͳͷͰ — ݕূͱ͔ɺࢁͷྫ֎͕͋Γ͏Δ͡Όͳ͍Ͱ͔͢ʁ ·ͱΊͯऔΓѻ͑Δͱศར͡Όͳ͍Ͱ͔͢ʁ — ͳͷͰɺྫ֎ΛྻͰ࣋ͯΔྫ֎͕͋Δͱศར͔ͳͬͯ…
(࣮ࡍศར)
## Controllerͱ͔Ͱ function run(array $post){ try{ $exceptions = []; //
͖ͬ͞ͷίʔυͱಉ͡ͳͷͰলུ if (count($exceptions) > 0) { throw new UserEditException('Invalid input', 0, null, $exceptions); } return render_success_page(); }catch (UserEditException $e){ return render_error_page($e->exceptions); } }
ͱ͜ΖͰಠࣗྫ֎ͬͯศརͰ͢Ͷ — ಠࣗྫ֎(Ϋϥε)ͳΒinstanceofͰʮͦΕ͕Ͳͷྫ֎ͳͷ ͔ʯΛؒҧ͍ͳ͘ఆͰ͖ΔΜͰ͢Α — (ॻ͘ʹͯ͠ɺϦϑΝΫλϦϯάͰফ͢ͱͯ͠) ܕͱ੩తղੳͰ͍͖͍ͬͯͨ͡Όͳ͍Ͱ͔͢ʁ — ʮશ෦Exceptionͱ͔RuntimeExceptionʹͯ͠ɺ ɹgetMessageΛจࣈྻϚονͰذʯͱ͔ΊΑ͏
// ྫ֎ͷྻ͔Βɺࢦఆͷྫ֎͚ͩΛൈ͖ग़͢܅ function get_list_contain_exception(array $exceptions, string $exception_name): array { return
array_reduce( $exceptions, function($carry, $e){ if($e instanceof $exception_name) $carry[] = $e; }, [] ): array; } <?php $password_exceptions = get_list_contain_exception($all_exceptions, InvalidPasswordException::class) ςϯϓϨʔτͷύεϫʔυೖྗཝͱ͔Ͱ… <?php if (count($password_exceptions)>0){ ?> <?php foreach($exceptions as $e){ ?> <div class="error"><?=$e->getMessage()?></div> <?php } ?> <?php } ?>
ࢲʮྫ֎Λͱͯ͠͏ͷศརʂʂʂʯ — օ͞Μʮ…ʁʁʁʁʁʯ — ͍͖͍͚͓ͭͯͯͨͩͯΓ·͢Ͱ͠ΐ͏͔… — ෆ໌ɺ࿓ԼͰ࣭͍ͯͩ͘͠͞ɻ — (ཁ͋ΕɺYouTubeͳͲͰ࠶ԋ͠·͢…)
ͬͱྫ֎Λ֦ுɾ׆༻ɾ ѱ༻ ͍ͨ͠ʂʂʂ — (ࢲʮ͞Βʹअಓʹͯ͠ɺօ͞ΜΛ͓͖͟Γʹ͍ͯ͘͠ʯ) — ྫ֎σόοάͱ͔ௐࠪʹ͏͔Β(ී௨)දࣔ༻ʹ͑ͳ ͍… Ͱɺදࣔ༻ͷจষͱ͔ͬ͠Γඥ͚͍ͨɻ —
͞Βʹ͍͑ɺଟࠃޠରԠͱ͔͍ͨ͠ɻ — ʁʮಠࣗྫ֎Λࢁͭ͘Δͷ͕େม͗͢ΔΜͰ͕͢ʯ ࢲʮCodeͬͯͷ͕͋ΔͷͰɺͦΕ͑Δʯ ʁʮCodeͬͯͳʹʁʯࢲʮ͋͞…ʁʯ
ྫ֎ʹػೳࡌͤͪΌ͏ϋφγ
<?php declare(strict_types=1); // Ұͭͷྫ֎ͰɺෳͷΤϥʔΛͪͭͭɺI18Nͳϝοηʔδͭྫ֎ class InvalidPasswordException extends RuntimeException { use
I18NMessageTrait; // ޙड़ const int SHORT = 1; const int AVOID_LF = 2; // ͜͜ΛENUMʹ͢Δͷѱखͱ͓͍·͢ const array MESSAGES = [ ExceptionLang::JA->value => [ self::SHORT => "͍Ͱ͢Ͷʙʙ", self::AVOID_LF => "վߦແཧʂ", ], ExceptionLang::EN->value => [ self::SHORT => "Too Short", self::AVOID_LF => "LF is not allowed", ], ]; }
trait I18NMessageTrait // ͖ͬ͞use͍ͯͨ͠ͷ { public function getI18NMessage(ExceptionLang $lang) {
return self::MESSAGES[$lang->value][$this->code] ?? throw new \OutOfBoundException( "Undefined message." . self::class ." code:{$this->code}" ); } } // -- enum ExceptionLang: string { case JA = 'ja'; // ผʹENUMʹ͠ͳͯ͘ɺจࣈྻͷjaͰΑ͍ͷͰʁʁʁ case EN = 'en'; }
# όϦσʔγϣϯՕॴͰ… $e = new InvalidPasswordException( "ྫ֎ϝοηʔδΛϢʔβʔʹදࣔ͢ΔͷΞϯνύλʔϯ ͜͜Ϣʔβʔʹදࣔ͠ͳ͍ͷͰɺσόοάใ͍ΕͯΑ͍", InvalidPasswordException::SHORT );
# ςϯϓϨʔτͱ͔Ͱ… echo $e->getI18NMessage(ExceptionLang::JA); // => "͍Ͱ͢Ͷʙʙ"
ศརʂʂʂ — ϝοηʔδͱ͔ΛPOJSONͰ࣋ͭΑΓɺ ίʔυʹೖΕΕόϥόϥʹͳΒͣʹࡁΉʂ — ੩తղੳͰʮΘΕ͍ͯͳ͍ΤϥʔϝοηʔδʯΛ ಛఆͰ͖·͢ — ͍ͭࢦఆ͠ͳ͍ɺྫ֎ͷ Code
Λ׆༻͢Ε ಠࣗྫ֎ͷΛͪΐͬͱݮΒͤ·͢
͜͏͍͏ΦϨΦϨͳ͜ͱΛ͢Δͱ… — ʁʮ͍…ීஈݟͳ͍ελΠϧʹੜཧతݏѱײ͕…ʯ — ࢲʮΦϨΦϨͷҰछ͔ͩΒͶ…ʯ — (ଟ)͜ͷίʔυ10ੜ͖Δࣄ͕Ͱ͖Δʂʂʂ (͕͜͜ݸਓతʹॏཁ) — ࢲɺศརϥΠϒϥϦʹͨΑΒͣɺPOPOͰද͍ͨ͠ɺ
͜Ε͘Β͍ͷදݶศརϥΠϒϥϦʹཔΒͣͰ͖Δ
ʮ͜Εɺྫ֎Ͱ͋Δඞཁ͕͋Δͷ͔ʁʯ — ʁʮUserEditExceptionͱ͔͘ɺதExceptionͰͳ ͍΄͏͕Α͍ͷͰʁ͜Εཞ༻Ͱʁʯ ࢲʮΫϥεͳΜ͔ͩΒศརϝιουੜͯ͑͑͠Ζʯ — ʮExceptionExceptionͳͷͰɺؒҧ͑Α͏͕ͳ͍ʯͱ͍ ͏ϝϦοτ(ओ؍)͕͋Δ — ͛ͳ͍ྫ֎ʹҧײ͋ΔͰ͠ΐ͏͕ɺมͱͯ͠औΓ
ճͯ͠ɺେ࠷ޙTypeErrorͰམͪΔͷͰ݁ߏ҆શ (࣍ϖʔδଓ͘)
ྫ֎ΛҰ͛ͳ͍ϋφγ
class UserEntity { public function __construct( public int $id, public
string $name, public string $email, public string $password ) { } }
# ྫ֎Λฦʹ͏ѱ༻ʁྫ function getUserFromDB(int $id): UserEntity|null|\RuntimeException { try { $pdo
= new PDO('mysql:host=localhost;dbname=test', 'root', ''); $stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id'); $stmt->execute(['id' => $id]); if(($res = $stmt->fetch(PDO::FETCH_ASSOC)) === false) return null; return new UserEntity(...$res); } catch (\Exception $e) { return \RuntimeException('ͳΜ͔DBͰΤϥʔ͕͓ͬͨ͜Θʙʙ', 0, $e); } } // --- $user = getUserFromDB(1); if (is_null($user)) { return show_notfound(); } elseif ($user instanceof \RuntimeException) { return show_internal_server_error($user/*== Exception*/); } return show_user_detail($user);
ϫʔοʂʂʂ — ͻͲ͍ίʔυͩͱ͓͍·͔͢ʁ => ͍ɻ — ͨͩɺࢁͷTry/CatchΑΓಡΈ͍͢(ओ؍) (͜Ε͙Β͍͍ͱಡΔ͕ɺtry͕͔ͬͨΓɺࢁtry/ catch͕͋ΔͱࡶͳPokemon HandlingʹͳΓ͕ͪ)
— (͜ͷྫͩͱ)show_user_detail ͰҾ͕ UserEntity Ͱ͋Δ ͱ໌هͯ͋͠ΕTypeErrorͰམͪΔͷͰɺ ઌʹਐΉ͜ͱͳ͍ͷͰͪΐͬͱ҆શ
# ී௨ͱअಓͷൺֱྫ ## ී௨ͷTry/Catch try{ $user = getUserFromDB(1); if (is_null($user))
show_notfound(); return show_user_detail($user); # ͜͜ΒΜ͕ΊʔͬͪΌͳͳ͕͍͜ͱ͕ଟ͍ }catch(SomeException $e){ return show_internal_server_error($e->getMessage()); # ࢁCatch͕͋ͬͨΓ… }catch(\RuntimeException $e){ return show_internal_server_error($e->getMessage()); # ͷͰɺ͕͍͜͜͢͝ԕ͍ } ## ઌ΄ͲͷअಓྫɺૣظReturnͬΆ͍Ͷʁ $user = getUserFromDB(1); if (is_null($user)) { return show_notfound(); } elseif ($user instanceof \RuntimeException) { return show_internal_server_error($user); } return show_user_detail($user);
ͬͺΓExceptionͰͳͯ͘Α͍ͷͰʁ — ͍ɻ — ͔͠͠ʮແ͍ʯʮ͋ΔʯʮΤϥʔʯผͷදݱʹ͍ͨ͠ — User,null,falseΈ͍ͨͳͷ֮͑Δͷ͕େม — ʮfalse͕ΤϥʔͰͳ͍έʔε͋Δʯ —
Exceptionɺ͔͋Β͞·ʹҟ࣭ͳͷͰɺΘ͔Γ͍͢ — ࠷ѱɺͳ͛Ε্Ґ͕Ωϟονͯ͘͠ΕΔ
·ͱΊ — Exception Λ͙͢ʹࣺ͛ͯͣɺड͚ೖΕΔɺ ͦΜͳअಓͰ͔ͭ͏ͱศརͳࣄ͋Δ — ʁʮ͜ΜͳͷҟৗʯࢲʮͦΜͳ͜ͱͳ͍Αʂʯ ʁʮࢀߟࢿྉʹ͔͍ͯ͋ͬͨʯࢲʮ͔ͨ͠ʹ…ʯ — ͢Δͱ৭ʑग़དྷָ͍ͯ͠Ͱ͢ΑͶɺ
ʮ◦◦ͷڭ͑ʹͳ͍ʂʯͱ҆қʹ ٫Լ͠ͳ͍ͱ͍͍ͱࢥ͍·͢ɻ — ͳͥͳΒɺੈքมΘΔ͔ΒͰ͢(ਓͷܦݧ)
͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ — ࣭ٙԠλΠϜ — ͋Δ͍ɺ͔͜͜Β͓·͚
໌͔Β͑Δখωλ — ʮྫ֎ʹۭimplementsΛ͔ͭ͏ͱศརʂʂʯ — ಠࣗྫ֎ʹಛఆͷimplementsΛ͚ͭΔͱɺʮϚʔΫʯ͕ͭ ͚ΒΕΔ — ʮ͜ͷϚʔΫ͕͋ΔͳΒɺϩάʹͩ͢ʯͱ͔ɺʮίϨϚ δக໋తʯͱ͔͕৭ʑΓ͍͢ —
ϦϑΝΫλϦϯάͷͱ͖ʹྫ֎Λ͚ସ͑Δͱ͔ةͳ͍͜ ͱΛ͠ͳͯ͘ྑ͍ — traitΈ͍ͨͳͷ(ॾઆ͋Γ·͢)
// ϚʔΧʔɺதۭͰΑ͍ interface MustLogging{} // ಠࣗྫ֎ class MyException extends RuntimeException
implements MustLogging{} // ྫ֎ॲཧͷͱ͖ɺΠϯϓϦ͞Ε͍ͯΔ͔ΛݟͯॲཧΛม͑Δ catch(Exception $e){ if($e instanceof MustLogging) error_log($e->getMessage()); } MustLogging ͷ͚֎҆͠શʹͰ͖Δʂ ͨͩ݁ߏنײ͋ΓɺଞਓʹಡΈͮΒ͍͔ (FWͬͯͦ͏͍͏ͷͰʁ)
## ׆༻࣮ྫ(ʁ) interface BailoutWhenBatchTag{ } // όονͷ߹ඞͣఀࢭ͢ΔϚʔΫ interface IgnoreOnProductionTag{ }
// ຊ൪ͩͱແࢹ͢ΔϚʔΫ interface InternalServerErrorTag{ } // 500ʹ͍ͨ͠ϚʔΫɺBadRequestͱ͔͋Δ
ਖ਼͍͠ྫ֎(ʁ)Λֶͼ͍ͨͳΒ — ͍͔ͭ͘ࢿྉͷϦϯΫ — (ࣗͷݴ༿Ͱ৭ʑॻ͜͏ͱ͓͚ͬͨͲɺͲ͏ͤԶͷݴ ͏͜ͱͳΜͯΈΜͳ৴༻ͤΜΖ͔ΒͳʂΨϋϋʂʂ)
ͱΓ͋͑ͣɺkoriym͞Μͷهࣄ — ΤΩαΠτ Advent Calendar 2016 15ʮPHPͷྫ֎ʯ — https://qiita.com/koriym/items/17cfd1bbbaead1a2e5a9
࣍ʹt-wada͞Μͷൃද — PHP7 Ͱݎ࿚ͳίʔυΛॻ͘ - ྫ֎ॲཧɺද໌ϓϩάϥϛ ϯάɺܖʹΑΔઃܭ / PHP Conference
2016 — https://speakerdeck.com/twada/php-conference-2016 — ྫ֎ઃܭʹ͓͚Δେࡑ — https://www.slideshare.net/t_wada/exception-design- by-contract
ಠࣗྫ֎ͷઃܭྫ — PHPʹ͓͚Δಠࣗྫ֎ઃܭΛߟ͑Δ - hgsgtk͞Μ — https://speakerdeck.com/hgsgtk/a-way-to-design- user-defined-exception-with-php — (SymfonyελΠϧͷྫղઆͰ໘ന͍Ͱ͢Ͷ)
— Laravel ϚχϡΞϧ — https://laravel.com/docs/10.x/errors — ݁ߏྫ֎Λ׆༻͍ͯ͠Δ — ΠϕϯτόϒϦϯάΈ͍ͨʹɺͰ͖Δ͚ͩྫ֎Laravel(֎ ଆ)ʹͤΔελΠϧ
— ϚʔΫΛ͚Δ͜ͱͰɺLaravelଆ͕Α͠ͳʹ͢ΔͳͲ͋Δ — ͚Ͳɺʮศརͳن͕͔ͳΓଟ͍ʯͷͰ֮͑Δͷগʑ େม
ͦͦʮྫ֎Ͱͳ͚ΕͳΒͳ͍ͷ͔ʁʯ — https://go.dev/doc/faq#exceptions — ҙ༁ʮྫ֎ॲཧ͕هड़Ͱ͖Δʹ༧Մೳ ͳͷʹʰྫ֎ʱͳͷʁifͰॻ͚ͳ͍ʁʯ => (͔ͨ͠ʹฦͰఆϛεΓ͍͢ɺΕͨΓɺΤ ϥʔͱ͕ಉҰࢹ͞ΕͨΓ(goଟΛ͔ͭͬͨ —
LaravelFormͱɺMessageBag
ͱ͍͑ɺྫ֎ศར — Τϥʔ࣌ʹɺΤϥʔॲཧҰؾʹδϟϯϓͰ͖Δ — ≒ʮਖ਼ৗ࣌ແࢹ͢Δίʔυʯָ͕ʹॻ͚Δɺ ͨͱ͑ΤϥʔϩάɺDBૢ࡞࣌ͷϩʔϧόοΫɺ ͖Ε͍ͳΤϥʔը໘ — (ݸਓతʹʮ(ճ෮Մೳͳ)ΤϥʔॲཧʯΛॻͨ͘Ίͷ ͷ͡Όͳ͍ͱࢥͬͯΔ)
— (ͷͰɺಡΈ͘͢͢ΔͨΊʹ͏͖Ͱ͋Γɺ ʰݎ࿚ʱʹ͍ͨ͠ͳΒɺී௨ʹifͰஸೡʹॻ͍ͯ΄͍͠)
͔͠͠ɺ(ࢥ͏ʹ)͏·͘͏ͷΉ͔͍ͣ͠ — tryͱcatch(ܕ)ͷΈ߹ΘͤΤϥʔॲཧΛॻ͚Δ͕… — ʮ໘Ͱશ෦(Runtime)Exceptionʯ — ʮແݶ૿Ճ͢Δಠࣗྫ֎ʯ(ෳࡶԽ) — try͔Βԕ͗ͯ͢ɺͲ͜Ͱcatch͞ΕΔ͔ಡΈͮΒ͍ —
ྫ֎ॲཧͰ͖Δ͚ͩগͳ͍΄͏͕Α͍ — catch͕ࢁ͋ͬͨΒҙ͕ඞཁ — (օ͕௨Δ ʮ͔͠ʯ Ͱ͋Δ)
͍Ͳ͜Ζ — ೖྗɾҾݕূ — (DBϑΝΠϧͳͲ)ετϨʔδૢ࡞ — ֎෦௨৴ॲཧ — ͜ΕΒҎ֎Ͱtry/catch͔ͭ͏ࣄ͋Μ·Γͳ͘ͳ͍͔ʁ —
(ͦͯ͠ɺ͜ΕΒʮ͖Ε͍ͳΤϥʔΛग़͢Ҏ֎Ͳ͏͠Α͏ ͳ͍ʯͬ͠ΐʁ͍͍ͤͥϦτϥΠʁ)
PDOExceptionΛྫʹͨ͠ɺඍস·͍͠ਓؒͷྫ — ʮͳΜ͔ɺઌഐAI͕͜͏ॻ͚͍ͬͯͬͨͷͰॻ͍ͨʯ => \Exception͔͔ͭ͠Θͳ͍ظ — ʮDBॲཧ͕ݪҼͱղͬͯศརʂʯ => ྫ֎ΛΓ͡Ίͯສೳײظ —
ʮʁDBॲཧͷͲ͜ͰࢮΜ͔ͩΘ͔ΒΜ͕ʁม͢Μͧʯ => ಠࣗྫ֎Ͱͩ͜ΘΓຍظ — ʮϩʔϧόοΫͰ͖Ε͍͍ΘɺҰԠϩάͯ͠re-throwʯ => ఘ؍ظ