There are two possibilities to solve this problem, one of them being less appropriate from the point of view of Object Orientation but perhaps more usable for your particular case.
The properties of a class serve to store all that the class, Upon its object, may need during the Request in which it was instantiated.
If you have several methods that act as Wrappers for the repetitive part of the PDO and they all use the same object, instead of opening a connection for each method, you store the PDO instance in a class, thus:
class Site {
private $conn;
public function __construct($driver, $host, $dbname, $user, $pass) {
$this -> conn = new PDO( /** ... */ );
}
public function jazz() {
return $this -> conn -> query( /** ... */ );
}
}
The second alternative is a little more complex, but much more timely from the point of view of Object Orientation because, in the ideal scenario, you should not restrict access to your data to just one database, let alone force the use of PDO.
In such cases, using a Design Pattern called Registry you have an Object-Oriented implementation of basically a large box, where you can save whatever you want to use later:
class Registry {
private $registry = array();
/**
* Add/Set a Registry Entry value
*
* @param string $key
* Registry Key
*
* @param mixed $value
* Value to be stored
*
* @return Registry
* Registry Object (Fluent Interface)
*/
public function set( $key, $value ) {
$key = trim( $key );
if( ! empty( $key ) ) {
$this -> registry[ $key ] = $value;
}
return $this;
}
/**
* Get a Registry Entry value
*
* @param string $key
* Registry Key
*
* @return mixed
* Registry Entry
*/
public function get( $key ) {
$key = trim( $key );
return ( array_key_exists( $key, $this -> registry ) ? $this -> registry[ $key ] : FALSE );
}
}
However, alone, Registry does not solve the problem of the object’s state, which is precisely what concerns its problem.
Without solving this problem, you would see yourself:
- Duplicating code, as it should currently be doing
- Create a global variable and access it in the local scope of the methods used the keyword global or the superglobal array $GLOBALS, which is extremely wrong
To solve this "problem" of Registry, since it is not exactly a problem it does not solve that was not designed to solve, just integrate it to another Design Pattern, the Singleton.
Singleton is a pattern that aims to make the instance of a single object. No matter where in the code you invoke the object, it will always be the same, including with the same properties filled in the previous "levels".
With levels I refer to the increasing and Verical flow of the Application. The lower levels would be first instance files, such as index php. or in more elaborate systems Froncontroller and with higher levels, the Action/Page Controllers or the Models.
Singleton a very useful pattern, if used correctly.
The unrestrained use of this pattern in the past has given it a bad reputation among experienced programmers because when you abuse Singleton, you simply leave global variables "cute".
But allied to Registry, creating what we call the Singleton Registry, you have a large box accessible in any scope to store everything that needs to be used in any part of the code.
Let’s see how it looks:
/**
* Registry Class
*
* @author Bruno Augusto
*
* @copyright Copyright (c) 2010 Next Studios
* @license http://creativecommons.org/licenses/by/3.0/ Attribution 3.0 Unported
*/
class Registry {
/**
* Registry Instance
*
* @staticvar Registry $_instance
*/
private static $_instance;
/**
* Registry Storage
*
* @var array $registry
*/
private $registry = array();
/**
* Enforcing Singleton. Disallow Cloning
*/
private function __clone() {}
/**
* Enforcing Singleton. Disallow Direct Constructor
*/
private function __construct() {}
/**
* Get Registry Instance
*
* @return Registry
* Registry Instance
*/
public static function getInstance() {
if( NULL === self::$_instance ) {
self::$_instance = new Registry;
}
return self::$_instance;
}
/**
* Add/Set a Registry Entry value
*
* @param string $key
* Registry Key
*
* @param mixed $value
* Value to be stored
*
* @return Next\Components\Registry
* Registry Object (Fluent Interface)
*/
public function set( $key, $value ) {
$key = trim( $key );
if( ! empty( $key ) ) {
$this -> registry[ $key ] = $value;
}
return $this;
}
/**
* Get a Registry Entry value
*
* @param string $key
* Registry Key
*
* @return mixed
* Registry Entry
*/
public function get( $key ) {
$key = trim( $key );
return ( array_key_exists( $key, $this -> registry ) ? $this -> registry[ $key ] : FALSE );
}
}
Realized the difference?
We block access to the object constructor, so it cannot be instantiated with the operator new, which is what makes the object instance change.
Extra Credit: To see a representation of the variation of an object instance, pass the instance as argument to spl_object_hash()
But to work with objects you need to instill it and you will yes instantiate the Registry class, but indirectly through the static method Registry::getInstance().
This method queries a static property and checks if there is an instance of the object stored in it. If it does not exist, it means that the registry is being used for the first time, then it is created.
At other times, at the higher levels, this instance already exists and instead of being created again, it is returned the way it is.
And by "the way you are," I mean whatever’s inside that big box, in your case, your connecting object, which you arrow through Registry:() and rescues through Registry::get(). Let’s see?
$link = new Site( /** ... */ );
Registry::getInstance() -> set( 'link', $link );
// Em alguma outra parte do código DEPOIS de adicionar o objeto à caixa
$link = Registry::get( 'link' );
$link -> prepare( '/** ... */' );
// ...
:D
If the bank is the same for both methods not why create two connections.
– rray
Utilizes a Pattern Design.
– ptkato
In fact, two Design Patterns, each to solve part of the problem. Specifically in your case, after implementing the Patterns, you would have in your constructor a property that would receive the connection link stored by Pattern (Registry) and then use this property as connection objects. Or you would rescue the link from within the box in each method, whatever.
– Bruno Augusto
Or save the object as property of the class. In this situation Registry with Singleton is killing ant with bazooca.
– gmsantos
I agree disagreeing, because everything depends on the complexity of the Application. Of course, the applicability of Registry in a project is almost always restricted to just perpetuating one or more link(s) from the Application Controller to the Model, but since you don’t know what else the Application does, there may be some other recourse that requires a single body. I even doubt my own words, but also, I don’t think I had any answer as to this problem on the site yet. Not that I have even researched either... : P
– Bruno Augusto