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
930
例外を投げるのをやめてみないか? あるいは受け入れてみないか? - 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
「Chatwork」Android版アプリを 支える単体テストの現在
okuzawats
0
180
LLM Supervised Fine-tuningの理論と実践
datanalyticslabo
3
890
Symfony Mapper Component
soyuka
2
730
Zoneless Testing
rainerhahnekamp
0
120
アクターシステムに頼らずEvent Sourcingする方法について
j5ik2o
4
160
Semantic Kernelのネイティブプラグインで知識拡張をしてみる
tomokusaba
0
180
わたしの星のままで一番星になる ~ 出産を機にSIerからEC事業会社に転職した話 ~
kimura_m_29
0
180
Keeping it Ruby: Why Your Product Needs a Ruby SDK - RubyWorld 2024
envek
0
180
なまけものオバケたち -PHP 8.4 に入った新機能の紹介-
tanakahisateru
1
120
Refactor your code - refactor yourself
xosofox
1
250
モバイルアプリにおける自動テストの導入戦略
ostk0069
0
110
Webエンジニア主体のモバイルチームの 生産性を高く保つためにやったこと
igreenwood
0
330
Featured
See All Featured
No one is an island. Learnings from fostering a developers community.
thoeni
19
3k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
8
1.2k
Making Projects Easy
brettharned
116
5.9k
Agile that works and the tools we love
rasmusluckow
328
21k
Faster Mobile Websites
deanohume
305
30k
Building a Scalable Design System with Sketch
lauravandoore
460
33k
YesSQL, Process and Tooling at Scale
rocio
169
14k
Practical Orchestrator
shlominoach
186
10k
Building Adaptive Systems
keathley
38
2.3k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
Building Your Own Lightsaber
phodgson
103
6.1k
Code Reviewing Like a Champion
maltzj
520
39k
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ʯ => ఘ؍ظ