If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
Catching an exception is really powerful. But you can get even fancier.
For right now, var_dump()
the Exception
object:
... lines 1 - 8 | |
class ShipLoader | |
{ | |
... lines 11 - 60 | |
private function queryForShips() | |
{ | |
try { | |
... line 64 | |
} catch (\Exception $e) { | |
var_dump($e); | |
... lines 67 - 69 | |
} | |
} | |
} | |
Ok, this object is actually a PDOException
. Two Important things: all exceptions
are objects, and all exception classes ultimately extend PHP's base Exception
class.
So if you could look at the source code for PDOException
, you'd see that it
extends Exception
:
And this ends up giving us a lot more flexibility when working with exceptions.
Why? Remember, we're pretending that - for some reason - we occasionally have some
database problems that cause a PDOException
to be thrown. When that happens, we
want to recover and just show zero ships. And we've got that.
But what if something else goes wrong inside fetchAllShipsData()
that has nothing
to do with talking to the database. Well, that would be truly unexpected, and in
those cases, I want to let the exception be thrown like normal so we can see it
while we're developing.
So here's the question: how can we catch PDOException
objects, but not any others?
By changing the catch to \PDOException
:
... lines 1 - 8 | |
class ShipLoader | |
{ | |
... lines 11 - 60 | |
private function queryForShips() | |
{ | |
try { | |
... line 64 | |
} catch (\PDOException $e) { | |
trigger_error('Database Exception! '.$e->getMessage()); | |
... lines 67 - 68 | |
} | |
} | |
} | |
I'll also change the message to "Database Exception".
Refresh! Cool: it still catches that exception. But check this out: go back into
PdoShipStorage
and - before the query - throw a different exception: there's one
called InvalidArgumentException
:
... lines 1 - 4 | |
class PdoShipStorage implements ShipStorageInterface | |
{ | |
... lines 7 - 13 | |
public function fetchAllShipsData() | |
{ | |
throw new \InvalidArgumentException('something else went wrong!'); | |
... lines 17 - 20 | |
} | |
... lines 22 - 34 | |
} |
There's nothing special about this class: PHP has several built-in exceptions, and you can use whatever one feels right for your scenario.
But, it should not be caught by our try-catch. Try it out.
Yes! It totally kills the page.
Exceptions are something that you'll get used to leveraging as you develop more. But here's the key takeaway: when things go wrong, throw an exception.
Oftentimes, I see people try to not throw exceptions. Instead, they try to recover in some way. Don't do that. I would rather throw an exception, see the error in my error log and fix it than try to render a broken page and never realize that there's a bug in my code.
In fact, most frameworks have a pretty easy way to automatically notify you - like via Slack or by email - whenever an exception is thrown on your site.
Let's fix our code: take out the throw new exception and change the table back to
ship
. All better.
Hey Marc R.
Yes, you're right it doesn't tell you to print that message but it already comes with the initial code so we thought it would be intuitive, but maybe not? We're sorry for the confusion.
You forgot to specify that we had to print "Planet cannot be rendered" in the InvalidRadiusException catch for the 2nd challenge.