Dependency Injection simple implementation - php

after reading this question i wonder if someone can help me understand how to implement correctly Dependency Injection with these PHP Classes:
class DBClass
{
private $mMysqli;
function __construct(mysqli $database)
{
$this->mMysqli=$database;
}
function __destruct()
{
$this->mMysqli->close();
}
public function listUsers()
{
$query='SELECT * FROM Utente;';
$resultset=$this->mMysqli->query($query);
while($row = $resultset->fetch_array(MYSQLI_ASSOC)) {
echo $row['username'];
echo $row['pwd'];
echo "<br />\n";
}
}
public function runQuery($query)
{
return $resultset=$this->mMysqli->query($query);
}
public function getConnection()
{
return $this->mMysqli;
}
}
Session class:
class Session
{
private $_session;
public $maxTime;
private $database;
public function __construct(DBClass $database)
{
$this->database=$database;
$this->maxTime['access'] = time();
$this->maxTime['gc'] = get_cfg_var('session.gc_maxlifetime');
session_set_save_handler(array($this,'_open'),
array($this,'_close'),
array($this,'_read'),
array($this,'_write'),
array($this,'_destroy'),
array($this,'_clean')
);
register_shutdown_function('session_write_close');
session_start();
...
}
}
User Class (for details about the currently logged in user):
class User
{
private $username;
private $role;
private $session;
function __construct($session)
{
$this->session=$session;
...
}
}
Externally:
$connection=new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_DATABASE);
$database=new DBClass($connection);
$session=new Session($database);
$user=new User($session);
Is this the proper way?

Yes. You are now injecting the dependencies through the constructor which provides for less coupling. You can now more easily swap out these dependencies, e.g. when UnitTesting you can replace them with Mocks.
You have still some coupling though by using the concrete DBClass as a TypeHint instead of an interface. So when you would want to use a different DBClass, it would have to be named DBClass. You could achieve more loose coupling by coding against an interface that the concrete classes have to implement instead.
To create only single instances of a class (as asked in the comments), you could either use a Singleton (like Kevin Peno suggested) or a Factory to create and keep track of if the instance has been created yet. Or use a DI Service Container, which is similar to a Factory, yet not the same thing. It creates and manages objects for you.
The Symfony Components library has a Dependency Injection Container with excellent documentation and introduction to the topic on how to further enhance DI this with Service Containers. The containers can also be used to limit instances. Check it out.

Related

Understanding Interfaces and Abstract Classes

I have never used Interfaces or Abstract Classes in PHP, but have come to a point where I want to support similar but different types of the same object (in this case Network Switches) and possibly add more in the future. I communicate with them via SSH (PHPSecLib) and which the interactions are different, the actual methods would be the same.
In my particular case I believe an Abstract Class, implementing the constants, private variables, connect functions and constructor/destructors would be appropriate, leaving the extended classes ONLY to implement the functionality, where an Interface would just be a template but each extended class would still re-implement methods that are the same between them.
Am I correct in thinking that Abstract Classes are the way to go in this scenario? Do you need to place empty methods in Abstract Classes which are overridden by extended classes or can the extended class have methods that don't exist in the Abstract class?
Example:
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '/home/devicepo/public_html/include/PHPSecLib');
include('Net/SSH2.php');
include('File/ANSI.php');
abstract class Switch
{
const STATUS_UNKNOWN = "-1";
const STATUS_OFFLINE = "0";
const STATUS_ONLINE = "1";
public $conn;
private $_server;
private $_username;
private $_password;
private $_bashshell;
public function __construct($server, $username, $password)
{
if (!$server)
die("Switch configuration not Defined");
$this->_server = $server;
$this->_username = $username;
$this->_password = $password;
}
public function connect()
{
// Establish new SSH2 Connection
$this->conn = new Net_SSH2($this->_server, 22);
if(!$this->conn->login($this->_username, $this->_password))
{
die("Failed to connect to Switch: " . $this->_server);
}
}
public function enable_port($port)
{
// Define in extended classes
}
public function disable_port($port)
{
// Define in extended classes
}
}
?>
I believe that in your case the Abstract class is the way to go. The reasons are that:
Your child classes share a big part of code with the parent class
Your child classes have a notion of similarity.
To be more specific regarding point 2, keep in mind that two classes implementing the same interface are not necessarily related. The interface represents an ability. Consider for example an airplane and a bird. Both can implement a flyable interface, but except from that they are not related in any other way. On the other hand, your child classes have a similar type. They are all switches. So your abstract class could be
abstract class BasicSwitch { // You cannot use the name switch
const STATUS_UNKNOWN = "-1";
const STATUS_OFFLINE = "0";
const STATUS_ONLINE = "1";
public $conn;
private $_server;
private $_username;
private $_password;
private $_bashshell;
public function __construct($server, $username, $password) {
if (!$server) die("Switch configuration not Defined");
$this->_server = $server;
$this->_username = $username;
$this->_password = $password;
}
public function connect() {
// Establish new SSH2 Connection
$this->conn = new Net_SSH2($this->_server, 22);
if(!$this->conn->login($this->_username, $this->_password)) {
die("Failed to connect to Switch: " . $this->_server);
}
}
abstract public function enable_port($port);
abstract public function disable_port($port);
}
and a concrete implementation could be
class CiscoSwitch extends BasicSwitch {
public function __construct($server, $username, $password) {
parent::__construct($server, $username, $password);
}
public function enable_port($port) {
echo 'Port is enabled';
}
public function disable_port($port) {
echo 'Port is disabled';
}
}
The most important think to keep in mind here is that CiscoSwitch is also a type of BasicSwitch. This means that a CiscoSwitch can be used anywhere a BasicSwitch is expected. So consider that you have a Rack with many switches and you want to enable the same port an all switches in the rack. Here is your Rack class:
class Rack {
protected $switches;
public function addSwitch(BasicSwitch $switch) {
$this->switches[] = $switch;
}
public function enable_ports($port) {
foreach($this->switches as $switch) {
$switch->enable_port($port);
}
}
}
If you type hint on the Abstract class (BasicSwitch) and not on the implementation you can be sure that any switch inside the rack can enable and disable its ports. You really don't care which switch it is. You just know that it can do the job.
This is what code on an interface and not on implementation is all about. This way your code is open for extension but closed for modification. You can create as many switch types as you want but you will be sure that the Rack class will continue to work.

PHP Static v Singleton class - ConnectionFactory explained

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.

PHP: How to access object inside class

I have a language class with public data members:
class language {
public $error = "There was an error";
}
Then I have many different classes that uses this class. How can I access this class from within other classes? You could of course instantiate an object of it inside all the classes that uses it, but I suppose that would drastically decrease the performance, if I were to do that with multiple classes.
I do only need one object, since I don't change them anyway. So, I've done
$language = new language();
class name {
private $language;
public function __construct() {
global $language;
$this->language = $language;
}
public function method() {
mysql_query(...) or die($this->language->error);
}
}
Is this a good way to do it? Now I have to instantiate it in every "mother" script. And I suppose by doing __construct() I'm only passing a refrence, since I don't use the clone word?
Basically your language object is a dependency of your other objects. There are a number of factors you need to consider:
- performance (how wise it is to instantiate a new language object each time you need it, or whether that is even possible)
- testing - how you could test your classes if each one has a hard-coded dependency on your language class
- maintainability/readability.
There are various different solutions to the problem. The one that seems to be most in fashion in the PHP community is the Dependency Injection Container. This can be a good solution if you are in a greenfield situation.
A good article on the general subject is one by Martin Fowler (who else?).
EDIT: To explain a bit more the article deals with the Inversion of Control principle. I won't explain it in depth as I don't think I could do it as well as Martin Fowler amongst others but the nub of it is that your classes do not manage their own dependencies; that is done elsewhere (hence the name Inversion of Control). There are broadly two different ways of doing it - Dependency Injection (which may or may not involve a Container) and Service Locator. This section of Martin Fowler's article deals with some of the differences between the two.
I do only need one object
This is the Singleton pattern.
Here is a quick example of a way to have only one instance of your Language class:
class Language {
public $error = "text";
private static $instance = null;
public static function getInstance() {
if (self::$instance == null)
self::$instance = new self();
return self::$instance;
}
private function __construct() {}
}
$lang = Language::getInstance();
$text = $lang->error;
You can also use dependency injection:
interface ILanguage {
public function getError();
}
class Language implements ILanguage {
private $error = "error";
public function getError() {
return $this->error;
}
}
class name {
private $language;
public function __construct(ILanguage $lang) {
$this->language = $lang;
}
public function method() {
mysql_query(...) or die($this->language->getError());
}
}
$language = new Language();
$n = new name($language);
This example of dependency injection is called constructor injection.
Instantiate the Language object in the constructor of your class:
public function __construct() {
$this->language = new Language();
}
If you do not want to have instances of this class, consider making its properties and methods static:
class language {
static public $error = "There was an error";
}
then use them statically:
$error = language::$error;
Instead of using global variable, you could pass it via constructor.
public function __construct($language) {
$this->language = $language;
}

Registry pattern and lazy instantiation of registered objects

Let's imagine that we have Registry pattern...
<?php
class Registry
{
private static $objects = array();
private static $instance = null;
public static function getInstance() {
if (self::$instance == null) {
self::$instance = new Registry();
}
return self::$instance;
}
protected function _get($key) {
return ($this->objects[$key]) ? $this->objects[$key] : null;
}
protected function _set($key, $val) {
$this->objects[$key] = $val;
}
public static function get($key) {
return self::getInstance()->_get($key);
}
public static function set($key, $object) {
return self::getInstance()->_set($key, $object);
}
}
?>
Using this realization is really easy...
<?
Registry::set('db', $db_client);
Registry::set('redis', $redis_client);
//Using registered objects is really easy
Registry::get('db')->query("...");
Registry::get('redis')->get("...");
?>
But as you can see, we're adding instances into registry even if we don't need them (yes, it's all about performance).
So, the question is... How to modify Registry pattern to be able to do lazy instantiation?
Here is what I'm looking for...
<?
class Registry
{
private static $objects = array();
private static $instance = null;
public static function getInstance() {
if (self::$instance == null) {
self::$instance = new Registry();
}
return self::$instance;
}
protected function _db() {
if (!$this->objects['db']) {
$this->objects['db'] = new DatabaseAdapter(DB_HOST, DB_NAME, DB_USER, DB_PASSWORD);
}
return $this->objects['db'];
}
protected function _redis() {
if (!$this->objects['redis']) {
$this->objects['redis'] = new Redis(REDIS_HOST, REDIS_DB, REDIS_USER, REDIS_PASSWORD);
}
return $this->objects['redis'];
}
public static function db() {
return self::getInstance()->_db();
}
public static function redis() {
return self::getInstance()->_redis();
}
}
?>
As you can see, DatabaseAdapter() or Redis() will be created only in we'll request them. Everything seems to be ok, but as you can see it's not a standalone class because _db(), _redis() methods contains connection constants etc.
How to avoid it? How can I define registry method within registry class to separate Registy class and objects inside it?
I'm really sorry about my English, but I hope it is clear for you.
Thank you.
PS: All code above was written 1 min. ago and wasn't tested.
If you use global constants you will always have a dependency on the global scope. It doesnt matter where it is. Also, even if you do not use constants, you still have the dependency on the Database class inside the Registry. If you want to dissolve those dependencies, you could use Factory methods on the to be created classes:
public function get($service)
{
if( !this->_data[$service] ) {
// requires PHP 5.2.3
this->_data[$service] = call_user_func($service .'::create');
}
return this->_data[$service];
}
So if you do get('DB'), the code would try to call the static DB::create() method inside the class you intend to create. But like I said, if you use global Constants for the configuration, you would just move the problem into another class.
Your db class could look like this:
class DB
{
protected static $_config;
public static setConfig(array $config)
{
self::_config = $config;
}
public static create()
{
return new self(
self::config['host'],
self::config['db'],
self::config['user'],
self::config['pass']);
}
}
The configuration can be stored inside an external configuration file, which you load and set to the DB class during bootstrap, e.g.
DB::setConfig(parse_ini_file('/path/to/db-config.ini'));
The disadvantage of this is, you have to add create() methods all over the place and all classes must be able to store their own configuration. You could centralize these responsibilities into a Builder pattern. But if you do this, you are half way to implementing an IoC Container anyways, so check out the following resources:
Fabien Potencier: What is Dependency Injection
Martin Fowler: Inversion of Control Containers and the Dependency Injection pattern
Design pattern – Inversion of control and Dependency injection
Note: You are using a "static" modifier for $objects - as you are working with an instance, this is probaby not necessary.
How can I define registry method within registry class to separate Registy class and objects inside it?
They are always separate: Each object inside the registry class is just a reference to the (independent) object. But if this question is about including the appropriate class definition (?) you may use the class_exists() function to load the class as soon as required.
BurninLeo

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

Categories