PHP Static v Singleton class - ConnectionFactory explained - php

I'm new to this level of PHP programming and I've been reading a post about singleton and static classes. I'm in the process of writing a class that would facilitate my DB connections.
I came across the following code by Jon Raphaelson (here) :
class ConnectionFactory
{
private static $factory;
public static function getFactory()
{
if (!self::$factory)
self::$factory = new ConnectionFactory(...);
return self::$factory;
}
private $db;
public function getConnection() {
if (!$this->db) // this line was modified due to comment
$this->db = new PDO(...); // this line was modified due to comment
return $db;
}
}
function getSomething()
{
$conn = ConnectionFactory::getFactory()->getConnection();
.
.
.
}
It seemed like I had found what I was looking for, however I have a few questions about it.
self::$factory = new ConnectionFactory(...); - I don't see a constructor in this class. Do I just create this constructor and pass in the db details ('dbname', 'user', 'pass', etc)?
the getSomething() function, I'm assuming that the intent was to put all of the actual functions that would retrieve data within the ConnectionFactory class - and this is the reason for this function being in this class. Otherwise, I would have expected this function to be within another class. [edit] SKIP THIS QUESTION, I didn't see the one bracket.
What happens when two users are logged into the site and are requesting the DB connection (both are doing updates, etc)? Will it be an issue that this is a singleton?
Thanks!

This is mostly to expand on my comments under the question...
The better "singleton" pattern would be this:
class ConnectionFactory {
protected static $connection;
public function getConnection() {
if (!self::$connection) {
self::$connection = new PDO(...);
}
return self::$connection;
}
}
The users of this factory should expect an instance of it, not call it themselves:
class Foo {
protected $connectionFactory;
public function __construct(ConnectionFactory $factory) {
$this->connectionFactory = $factory;
}
public function somethingThatNeedsAConnection() {
$connection = $this->connectionFactory->getConnection();
...
}
}
$foo = new Foo(new ConnectionFactory);
This allows Foo to get a connection itself when needed, but also allows you to inject some alternative connection into Foo, for example for testing purposes.
As a convenience measure and to cut down on instantiation complexity, this pattern is also good:
class Foo {
protected $connectionFactory;
public function __construct(ConnectionFactory $factory = null) {
if (!$factory) {
$factory = new ConnectionFactory;
}
$this->connectionFactory = $factory;
}
...
}
This still allows the dependency to be injected and overridden, but it doesn't require you to inject a factory every time you instantiate Foo.

The factory is a singleton because you're not want more than one factory.
You don't need a constructor, you can setup whatever state you need for the factory the getFactory() method. The getFactory() function doesn't get a connection, so don't do any connection related setup here, but not the connection object itself. Factories 'build instances' of classes for you to use, so you'd use the getConnection() method to set the state and construct the connection object the factory is supposed to generate.
getSomething() isn't a method in the ConnectionFactory class, it's just a example of using the factory class to get a factory, then get a connection.
I personally hate method chaining in PHP. What's really happening in getSomething() is:
function getSomething()
{
$factory = ConnectionFactory::getFactory();
$conn = $factory->getConnection();
.
.
.
}

A class doesn't need an explicit constructor in order to be instantiated with new ClassName(). However, if the class is supposed to be a singleton (and it looks like it in this case), the entire point of the pattern is making such instantiations impossible from outside of the class which is why I believe there should be a constructor declared with private keyword.
The get getSomething() is a "standalone" function with an example of using your class.
No. Multiple users use multiple instances of PHP processing your script and nothing is shared among them.

Related

How to use an instance of a class within another class in PHP 7

I have what seems like a simple query but I have not found an answer elsewhere.
I have 2 classes, one called DB which essentially connects to the database and can then run queries. I instantiate it at the top of the document $db= new DB; and I can then run a series of queries on the database throughout the page.
The issue I am having is that I want to use this instance within another class I have called User.
I know I can either instantiate again but this does not make sense OR pass the instance of DB when instantiating User, for instance $user = new User($db); but considering the $db instance will be used by most classes I am going to create I am thinking there is a better solution to import it into other classes.
I have looked at the global route but I read it is bad practice + I am getting unexpected global error
class User{
global $db;
public function __construct()
{
var_dump($this-> db);
}//end constructor
}//end class
Since your DB client will be instantiated once and then used everywhere else my initial thought was to recommend passing it as a constructor parameter (dependency injection), but since you are not fan of this approach, I would recommend making your DB client a singleton class, which means it can only be instantiated once and any subsequent attempt would return the same instance everywhere.
You can see a detailed response about singleton classes in PHP at Creating the Singleton design pattern in PHP5.
As a quick example, your DB would look like similar to this:
final class DB
{
public static function getInstance()
{
static $inst = null;
if ($inst === null) {
$inst = new self();
}
return $inst;
}
private function __construct()
{
// your code here ...
}
// your code here ...
}
And then, on your User class you would just get the DB class instance:
class User {
// your code here ...
public function doSomething() {
$db = DB::getInstance();
// your code here ...
}
}
PHP does not handle scopes like Javascript does, your $db is undefined.
The scope of a variable is the context within which it is defined. For the most part all PHP variables only have a single scope. This single scope spans included and required files as well […] Within user-defined functions a local function scope is introduced. Any variable used inside a function is by default limited to the local function scope.
Source: http://php.net/manual/en/language.variables.scope.php
This means that there is only a global scope and a function/method scope in PHP. So, either pass the $db instance into the method as a collaborator
class User{
public function __construct() {}
public function getInfo(Database $db) {
$db->query( /* ... */ );
}
}
$user = new User();
$db = new Database();
$user->getInfo($db);
or pass it in the constructor (dependency injection)
class User{
private $db;
public function __construct(Database $db)
{
$this->db = $db;
}
public function getInfo() {
$this->db->query( /* ... */);
}
}
$db = new Database();
$user = new User($db);
$user->getInfo();

Calling PHP class from inside another class?

Im building small MVC, and have some doubts that would like to sort out.
I have dispatcher class, and that class needs HTTP Request, HTTP Response and Router classes.
I could do this using Dependency Injection like:
$dispatcher = new Dispatcher($request, $response, $router);
Now lets say I dont like this approach and would like to use classes inside Dispatcher class like this:
class Dispatcher()
{
protected $request;
protected $response;
protected $router;
public function __construct()
{
$this->request = new Request();
$this->response = new Response();
$this->router = new Router();
}
}
Is there something wrong with 2 approach? Am I braking some OOP principles? Or is it just fine to use it this way?
It's hard to say that there is anything wrong with one approach or the other. It's only wrong if it does not fulfill required specifications.
The reason that the first approach is preferred over the second is because it allows you flexibility on what you can inject. For example:
class Dispatcher {
private $req;
public function __construct(IRequest $req) {
$this->req = $req;
}
}
interface IRequest {}
class Request implements IRequest {}
class MockRequest implements IRequest {}
//PRODUCTION
new Dispatcher(new Request);
//TESTING
new Dispatcher(new MockRequest);
There's a reason you should use DI that you're glancing over: Dependency injection removes the dependencies from your code and abstracts them to the caller. This makes it easier to unit test your code as well, since the code doesn't inherently require an external dependency to function.
This is best demonstrated in an example. Imagine if your class required a database connection:
class Dispatcher()
{
protected $db
public function __construct() {
$this->db = new MysqlDB();
}
}
Now, you just forced everyone to use a MySQL database. But, had you used DI, you can abstract the details of the database away, and just rely on some class that represents a database object:
class Dispatcher()
{
protected $db
public function __construct( Database $db) {
$this->db = $db;
}
}
And then, you define some objects that represent different database connections:
interface Database {
public function query( $sql);
}
class MySQLDB implements Database {
public function query( $sql) { // Stuff for MySQL
}
}
class OracleDB implements Database {
public function query( $sql) { // Stuff for Oracle
}
}
Now, whether your users do:
$dispatcher = new Dispatcher( new MysqlDB());
Or:
$dispatcher = new Dispatcher( new OracleDB());
It doesn't matter - The same class can be reused for both databases.
The second example cause tight coupling between the Dispatcher class and all the 3 that it uses. If you are looking for a specific law or principle, that is violated by this, it would be open/closed principle.
P.S.: are you sure taht you are using event-driven architecture? Because that is the only context in which i found Dispatcher mentioned.
Second example should be called with a Factory suffix, since it creates other objects.
In both examples, you end up with a high coupled Dispatcher object (Dependancy inversion)
Dispatcher should be able to just ask for interfaces or service, that the other objects implement/ are registered to.

PHP Singleton extending class

I am new to OOP (PHP) and just met the design pattern - singleton.
I have found a DB class which uses mysqli (singleton class). I have added some custom methods to it (insert_id(), query(), fetch_result(), etc).
Then I created a new class called UserTools and I want to extend the database class to use the methods I've created previously (query(), fetch_result(), etc).
But I get this error:
Fatal error: Call to private Database::__construct() from invalid context in (...)
when I try to create instance of the new class (User Tools).
What should I do? Is it a right structure?
There are several way to achieve what you want.
One would be :
class UserTools {
private $db;
function __construct() {
$this->db = Database::db_connect();
}
function login() { /* ... */}
}
Although it would be better to directly pass the database instance to the constructor like this :
class UserTools {
private $db;
function __construct($db) {
$this->db = $db;
}
function login() { /* ... */}
}
// Usage
$userTools = new UserTools(Database::db_connect());
If you're really lazy you could just modify your database class and make the constructor public :
class Database {
/* ... */
public function __construct(){/* ... */}
/* ... */
}
class UserTools extends Database {/* ... */}
But I really discourage you to use the latter one. It's really bad code and it doesn't make sense in a logical point of view. Your UserTools class use a database instance. It is not a database.
It is my understanding that only protected and public methods and variables are inherited through extension, not private ones. Try changing your methods/variables from private to protected. public ones are visible to all.
For more information, See: PHP Visibility (Manual)
Edit
Understand the Singleton pattern. It is called 'singleton' because only one instance of a class is expected. Because of this, most classes implementing the singleton pattern define the constructor as private to restrict you from creating more than one.
To create an instance of a singleton, most classes define some kind of getInstance static method, which is public. This public method calls the private constructor, which probably sets flags indiciating that the class has been instantiated in order to prevent further attempts to instantiate the class. The getInstance method returns the results of calling the constructor, essentially the instance of the class.
You could write something like
class UserTools extends DB {
....
}
A quick example on inheritance in PHP:
class A {
public $a;
public function set_a($new_a) { $this->a = $new_a; return $this; }
public function get_a() { return $this->a; }
}
class B extends A {
public $b;
public function set_b($new_b) { $this->b = $new_b; return $this; }
public function get_b() { return $this->b; }
}
$objb = new B();
$objb->set_a("Some Value")->get_a(); //Some Value
The singleton pattern in most cases prevents instantiating the Singleton class by defining the constructor as private (ie private function __construct()).
So if you try to instantiate either your custom class or the original one that you're extending you will get the message above. You should either create a different class or define and use your function as static (eg public static function query($sql, $dbconnection)).
See http://php.net/manual/en/language.oop5.patterns.php

Properly using classes in other classes in php?

Should have asked someone this a long time ago.
What is the best way to use other classes within another class?
For instance, lets say I have an application class:
class Application
{
public function displayVar() {
echo 'hello world';
}
}
and a database class
class Database
{
// connects to db on construct
public function query() {
// queries db
}
}
now, i want to add a function to my application class that uses a function from the db class
class Application
{
public function displayVar() {
echo 'hello world';
}
public function getVar() {
global $db;
$sql = foo;
$db->query($sql);
}
}
so then I have
$db = new Database();
$app = new Application();
$app->getVar('var');
Is there a better way of doing this? Really what I am looking for is the standard way of doing it, not another way of rigging it.
There are a couple of ways of doing that. Global variables is certainly one way and the most looked down upon too. You can create a Singleton and all other classes that need database access would call upon this singleton.
final class Database {
private static $connection;
public static function getInstance() {
if(self::$connection == NULL) {
self::$connection = // init your database connection
}
return self::$connection;
}
}
And use this database connection object in whatever class needs it.
class Application {
public function displayVar() {
echo 'hello world';
}
public function getVar() {
$db = Database::getInstance();
$sql = foo;
$db->query($sql);
}
}
This is all well for a start and a great step beyond using global variables, but you can do better with Dependency Injection. Dependency Injection is a simple concept that if a class has any external dependencies, such as the database connection in your example, you explicitly pass those to the needy class in its constructor or a method. So the new code would look something like Jonathan's solution. A major advantage of using dependency injection is in unit testing, where you can easily replace this actual database object with a mock object and pass it to whoever needs it.
class Application {
private $db;
public function __construct(Database $db) {
$this->db = $db;
}
public function displayVar() {
echo 'hello world';
}
public function getVar() {
$sql = foo;
$this->db->query($sql);
}
}
For smaller projects, you can easily do it yourself. For large projects, there are various DI frameworks available for PHP
$db could be a property of your Application class. Any reference to it from within an instance of Application would be done via $this - $this->db
class Application {
private $db = null;
public function setDB($name) {
$this->db = new Database($name);
}
}
Include the class file (or set up autoinclude) in each PHP file that needs the class in question. Then instantiate it as needed.
If you need to have a "common" instance of an object, you can look at the Singleton and Factory patterns:
Singleton Pattern
Factory Pattern

In a PHP5 class, when does a private constructor get called?

Let's say I'm writing a PHP (>= 5.0) class that's meant to be a singleton. All of the docs I've read say to make the class constructor private so the class can't be directly instantiated.
So if I have something like this:
class SillyDB
{
private function __construct()
{
}
public static function getConnection()
{
}
}
Are there any cases where __construct() is called other than if I'm doing a
new SillyDB()
call inside the class itself?
And why am I allowed to instantiate SillyDB from inside itself at all?
__construct() would only be called if you called it from within a method for the class containing the private constructor. So for your Singleton, you might have a method like so:
class DBConnection
{
private static $Connection = null;
public static function getConnection()
{
if(!isset(self::$Connection))
{
self::$Connection = new DBConnection();
}
return self::$Connection;
}
private function __construct()
{
}
}
$dbConnection = DBConnection::getConnection();
The reason you are able/would want to instantiate the class from within itself is so that you can check to make sure that only one instance exists at any given time. This is the whole point of a Singleton, after all. Using a Singleton for a database connection ensures that your application is not making a ton of DB connections at a time.
Edit: Added $, as suggested by #emanuele-del-grande

Categories