A simpler singleton - php

All the singleton patterns I have seen use a reference to the object to determine if the object has been instantiated. However, if I am using a singleton to guarantee only one db connection, why not use the db connection resource link to do this? Here is the code I am using. (PS: it works fine). I use the comment to be able to search for my classes easily.
/*one*/
class one
{
public static $db;
private function __construct()
{
self::$db=new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DATABASE);
}
public static function get()
{
if(self::$db==NULL)
{
new self();
}
return self::$db;
}
}

In PHP, a constructor does not return.
So your get method returns a one object, the first time it's called, then a mysqli object. Probably not what you want.
if( self::$_db == NULL )
{
return new self(); // Here you return an object of class one
}
else
{
return self::$_db; // Here you return an object of type mysqli
}
If you want to return the mysqli object, you do not need a singleton, as there is no need to create an instance of an object that's only here to return an instance of another object.
The registry pattern would be better in such a case.
If you need to provide methods (a wrapper for your DB object), then create a real singleton.
EDIT
I checked your updated code.
Now you return always the mysqli instance. But you do not need to instantiate your own object. That's completely useless...
If you really want to go with your kind of pattern, as golden said, in your static instance, checks if self::db is NULL. If yes, creates the mysqli instance, and assign it to self::db. Then returns it.
public static getDatabaseInstance()
{
if( self::$_db == NULL )
{
self::$_db = new mysqli( ... );
}
return self::$_db;
}
Also set the constructor private, so users won't be able to create useless instances of your class. Or better make it public and throw an exception:
public function __construct()
{
throw new Exception( 'This class is not supposed to be instantiated' );
}

Define it works fine :)
Try to:
compare object hashes returned from both of the methods (does matter when you use object cloning)
connect to DB using different credentials (e.g. in unit tests)
disconnect from the DB and reconnect again
reset the instance of the object (now creating 1000 objects using new fills the memory up)
tell some other developer to create in instance of this class, he will for sure look for one::getInstance() method. How do he guesses the behavior of this class?
Singletons are about global state. Looks like here you have global state + some mess.

Assuming I'm parsing your question correctly, you're asking if it's okay to use the nullity of $db to make sure that you only instantiate one; that's a perfectly valid way to do things, and in fact is what I would recommend. PHP null is explicitly intended to represent a variable with "no value" - a perfect fit for the uninitialized state of the singleton pattern.
Typically, these things will just be called by an intuitive name, e.g. SomeAppDbConn.

class one
{
private static $_selfInstance;
public $db;
private function __construct()
{
}
public function getDb()
{
if($this->db == null)
$this->db=new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DATABASE);
return $this->db;
}
public static function getInstance()
{
if( !(self::$_selfInstance instanceof self) ) {
self::$_selfInstance= new self();
}
return self::$_selfInstance;
}
}
Access
$db = one::getInstance()->getDb();

As Macmade already pointed out, the constructor method doesn't return anything but an instance of the class. Assuming you always want the same instance of mysqli, here's how I'd do it.
class DBInstance
{
protected static $db;
private function __construct()
{
// intentionally empty
}
public static function get()
{
if(self::$db === NULL)
{
self::$db=new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DATABASE);
}
return self::$db;
}
}
It most certainly is a singleton pattern with an added bonus of separating instantiation from the instantiated class.

Related

What is the difference between a public constructor which calls a class method and a class method that calls another class method?

I'm a little new to OO programming and am having trouble grasping why one mechanism works and another does not.
I've create a simple class that is to return a MySQL database handle. My attempt at returning the handle directly from a constructor fails. But succeeds from either a class method or from a class(?) method after an instance has been created. Here's the class definition and the sample script
<?php
class HMMDatabaseHandle {
private static $configfile = "config.json";
// uncomment for test 1
// public function __construct () {
// return self::get_handle_admin();
// }
public static function create() {
return self::get_handle_admin();
}
private static function get_handle_admin() {
$config = json_decode(file_get_contents(self::$configfile));
$dbhost = $config->database->dbhost;
$dbname = $config->database->dbname;
$dbuser = $config->database->dbuser;
$dbpass = $config->database->dbpass;
try {
return new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
}
catch(PDOException $e) {
echo $e->getMessage();
}
}
}
?>
And here is the test script I'm using:
<?php
require_once 'HMMDatabaseHandle.php';
// Test 1 - fails (uncomment constructor func) at call to prepare() with:
// PHP Fatal error: Call to undefined method HMMDatabaseHandle::prepare()
//$dbh = new HMMDatabaseHandle();
// Test 2 - works when class creates default constructor
// i.e. no explicit __construct() func
// Fetching data from executed query is fine
//$db = new HMMDatabaseHandle();
//$dbh = $db->create();
// Works using static class methods rather than instance
$dbh = HMMDatabaseHandle::create();
$sth = $dbh->prepare('select data_title,track_id from master');
$sth->execute();
while($row = $sth->fetch(PDO::FETCH_ASSOC)) {
...
}
My questions are:
Why can't I return the handle directly from a constructor when it seems so similar to calling the class method directly? Why does it matter whether the constructor calls the class method or my script calls it?
If I create an instance with PHP's default constructor, am I really calling a class method with $db->create()?
I seem to be missing some fundamental concept here. Thanks in advance!
You can't return the handle from the constructor in that context because that would violate the defined behavior of new. new SomeClass(); will only ever return an instance of the class, regardless of what other methods are called in the constructor.
__construct() is a void method. It is not intended to return anything1. That doesn't mean that the other code in it doesn't get executed, just that your return is disregarded in the context of creating a new object. This makes sense as the primary purpose for the constructor is to provide a means to pass dependencies to the object. Sometimes it is used to do additional initialization/setup of the object, but many people believe it should not do any work other than assigning the given arguments to the object's properties. Either way, there should be no need for it to return anything.
1 You can actually call the __construct() method explicitly after you create the object, and then it will behave like a normal method and your return will work.
$db = new HMMDatabaseHandle();
$dbh = $db->__construct();
var_dump($dbh); // PDO Object
This isn't a normal thing to do though, and I can't think of a scenario where it would be useful or desirable. I just wanted to point out that it is possible.
Why can't I return the handle directly from a constructor when it
seems so similar to calling the class method directly?
If you were able to do that, then you wouldn't have an instance of HMMDatabaseHandle; you'd have an instance of PDO. How would you access any other methods that HMMDatabaseHandle provides?
While I fully agree with #Don't Panic's answer, I need to also point out that you're mixing static and instance methods.
As a general rule of thumb, use the static keyword when you want to be able to call a method without instantiating the object first. If you want to actually create and use an object, then you can define you class like so and use $this-> (or $object-> if outside of the class) instead of :: to access instance properties and methods.
<?php
class HMMDatabaseHandle
{
private $configfile = "config.json";
public function __construct()
{
// You're not initializing anything in here, so this constructor is optional.
}
public function create()
{
return $this->get_handle_admin();
}
private function get_handle_admin()
{
$config = json_decode(file_get_contents($this->configfile));
$dbhost = $config->database->dbhost;
$dbname = $config->database->dbname;
$dbuser = $config->database->dbuser;
$dbpass = $config->database->dbpass;
try {
return new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
}
catch (PDOException $e) {
echo $e->getMessage();
}
}
}
To actually execute this, you need to now instantiate new class.
$dbManager = new HMMDatabaseHandle();
$handle = $dbManager->create();
Finally, there is a trick you can employ to make your constructor chainable. Simply wrap it in brackets.
$handle = (new HMMDatabaseHandle())->create();

database connection is not recognized in my functions [duplicate]

A couple of the options are:
$connection = {my db connection/object};
function PassedIn($connection) { ... }
function PassedByReference(&$connection) { ... }
function UsingGlobal() {
global $connection;
...
}
So, passed in, passed by reference, or using global. I'm thinking in functions that are only used within 1 project that will only have 1 database connection. If there are multiple connections, the definitely passed in or passed by reference.
I'm thining passed by reference is not needed when you are in PHP5 using an object, so then passed in or using global are the 2 possibilities.
The reason I'm asking is because I'm getting tired of always putting in $connection into my function parameters.
I use a Singleton ResourceManager class to handle stuff like DB connections and config settings through a whole app:
class ResourceManager {
private static $DB;
private static $Config;
public static function get($resource, $options = false) {
if (property_exists('ResourceManager', $resource)) {
if (empty(self::$$resource)) {
self::_init_resource($resource, $options);
}
if (!empty(self::$$resource)) {
return self::$$resource;
}
}
return null;
}
private static function _init_resource($resource, $options = null) {
if ($resource == 'DB') {
$dsn = 'mysql:host=localhost';
$username = 'my_username';
$password = 'p4ssw0rd';
try {
self::$DB = new PDO($dsn, $username, $password);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
} elseif (class_exists($resource) && property_exists('ResourceManager', $resource)) {
self::$$resource = new $resource($options);
}
}
}
And then in functions / objects / where ever:
function doDBThingy() {
$db = ResourceManager::get('DB');
if ($db) {
$stmt = $db->prepare('SELECT * FROM `table`');
etc...
}
}
I use it to store messages, error messages and warnings, as well as global variables. There's an interesting question here on when to actually use this type of class.
Try designing your code in an object-oriented fashion. Methods that use the database should be grouped in a class, and the class instance should contain the database connection as a class variable. That way the database connection is available to the functions that need it, but it's not global.
class MyClass {
protected $_db;
public function __construct($db)
{
$this->_db = $db;
}
public function doSomething()
{
$this->_db->query(...);
}
}
I see that a lot of people have suggested some kind of static variable.
Essentially, there is very little difference between a global variable and a static variable. Except for the syntax, they have exactly the same characteristics. As such, you are gaining nothing at all, by replacing a global variable with a static variable. In most examples, there is a level of decoupling in that the static variable isn't referred directly, but rather through a static method (Eg. a singleton or static registry). While slightly better, this still has the problems of a global scope. If you ever need to use more than one database connection in your application, you're screwed. If you ever want to know which parts of your code has side-effects, you need to manually inspect the implementation. That's not stuff that will make or break your application, but it will make it harder to maintain.
I propose that you chose between one of:
Pass the instance as arguments to the functions that needs it. This is by far the simplest, and it has all the benefits of narrow scope, but it can get rather unwieldy. It is also a source for introducing dependencies, since some parts of your code may end up becoming a middleman. If that happens, go on to ..
Put the instance in the scope of the object, which has the method that needs it. Eg. if the method Foo->doStuff() needs a database connection, pass it in Foo's constructor and set it as a protected instance variable on Foo. You can still end up with some of the problems of passing in the method, but it's generally less of a problem with unwieldy constructors, than with methods. If your application gets big enough, you can use a dependency injection container to automate this.
My advice is to avoid global in the bulk of the code - it's dangerous, hard to track and will bite you.
The way that I'd do this is to have a function called getDB() which can either be at class level by way of a constructor injection or static within a common class.
So the code becomes
class SomeClass {
protected $dbc;
public function __construct($db) {
$this->dbc = $db;
}
public function getDB() {
return $this->dbc;
}
function read_something() {
$db = getDB();
$db->query();
}
}
or using a common shared class.
function read_something() {
$db = System::getDB();
$db->query();
}
No matter how much elegant system design you do, there are always a few items that are necessarily global in scope (such as DB, Session, Config), and I prefer to keep these as static methods in my System class.
Having each class require a connection via the constructor is the best way of doing this, by best I mean most reliable and isolated.
However be aware that using a common shared class to do this can impact on the ability to isolate fully the objects using it and also the ability to perform unit tests on these objects.
None of the above.
All the mysql functions take the database connection argument optionally. If you leave that argument out, the last connection by mysql_connect() is assumed.
function usingFunc() {
$connection = getConnection();
...
}
function getConnection() {
static $connectionObject = null;
if ($connectionObject == null) {
$connectionObject = connectFoo("whatever","connection","method","you","choose");
}
return $connectionObject;
}
This way, the static $connectionObject is preserved between getConnection calls.

Singleton v Single Instance DB Connection in PHP

I'm moving onto teaching myself OOP in PHP.
I'm creating a couple of little web apps and have followed a lot of tutorials that either create the database (using PDO) via a Singleton, or via passing the global around. I've read that these are pretty much the same thing and are both to be avoided like the plague.
So I've watched the Google Tech Talks on clean code, and read almost every SO article on dependency injection and the like. I have a couple of questions.
The clean code videos suggest you shouldn't do 'work' in your constructors. Is this 'work' in reference to business logic. Ie. If my class's job is to create another object, is that an OK kind of 'work'?
For example, in trying to conform to single repsonibility classes I created three.
Class DB - which actually connects to the database.
Class DBFactory - which creates the DB object which connects to the database.
Class DBInstance - which returns a single instance of the DBFactory created PDO object.
Please note that I'm trying to create a single instance, without creating a Singleton pattern.
So I try and pass my dependencies for each class up the chain. I find myself in a position where I have to create all of the objects (from DB down) so I can inject the dependencies. For some reason I thought it would work the other way, I'd create the first object, which would create the second for me etc. I'm clearly missing something?
Hopefully this helps others as well - there seems to be a myriad of questions relating to this stuff and databases but very little good examples.
(I should mention this does work, I do get a list of hotel names out of the database!)
TestCode.php
include './classes/DB.php';
include './classes/DBFactory.php';
include './classes/DBInstance.php';
include './classes/Location.php';
$db = new DB;
$dbfactory = new DBFactory($db);
$dbinstance = new DBInstance($dbfactory);
$dbh = $dbinstance->getDbInstance();
//Example business logic
$location_names = Location::getLocationNames($dbh);
print_r($location_names);
Class DB.php:
class DB {
private $_dbhost = 'myhost';
private $_dbname = 'myname';
private $_dbuser = 'myuser';
private $_dbpass = 'mypass';
private $_error;
public function connect() {
try {
return new PDO("mysql:host=$this->_dbhost;dbname=$this->_dbname",
$this->_dbuser, $this->_dbpass);
}
catch (PDOException $e) {
$this->_error = 'Error! ' . $e->getMessage() . '<br />';
die();
}
}
public function getError() {
if (isset($this->_error)) {
return $this->_error;
}
}
}
Class DBFactory.php
class DBFactory {
private $_dbh;
public function __construct(DB $db) {
$this->_dbh = $db;
}
public function Create() {
return $this->_dbh->Connect();
}
}
Class DBInstance.php
class DBInstance {
private static $_dbinstance;
public function __construct(DBFactory $dbfactory) {
if (!isset(self::$_dbinstance)) {
self::$_dbinstance = $dbfactory->Create();
}
}
public function getDbInstance() {
return self::$_dbinstance;
}
}
Your code seems to do what you want it to.. but maybe we can use less object instantiation using inheritance and maybe we can avoid static properties in instanciated classes.
Also in regard to using a pattern of dependency injection that is able to handle multiple connections, but support using a single instance of it. exemple first, classes after
$params = array
('host'=>'localhost',
'db'=>'ice',
'user'=>'kopitar',
'pass'=>'topnet',
'charset'=>'utf8'); // passing the charset explicitely is great
$handle = new handle($params);
$db = $handle->getInstance();
we can either pass the $db to our functions
$location_names = Location::getLocationNames($db);
or the whole $handle. as long as $handle is not reconstructed, it will always return the same database connection.
$location_names = Location::getLocationNames($handle);
if I want to reconstruct I need the whole $handle
$handle->__construct(/* params but with another database infos */);
$db2 = $handle->getInstance();
As for the classes, I think we want the params to arrive from the instanciated class, so we can change them later.
class db {
function __construct($params) {
foreach ($params as $param => $value) {
$this->{$param} = $value; // assigns the connections infos
}
}
protected function connect() {
$dsn = 'mysql:host='.$this->host.';dbname='.$this->db.';charset='.$this->charset;
return new PDO($dsn,$this->user,$this->pass);
}
}
the factory creates a connection from params and passes it to something else, good factory
class factory extends db {
protected function create() {
return $this->connect();
}
}
now we want to have our object to keep it's connection as long as we do not rebuild it. so we give it to instance
class instance extends factory {
function instantiate() {
$this->instance = $this->create();
}
}
and last but not least, our handle which returns the instance. it could be in instance class.....................
but I feel like having four and find no real reason not to.
class handle extends instance {
function __construct($params) {
db::__construct($params);
$this->instantiate(); // when we construct a handle, we assign an instance to the instance property
}
function getInstance() {
return $this->instance;
}
}
KISS
Don't make things more complex than they are, of course this is just my opinion, but as I see it you are building a complex solution for a problem that someone else says might exist is some cases.
Php is not multi threaded so there goes one of the biggest arguments overboard. (in very rare-occasions it might be)
I'm using singletons for my database connections for about 15 years now and never ever had a problem with them, I do play around with different connections having one singleton handle several connection instances, but whatever... it works great and everyone that looks at the code.. understands it directly.
I'm not using globals because they can be overwritten and are kind of hard to predict (when it holds the correct object, and when/why they don't)
Use OOP to make your code cleaner, easier to work with and more flexible.
Don't use it to fix problems that aren't there and make your code more complex because others tell you to.
An very simple example of a db-connection singleton class handling several different connections.
class singleton{
private static $_instances=array();
public static function getInstance($connectionName){
if(!isset(self::$_instance[$connectionName]){
self::$_instance[$connectionName]=self::_getConnection($connectionName);
}
return self::$_instance[$connectionName];
}
}
just my 2 cents
Why do you have a factory if you have a singleton? This is needless.
This is a never-ending debate, but I'm advocate of do not use singletons for database connections.
As far as in most applications, you have only one data channel, you can consider your database connection unique, but this might not be always true.
In deed, the effort made to create a singleton database connection is even bigger than just create a regular one.
Also, your class DB is not configurable, therefore, you need to change it when your connection parameters change. And I think DB is a very bad name for this.
I'd rather call this Storage and do something like:
inteface Storage {
public function insert($container, array $data);
public function update($container, array $data, $where);
public function delete($container, $where);
public function getAll($container);
public function getOne($identifier);
}
final class PdoStorage implements Storage {
private $dbh;
private $dsn;
private $user;
private $pswd;
public function __construct($dsn, $user, $pswd) {
$this->dsn = $dsn;
$this->user = $user;
$this->pswd = $pswd;
}
// Lazy Initialization
private function connect() {
if ($this->dbh === null)
$this->dbh = new PDO($this->dsn, $this->user, $this->pswd);
}
public function insert($container, array $data) {
$this->connect();
// ... omitted for brevity
}
}
Now, when you need a database storage, you do:
$someObj = new SomeClass(new PdoStorage(...));
Now you might be wondering if you will need to create an PdoStorage for each single object that depends on it.
The answer is: no!
Now you can use a factory to simplify your life.
class SomeFactory {
private $defaultStorage;
public function __construct(Storage $storage) {
$this->defaultStorage = $storage;
}
public function create($type) {
// Somehow fetches the correct class to instantiate and put it into $class variable , for example... and then
return new $class($this->defaultStorage); // Or you'd better do this with reflection
}
}
$factory = new SomeFactory(new PdoStorage(...));
$factory->create('SomeClass');
This way, you can have just one database connector or more if you need.

OOP efficiency when using a class in another class

I have a class called DB (class.pdo.php) that does all the handling on mysql queries using PDO and another class called user that I use to manage a login system.
My question relates to always having to instantiate the $db in every public function of users so I can use DB. Is this efficient? Shouldn't I be instantiating DB inside the __construct() of users?
This is my code
require_once("../../class.pdo.php");
class user {
private $db = null;
public function __construct(){
/* Empty? */
}
public function find_by_email($email){
$db = new db();
$db->query('SELECT * FROM users WHERE email = :email LIMIT 1');
$db->bind(':email',$email);
$result = $db->single();
return $result;
}
public function create($email,$password,$first_name,$last_name){
$db = new db();
$db->query("INSERT INTO users(email,password,first_name,last_name,created_at) VALUES (:email,:password,:first_name,:last_name,NOW())");
$db->bind(':email',$email);
$db->bind(':password',$password);
$db->bind(':first_name',$first_name);
$db->bind(':last_name',$last_name);
$result = $db->execute();
return $db->lastInsertId();
}
[more similar functions ommited]
Well, despite of some comments suggesting the use of the Singleton pattern, I totaly disagree in using it for this purpose.
Your application will not always use a single connection to just one database.
Let me show you how I'd do this:
class DbConnector {
private $dbh;
private $dsn;
public function __construct($dsn) {
$this->dsn = $dsn;
}
private function connect() {
if($this->dbh === null) {
$this->dbh = new PDO($this->dsn);
}
}
public function disconnect {
if($this->dbh !== null) {
$this->dbh = null;
}
}
public function query($sql) {
$this->connect();
//... do the rest
}
public function fetchAll($sql) {
$this->connect();
//... do the rest
}
public function insert($table, $values) {
$this->connect();
//... do the rest
}
public function update($table, $values, $cond) {
$this->connect();
//... do the rest
}
public function delete($table, $cond) {
$this->connect();
//... do the rest
}
}
class User {
private $dbConn;
public function __construct(DbConnector $dbConn) {
$this->dbConn = $dbConn;
}
public function create($email,$password,$first_name,$last_name){
$this->dbConn->query("INSERT INTO users(email,password,first_name,last_name,created_at VALUES (:email,:password,:first_name,:last_name,NOW())");
$this->dbConn->bind(':email',$email);
$this->dbConn->bind(':password',$email);
$this->dbConn->bind(':first_name',$email);
$this->dbConn->bind(':last_name',$email);
$this->dbConn->execute();
return $this->dbConn->lastInsertId();
}
// ...
}
Results:
No singleton used = testable.
Connection to the database is just openned when needed
Your connection is persistent. If you open and close connections in every method, you loose the capability of creating transactions.
What about using the Singleton pattern to create one object for the connection and use it everytime you need it, instead of creating new objects all the time?
I would do something similar with lazy loading: don't initiate in the constructor unless you're sure you actually need the connection every time an object is created but absolutly don't create a new object on each method call. Instead, save the resulting object into an object var which is checked on each method call and initiates the connection if missing.
class user {
protected $_db = null;
private function _init_db() { $this->_db = new XXX; }
public function create( $x, $y, $z ) {
if ( ! $this->_db ) $this->_init_db();
# use $this->_db ..
}
public function find_by_email( $x, $y, $z ) {
if ( ! $this->_db ) $this->_init_db();
# etc
}
}
This has the advantages of avoiding global static state (singletons..) and only creates the connection / object at the very last moment so you're sure you actually need it and it's not just a useless connection.
Speaking of efficiency, the main problem with your code is that it establishes new connection for the every method called. This one is indeed inefficient to the point of killing your database server. And it's incomparable to the other problem you have.
So, in general, you can have whatever way you want - either get somehow an instance of db class in the every function or use a class variable - but either way have to use single PDO instance throughout whole application.
Also I find your functions quite inefficient from the amount of code point of view, and would have optimized them this way
public function create($email,$password,$first_name,$last_name){
$sql = "INSERT INTO users(email,password,first_name,last_name,created_at) VALUES (?,?,?,?,NOW())";
$this->db->query($sql);
$result = $db->execute(func_get_args());
return $db->lastInsertId();
}
From a object point of view, I'd leave database instantiating within the methods, rather than an entire class.
Each method should only see the variables and data it needs, in order to perform its function.
For instance, a createUser() method would need to see variables or properties such as $username, $usergroupId, as well as $database etc.
However, you may have a function which is called randomPassword(), which generates a random password from numbers and letter.
This randomPassword() function doesn't need the database object and therefore, an already initialised database connection in the object scope would be wasteful.
It would be better only to create the new database object in methods that required it.
In addition, in my application, I don't create a new database connection each time I used new database. Instead, I've opted for a singleton PDO database object which keeps the connection active.
I can then just call the database object statically to retrieve an existing connection. Therefore, if, in the process of running my application I need to have 20 database objects, my application then only returns the same object, and the same connection.

php ClassName::staticFunction()->publicFunction() What is this doing?

I'm reading up on php design patterns, and I saw this code:
<?php
require_once("DB.php");
class DatabaseConnection
{
public static function get()
{
static $db = null;
if ( $db == null )
$db = new DatabaseConnection();
return $db;
}
private $_handle = null;
private function __construct()
{
$dsn = 'mysql://root:password#localhost/photos';
$this->_handle =& DB::Connect( $dsn, array() );
}
public function handle()
{
return $this->_handle;
}
}
print( "Handle = ".DatabaseConnection::get()->handle()."\n" );
print( "Handle = ".DatabaseConnection::get()->handle()."\n" );
?>
I understand it all except the last two print statements. I've been messing around with it, but I don't understand the static function somehow calling a public non-static function.
I've notice I can do:
DatabaseConnection::get()->get()->get()->handle();
but I can't so something like:
DatabaseConnection::get()->handle()->get();
I just don't understand what this is doing, other than calling the get function then calling the handle function.
This works because the static function returns a new object. This type of construction is typically referred to as a Singleton, since it is attempting to enforce that only one instance of a DatabaseConnection is ever available.
Notice that the constructor is private, so you cannot explicitly call new DatabaseConnection() unless you are already inside the class. Solutions utilizing a Singleton will have a property, initally null, that is then set to a non-null value upon object instantiation. The 'getInstance' (or get in this case) method will only return a new object if the property is null.
DatabaseConnection::get() creates an instance of DatabaseConnection and returns it.
So...
DatabaseConnection::get()->handle();
...could also be written as follows...
$db = DatabaseConnection::get();
$db->handle();

Categories