0

Let's pretend I have a database.php file which contains a persistent access to the database.

<?php
$database = new PDO('mysql:host=xxx', "xxx", "xxx", array(
    PDO::ATTR_PERSISTENT => true
));
?>

Every time I want to query the database within a controller, what should I do?

1/ Use the global keyword to get my global $database variable

<?php

include '../app/config/Database.php';

function getLastOfTheWeek()
{
    global $database;
    $database->query('SELECT * FROM `xxx`');
    ...
}
?>

2/ Include database.php within the function

<?php

function getLastOfTheWeek()
{
    include '../app/config/Database.php';
    $database->query('SELECT * FROM `xxx`');
    ...
}
?>

3/ Give this man some doc, he needs it

Or both are evil anyway, and I should use another method.

Alexsoyes
  • 444
  • 4
  • 12
  • This isn't so much about global versus include, this is about instantiating a new PDO connection instance every time versus re-using the same connection. – Devon Bessemer Oct 23 '17 at 17:27
  • I think you should not mix up your business layer with controller layer. – Tarun Oct 23 '17 at 17:27
  • 1
    Use a DIC https://stackoverflow.com/questions/2255771/how-can-i-use-dependency-injection-in-simple-php-functions-and-should-i-bothe – bassxzero Oct 23 '17 at 17:28
  • @bassxzero the "DIC" in the accepted answer is terrible. It's the opposite of how DI should work. – ishegg Oct 23 '17 at 18:05
  • @ishegg so go answer the question yourself. I'm just pointing him in the right direction. Hopefully he will google around instead of copying and pasting. – bassxzero Oct 23 '17 at 18:06
  • @ishegg, can you explain in details please? – Alexsoyes Oct 23 '17 at 19:10
  • @Dinath Basically, using that "DIC" you lose one of the biggest benefits of DI: explicitly stating each object's dependencies. Having just one dependency that calls the others is just as bad as singletons and globals and "service locators" – ishegg Oct 23 '17 at 19:15
  • Ishegg is right. Here are two very good resources which sustain and explain what he says: [The Clean Code Talks - Don't Look For Things!](https://www.youtube.com/watch?v=RlfLCWKxHJ0) and [James Mallison - Dependency Injection and Dependency Inversion in PHP](https://www.youtube.com/watch?v=Ojsn11XY0X8&feature=youtu.be). –  Oct 24 '17 at 05:26
  • A DIC provides and injects dependencies where they are needed (good). A DIC passed as argument becomes a "service locator" (not good). See the links above for details. –  Oct 24 '17 at 05:30

2 Answers2

2
  1. Global state is bad.
  2. Repeatedly creating DB connections is bad.

Good:

$dbh = new PDO (...);

function doSomething($dbh) {
  $dbh->query(...);
}

OK:

class Something {
  protected $dbh;

  public function __construct($db_config) {
    $this->dbh = new PDO($db_config); // still bad
  }

  public function doSomething() {
    $this->dbh->query();
  }
}

God Tier:

class Something {
  protected $dbh;

  public function __construct(PDO $dbh) {
    $this->dbh = $dbh;
  }

  public function doSomething() {
    $this->dbh->query();
  }
}

$dbh = new PDO(...);
$s = new Something($dbh);
$s->doSomething;

See: http://www.phptherightway.com/#dependency_injection

Sammitch
  • 30,782
  • 7
  • 50
  • 77
  • 1
    A good answer! ;-) Just a note though: the "OK" version I would directly entitle as "BAD" (regarding config array and tight coupling): [The Clean Code Talks - Don't Look For Things!](https://www.youtube.com/watch?v=RlfLCWKxHJ0) and [James Mallison - Dependency Injection and Dependency Inversion in PHP](https://www.youtube.com/watch?v=Ojsn11XY0X8&feature=youtu.be). –  Oct 24 '17 at 05:15
  • Let's pretend I have a basic website, with index.php, home.php, contact.php... All of them needs database connection. We choose the "God Tier" solution, then where the PDO instance will be made? In order to re-use the same databse connection any time? – Alexsoyes Oct 24 '17 at 13:58
  • In the ideal situation you don't have a 1:1 mapping of PHP files and pages. You have an application with a request router (eg: [FastRoute](https://github.com/nikic/FastRoute)) and the application is built from the inside out with DI. – Sammitch Oct 24 '17 at 17:35
  • Do you have an example? – Alexsoyes Oct 26 '17 at 14:02
1

In this simplified example, the global would be better performance assuming you have multiple functions or function calls as the global would re-use the same connection.

However, this does not mean that including Database.php multiple times is always going to be slower. Assuming you have opcache enabled, including the same file multiple times will have very little overhead. The problem is that you are opening a new PDO connection every time you include this file because of how your code is written.

There are a lot of other solutions that do not involve using a global. DI containers are often used to resolve dependencies at the start of an application. The singleton design pattern could also be beneficial if you always want to re-use the same connection.

Devon Bessemer
  • 34,461
  • 9
  • 69
  • 95