There are two possibilities for solving this problem, one of which is less appropriate from the point of view of Object Orientation but perhaps more useful for your particular case.
The properties of a class are used to store everything that the class, through its object, may need during the request in which it was instantiated.
If you have several methods that act as wrappers for the repeating part of the PDO and all of them use the same object, instead of opening a connection for each method, you store the instance of the PDO in a class, like this:
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 bit 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, much less force the use of the 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, by itself, the Registry does not solve the problem of the state of the object, which is precisely what concerns its problem.
Without solving this problem, you would see:
- Duplicating code, as it currently should be doing
- Create a global variable and access it in the local scope of methods used by the global keyword or the superglobal array $ GLOBALS , which is extremely wrong
To solve this "problem" of the Registry, since it is not exactly a problem it does not solve that it was not designed to solve, just integrate it to the other Design Pattern, the Singleton .
Singleton is a standard that aims to make the instance of a single object unique. No matter where in the code you invoke the object, it will always be the same, even with the same properties populated in the previous "levels."
With levels I mean the ver- ical and increasing flow of the Application. The lowest levels would be first-instance files, such as index.php or in more elaborate systems a FronController and higher levels, Action / Page Controllers or Models.
Singleton is a very useful standard if used the right way.
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 the Registry, creating what we call Singleton Registry, you have a large box accessible at any scope to store everything that needs to be used in any part of the code.
Let's see how it goes:
/**
* 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 );
}
}
Did you notice the difference?
We block access to the object constructor, so it can not be instantiated with the new operator, which is what makes the instance of the object change.
Extra Credit: To see a representation of the instance variation of an object, pass the instance as an argument to spl_object_hash ()
But to work with objects you need to instantiate it and you will instantiate the Registry class, but indirectly through the static Registry :: getInstance () method.
This method queries a static property and checks to see 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, so it is created.
At other times, at higher levels, this instance already exists and instead of being created again, it is returned the way it is.
And with "whatever it is," I mean with everything inside that big box, in your case, your connection object, which you point to through Registry :: set () 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