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?
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();
}
}
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);
}
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' );
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With