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
4
940
例外を投げるのをやめてみないか? あるいは受け入れてみないか? - 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
似たもの同士のPerlとPHP
uzulla
1
130
More Context, Better Code. 既存コードやOAS等をコンテキストとしてLLMに与える事で、よりよいコード生成を行う話
uzulla
1
110
あなたのアプリ、ログはでてますか?あるいはログをだしてますか? (Funabashi.dev用 軽量版)
uzulla
3
180
セッションのトークセッション / Traps for PHP session features in growing web apps
uzulla
2
120
Crafting a Own PHP - ウキウキ手作りミニマリストPHP
uzulla
5
2k
PHPerが ISUCONでやるべき事
uzulla
1
1k
開発生産性は上がらない - N Ways to Reduce Development Productivity
uzulla
1
240
test is not a job
uzulla
1
500
あなたのPHPアプリ、ログはでてますか?あるいはログをだしてますか? / Are you writing a log? Or just out a log?
uzulla
17
7.6k
Other Decks in Programming
See All in Programming
Mermaid x AST x 生成AI = コードとドキュメントの完全同期への道
shibuyamizuho
0
160
rails stats で紐解く ANDPAD のイマを支える技術たち
andpad
1
290
Amazon S3 NYJavaSIG 2024-12-12
sullis
0
100
Recoilを剥がしている話
kirik
5
6.7k
StarlingMonkeyを触ってみた話 - 2024冬
syumai
3
270
The Efficiency Paradox and How to Save Yourself and the World
hollycummins
1
440
競技プログラミングへのお誘い@阪大BOOSTセミナー
kotamanegi
0
360
Jakarta EE meets AI
ivargrimstad
0
240
責務を分離するための例外設計 - PHPカンファレンス 2024
kajitack
2
680
CQRS+ES の力を使って効果を感じる / Feel the effects of using the power of CQRS+ES
seike460
PRO
0
130
Webエンジニア主体のモバイルチームの 生産性を高く保つためにやったこと
igreenwood
0
330
103 Early Hints
sugi_0000
1
230
Featured
See All Featured
A Modern Web Designer's Workflow
chriscoyier
693
190k
Building Your Own Lightsaber
phodgson
103
6.1k
Being A Developer After 40
akosma
87
590k
How STYLIGHT went responsive
nonsquared
95
5.2k
The Art of Programming - Codeland 2020
erikaheidi
53
13k
Designing for humans not robots
tammielis
250
25k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
28
900
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
Fashionably flexible responsive web design (full day workshop)
malarkey
405
66k
A Philosophy of Restraint
colly
203
16k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
The Pragmatic Product Professional
lauravandoore
32
6.3k
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ʯ => ఘ؍ظ