OO Best Practice: Centralizing the Connection
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
Ready for the next problem? Our PDO
object is configurable, but we're still
creating it inside of ShipLoader
. What's going to happen if we add a battle
table and a BattleLoader
? Will it also need to create its own PDO object?
Right now - yea. So if we have 50 tables, that means 50 separate connections.
The horror!
I want one connection that every class uses.
Here's the goal: move the new PDO()
call out of ShipLoader
so that
it can be created in a central location and used by everyone. How? By using
the same strategy we just learned with configuration. If you want to move
something out of a service class, add it as a __construct()
argument and
pass it in.
Adding a $pdo __construct Argument
Let's do it! Instead of passing in the 3 database options, we need to pass
in the whole PDO
object. Replace the 3 arguments with just one: $pdo
.
Give it a type-hint to be great programmers. Next, remove the three configuration
properties. And back in __construct()
, we already have a $pdo
property,
so set that with $this->pdo = $pdo
.
// ... lines 1 - 2 | |
class ShipLoader | |
{ | |
private $pdo; | |
public function __construct(PDO $pdo) | |
{ | |
$this->pdo = $pdo; | |
} | |
// ... lines 11 - 71 | |
} | |
// ... lines 73 - 74 |
Time to simplify the getPDO()
function. We don't need to worry about creating
the object anymore. Instead, just return the property:
// ... lines 1 - 2 | |
class ShipLoader | |
{ | |
// ... lines 5 - 58 | |
private function getPDO() | |
{ | |
return $this->pdo; | |
} | |
// ... lines 63 - 71 | |
} | |
// ... lines 73 - 74 |
Again: big picture: if you need to remove something from a service class -
whether it's configuration or an object - remove it, and add it as an argument
to the __construct()
function.
Creating PDO
But now, we need go to index.php
and change the arguments we're
passing to the new ShipLoader()
. We're not passing these three configuration
pieces anymore. Copy those. Above this, create the PDO
object. $pdo = new PDO()
and paste in the arguments:
// ... lines 1 - 3 | |
$pdo = new PDO( | |
$configuration['db_dsn'], | |
$configuration['db_user'], | |
$configuration['db_pass'] | |
); | |
// ... lines 9 - 126 |
Below, pass $pdo
as the only argument to new ShipLoader()
:
// ... lines 1 - 3 | |
$pdo = new PDO( | |
$configuration['db_dsn'], | |
$configuration['db_user'], | |
$configuration['db_pass'] | |
); | |
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); | |
$shipLoader = new ShipLoader($pdo); | |
// ... lines 12 - 126 |
Ok, let's try it! Still works. Geez - we're unstoppable today.
Unfortunately, this isn't the only place we need this. Copy the $pdo
and
$shipLoader
code and paste it into battle.php
:
// ... lines 1 - 3 | |
$pdo = new PDO( | |
$configuration['db_dsn'], | |
$configuration['db_user'], | |
$configuration['db_pass'] | |
); | |
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); | |
$shipLoader = new ShipLoader($pdo); | |
// ... lines 12 - 114 |
Choose some ships to battle and.... Engage. And that still works too!
The Big Important Takeaway
Ready for the big important takeaway? Don't include configuration or create
new service objects from within a service. Even though the PDO
class comes
from PHP, it is a service class: it does work. If we create that service
object from within a class, we can't easily share it or control it.
Instead, create all of your service objects in one place and then pass them into each other. This stuff is hard - a lot of systems violate the heck out of these rules! And that's ok - I want you to learn to become a great object-oriented developer, so we're looking at the best way to do things.
The downside is that the code to create the service objects is getting a bit complicated. And it's duplicated! Dang it - it's not right yet. Let's fix that next by learning another awesome strategy.
How the new PDO() function will know to connect to database if we removed this ???
Missing i am something ???
$pdo = new PDO($this->dbDns, $this->dbUser, $this->dbPass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);