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 exceptions other than throwing
Search
uzulla
January 13, 2024
Programming
4
700
例外を投げるのをやめてみないか? あるいは受け入れてみないか? - 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
セッションのトークセッション / Traps for PHP session features in growing web apps
uzulla
2
65
Crafting a Own PHP - ウキウキ手作りミニマリストPHP
uzulla
5
1.6k
PHPerが ISUCONでやるべき事
uzulla
1
510
開発生産性は上がらない - N Ways to Reduce Development Productivity
uzulla
1
150
test is not a job
uzulla
1
430
あなたのPHPアプリ、ログはでてますか?あるいはログをだしてますか? / Are you writing a log? Or just out a log?
uzulla
16
6.8k
有名FWを採用する?しない? 令和5年におけるオレオレフレームの立ち位置 / To make with own framework or not do, that is the question
uzulla
2
970
May the PHP dev be with xdebug
uzulla
0
130
PHPの最高機能、配列を捨てよう!! / Throw away all PHP array now!!!
uzulla
12
13k
Other Decks in Programming
See All in Programming
Mastering Developer Experience: A Roadmap for Success 【開発生産性Conference 2024】
findyinc
1
380
CSC307 Lecture 14
javiergs
PRO
0
220
CSC307 Lecture 09
javiergs
PRO
1
500
Async Await: Mastering Python's Time-Bending Tricks - EuroPython2024
yanbo
1
290
Exploring the Gradually Lost Technical Skills in the Cloud Native Era
hwchiu
2
3.9k
日付と正規化
megmogmog1965
0
140
ぼっちを避けて楽しむためのアノテコノテ / Various Tips and Tricks to Avoid Loneliness and Have Fun
nrslib
3
1.7k
スクラムマスターって孤独じゃないですか?
yoshitaroyoyo
1
140
DMMプラットフォームにおけるTiDBの導入から運用まで
pospome
7
3k
Microservices rules (July 2024) : what good looks like
cer
PRO
0
1.6k
【Go言語】golangci-lintの使い方
tomo1227
0
270
AWSでゲームサーバーを運用! Amazon GameLiftのお話
iriikeita
0
200
Featured
See All Featured
Optimizing for Happiness
mojombo
373
69k
Fontdeck: Realign not Redesign
paulrobertlloyd
79
5.1k
The Invisible Customer
myddelton
117
13k
Optimising Largest Contentful Paint
csswizardry
18
2.6k
The Pragmatic Product Professional
lauravandoore
29
6.1k
Raft: Consensus for Rubyists
vanstee
134
6.5k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
17
8.7k
4 Signs Your Business is Dying
shpigford
178
21k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
18
1.2k
Web development in the modern age
philhawksworth
203
10k
Designing for Performance
lara
604
67k
Building Effective Engineering Teams - LeadDev
addyosmani
47
2.2k
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ʯ => ఘ؍ظ