Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Saving my PDO connection as a global variable [duplicate]

While asking another questions about PDO queries, I've been told that saving my PDO connection object as global to use it in my various functions that call queries to my database is generally bad practice.

Here is how I generally use my PDO object:

function somefunction(){
    global $pdo;

    $statement = $pdo->prepare("some query");
    $statement->execute();
}

The arguments I've read are more about code maintenance and debugging, where it's hard to trace who modified the PDO object and where in the code it would be. Other people just simply reject using global variables for storing the PDO object, but can't really explain why global variables are a bad approach.

However, for a small-medium projects with only one database, is there really a disadvantage to using a global variable? I usually have my connection script and my functions script separately, where the functions script will require_once() the connection script, where my PDO object is created. In this way, my connection is always established and all modifications to the PDO object are done in my connection script.

Is there any fundamental flaws in using this approach?

like image 753
Prusprus Avatar asked Oct 12 '13 18:10

Prusprus


2 Answers

Is there any fundamental flaws in using this approach?

The very first thing you have to understand, is that $pdo is a part of storage logic. That means, it should be only used inside classes that do abstract data access, be it a SQL table or a collection.

Let's look at your code,

function somefunction(){
    global $pdo;

    $statement = $pdo->prepare("some query");
    $statement->execute();
}

What if you want to switch from MySQL to Mongo/MSSQL/PgSQL, in future? Then you will have to rewrite a lot of code.

And for each database vendor, you will have to create a separated file with different variable. Just like this

function somefunction(){
    global $mongo;
    return $mongo->fetch(...);
}

By using a global state, you end up with mass code duplication, because you cannot pass parameters and thus cannot change function's behavior at runtime.

Now let's look at this,

function somefunction($pdo){
    $statement = $pdo->prepare("some query");
    $statement->execute();
}

Here, $pdo is passed as an argument, thus there's no global state. But the problem still remains, you end up violating the Single-Responsibility Principle

If you really want something that is maintainable, clean and very readable, you'd better stick with DataMappers. Here's an example,

$pdo = new PDO(...);

$mapper = new MySQL_DataMapper($pdo);
$stuff = $mapper->fetchUserById($_SESSION['id'])    

var_dump($stuff); // Array(...)

// The class itself, it should look like this
class MySQL_DataMapper
{
    private $table = 'some_table';

    private $pdo;

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

    public function fetchUserById($id)
    {
        $query = "SELECT * FROM `{$this->table}` WHERE `id` =:id";
        $stmt = $this->pdo->prepare($query);

        $stmt->execute(array(
           ':id' => $id
        ));

        return $stmt->fetch();
    }
}

Conclusion

  • It doesn't really matter if your project is small or large, you should always avoid global state in all it forms (global variables, static classes, Singletons) - For the sake of code maintainability

  • You have to remember, that $pdo is not a part of your business logic. Its a part of storage logic. That means, before you even start doing something with business logic, like heavy computations, you should really abstract table access (including CRUD operations)

  • The bridge that brings together your data access abstraction and computation logic is usually called Service

  • You should always pass the things function's need as parameters

  • You'd better stop worrying about your code and start thinking about abstraction layers.

  • And finally, before you even start doing any stuff, you'd firstly initialize all your services in bootstrap.php and then start querying storage according to user's input ($_POST or $_GET).

Just like,

public function indexAction()
{
    $id = $_POST['id']; // That could be $this->request->getPost('id')
    $result = $this->dataMapper->fetchById($id);

    return print_r($result, true);
}
like image 51
Yang Avatar answered Nov 02 '22 23:11

Yang


For a tiny tiny project it won't hurt much to use global. When the project size starts growing is when things start to get bad.

if your somefunction() had 300 lines in it using 5 global variables, someone looking at your code wouldn't know that the function uses outside variables unless they went through it looking for global variables.

Plus, it's so easy to not use global variables...so why do it

function somefunction( PDO $pdo ){
    $statement = $pdo->prepare("some query");
    $statement->execute();
}

EDIT:

show_profile.php is your controller. Your controller collects all the data for the view and loads the view. This is a very simplified version.

require( 'functions.php' );
$db = new PDO();
$user = get_user( $db, $user_id );
require( 'view.php' );
like image 35
Galen Avatar answered Nov 02 '22 23:11

Galen