What are good reasons to use static methods in PHP? - php

Does anyone have any good examples of using static methods instead of dynamic?

Singleton:
class SingletonClass {
private static $instance;
private function __construct() { }
public function __clone() {
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
public static function init() {
if (!isset(self::$instance)) {
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
// other public, dynamic methods for singleton
}
$singleton = SingletonClass::init();
Track number of instances:
class CountMe {
public static $instances = 0;
public function __construct() {
CountMe::$instances++;
}
public function __destruct() {
CountMe::$instances--;
}
}
$a = new CountMe();
$b = new CountMe();
echo CountMe::$instances; // outputs 2

When you don't need access to instance members.

A database connection would be a good use for a static function. You dont need direct access to an entire DB object, you just need access to the connection resource. So you can call
$connection = new DatabaseConnection();
StaticClass::setDatabase($connection);
$result = StaticClass::getDatabaseConnection()->query();
But if you need access to the class for storage later or multiple instances of the same object, then you would not want to go static.
Your class also now lives in a global scope, so you can access it from any class, in any scope, anywhere in your codebase.
function getUsers()
{
$users = StaticClass::getDatabaseConnection()->query('SELECT * FROM users');
}

In a less code-oriented nature, here's how I define static methods (I'll use a bank as an example):
If you had a bank class and would like to open a new bank you would use:
$b = new Bank;
Now let's say you wanted to add a new employee to this bank. Simply call:
$b->addEmployee( 'Person' );
Since you are applying the action to the bank you created and not the company that owns the bank as a whole you use a member method. Now let's say the company's traded some assets and made money. To update their total money you would call this:
Bank::addToCompanyBalance( 1000000 );
Notice how since the action wasn't just being applied to the bank we created, we used a static method instead.
Granted this example is very oversimplified, but I like the analogy. In a more programmatic sense case, static members are good for:
Singletons
class Singleton
private static $instance;
private function __construct() {}
private function __clone() {}
public static function getInstance() {
if( !isset( self::$instance ) ) self::$instance = new IamOne;
return( self::$instance );
}
}
Creating classes that may fail
Ex. A file handler class may not always want to create a new object (Say the file passed doesn't exist or can't be opened).
With abstract classes
Some classes may not wish to have instances (Ex. A router that interprets a user's request). Abstract classes, however, can be called statically and therefore can use static methods.

Example: Use static methods to create instances of an object which might perhaps take different arguments.
Class DBConnection
{
public static function createFromConfiguration(Configuration $config)
{
$conn = new DBConnection();
$conn->setDsn($config->getDBDsn());
$conn->setUser($config->getDBUser());
$conn->setPassword($config->getDBPass());
return $conn;
}
public static function newConnection($dsn, $user, $password)
{
$conn = new DBConnection();
$conn->setDsn($dsn);
$conn->setUser($user);
$conn->setPassword($password);
return $conn;
}
}

Related

Singleton access / PHP Magic method __toString/ printing a static object

what I'm trying to achieve (PHP 5.3) is to have an accessor to my representation of, for example, the HTML Body of a page. Instead of echoing everything directly it should be added to an array of entries in that singleton. Example: myBodyClass::add('<h1>Title</h1>');
add() is declared as public static function add($strEntry) {}
Now should I just add them to a static array $entries like self::$entries[] = $strEntry; (class VersionB) or should I use an instance like self::getInstance()->entries[] = $strEntry;? (class VersionA) (whereby getInstance() would of course instanciate ´...new self;´ if necessary)
I don't quite understand the difference yet, I'm afraid.
The second part of my question is how to print the object. The PHP manual is a bit thin about why __toString() cannot be static - but then again I would understand a parser to have a problem distinguishing echo myBodyClass from a constant (so is that the reason?)
Ideally I would like to call add() as often as needed to add all parts of the body, and then use something like echo myHeaderClass, myBodyClass, myFooterClass; at the end of the script, which should invoke the __toString() methods within the classes.
Thanks for pointing me into the correct direction.
Code Example
class VersionA
{
private static $instance = null;
private $entries = array();
private final function __construct(){}
private final function __clone(){}
private static final function getInstance()
{
if (self::$instance === null) :
self::$instance = new self;
endif;
return self::$instance;
}
public static function add($sString)
{
self::getInstance()->entries[] = $sString;
}
public static function getHtml()
{
return implode("\r\n", self::getInstance()->entries);
}
}
class VersionB
{
private static $entries = array();
private final function __construct(){}
private final function __clone(){}
public static function add($sString)
{
self::$entries[] = $sString;
}
public static function getHtml()
{
return implode("\r\n", self::$entries);
}
}
(Copied from comments, as requested by OP...)
You're missing the point of a singleton. There is a difference between a singleton object and a static class. If you want to use methods that act on an object (like __toString()), then you need it to be an object; a static class isn't good enough. If you want to avoid calling getInstance all the time, then set a variable to the object, and pass it around everywhere like you would with other objects, per the Dependency Injection pattern. That would probably be best practice advice anyway.
The thing with a static class is that it isn't really OOP; it's just a bunch of global functions with a shared class name. One may as well use plain functions with a namespace declaration.
But the main reason for using a genuine singleton is swappability. Assuming you follow my advice above and create a single reference to the object that you pass around your code, it becomes a lot easier to swap in an alternative object since you don't have the hard-coded class name being referenced all over the place. This makes it a lot easier to write decent unit tests for your code that uses the class.
Hope that helps.
You should probably not use a static add method.
The idea of a singleton is that you create a single instance of a class so that external objects can interact with that instance. That means that your add method should not be static.
You could do something like:
class MyBodyClass
{
protected $entries = array();
protected $instance;
public static function getInstance()
{
if (is_null($this->instance)) {
$this->instance = new self();
}
return $this->instance;
}
private function __construct() {}
public function add($strEntry)
{
$this->entires[] = $strEntry;
}
}
And call it like this:
MyBodyClass::getInstance()->add('<h1>blah</h1>');
Something like this should work:
class MySingleton
{
public static function getInstance()
{
static $inst = null;
if ($inst === null) {
$inst = new MySingleton();
}
return $inst;
}
private function __construct() { }
public static function add() {}
public function __toString() {
echo 'Something';
}
}
$body = MySingleton::getInstance();
$body::add('Something');
echo $body;

Static Method vs Static Instances

Consider the following code below, I've been thought by Lynda.com
to create a database class like this, my question is why not create
a static method for the database entirely instead of storing an
instance into a static property?
<?php
class Database {
private $conn;
private static $init;
public function __construct() {
$this->conn = new mysqli('localhost','root','root','mydb');
}
public static function getInstance() {
self::$init = new self();
return self::$init;
}
}
$db = Database::getInstance();
?>
If you want to use singleton you should to protect __construct()
class DB
{
private static $instance;
private function __construct($args)
{
// do some
}
public static function getInstance()
{
// get instance
}
}
$query = 'SELECT etc...';
$stmt = DB::getInstance()->prepare($query);
I use this pattern in DB class. But if you have more than 1 connection you should NOT! use singleton.
My guess is that code you posted was intended to be the following because it looks like it was intended to be a singleton. I've only changed the getInstance() method.
class Database {
private $conn;
private static $init;
public function __construct() {
$this->conn = new mysqli('localhost','root','root','mydb');
}
public static function getInstance() {
if (is_null(self::$init)) {
self::$init = new self();
}
return self::$init;
}
}
$db = Database::getInstance();
I think this should clear up the confusion of why a static instance variable is used.
If this wasn't intended to be a singleton, then your question of "why didn't they just use a static method" should have the answer "they should have".
Just to clarify, $db is a Database object, which is instantiated by calling static method getInstance().
why not create a static method for the database entirely?
A static method is defined inside a class, however it can be called without having to instantiate the class. In other words, a static method belongs to the class, since in can be called without instantiating an object.
You can add methods to the Database class to interact with the database as you deem necessary.

PHP maintain class state

I'd like to have a library class that maintains state across the same request. My use case is that I want to pass 'messages' to the class, and then call them at any time from a view. Messages can be added from any part of the application.
I had originally done this via static methods, which worked fine. However, as part of the lib, I also need to call __construct and __destruct(), which can't be done on a static class.
Here's a very simple example of what I am trying to do:
class Messages
{
private static $messages = array();
public function __construct()
{
// do something
}
public function __destruct()
{
// do something else
}
public static function add($message)
{
self::$messages[] = $message;
}
public static function get()
{
return self::$messages;
}
}
I can then add messages anywhere in my code by doing
Messages::add('a new message');
I'd like to avoid using static if at all possible (testability). I have looked at DI, but it doesn't seem appropriate, unless I'm missing something.
I could create a class (non-static) instead, but how do I then ensure that all messages are written to the same object - so that I can retrieve them all later?
What's the best way to tackle this?
I looks like you could benefit from using the Singleton pattern - it is designed for an object that must have only one instance throughout a request. Basically, you create a private constructor and a static method to retrieve the sole instance. Here is an example of a singleton that will do what you describe.
<?php
class Messages
{
private static $_instance;
private $_messages = array();
private function __construct() {
// Initialize
}
static public function instance() {
if (! self::$_instance) {
self::$_instance = new self();
}
return self::$_instance;
}
public function add_message( $msg ) {
$this->_messages[] = $message;
}
public function get_messages() {
return $this->_messages;
}
private function __destruct() {
// Tear-down
}
}
$my_messages = Messages::instance();
$my_messages->add_message( 'How now, brown cow?' );
// ...
$your_messages = Messages::instance();
$msgs = $your_messages->get_messages();
echo $your_messages[0]; // Prints, "How now, brown cow?"
Since the constructor is private, you can only create a Messages object from within a method of the object itself. Since you have a static method, instance(), you can create a new Messages instance from there. However, if an instance already exists, you want to return that instance.
Basically, a singleton is the gatekeeper to its own instance, and it stubbornly refuses to ever let more than one instance of itself exist.
Sounds like you are wanting to do a Singleton class. This will create an instance in one class and allow you to access that same instance in another class. Check out http://www.developertutorials.com/tutorials/php/php-singleton-design-pattern-050729-1050/ for more information.
How about making it a singleton class?
class Messages
{
// singleton instance of Messages
private static $instance;
public function __construct() { ... }
public static function getInstance()
{
if (!self::$instance)
{
self::$instance = new Messages();
}
return self::$instance;
}
}
This would ensure that all your messages get written to the same object, and also allow you to call __construct and __destruct
What you need is the Singleton pattern:
final class Singleton {
// static variable to store the instance
private static $instance = NULL;
// disable normal class constructing
private function __construct() {}
// instead of using the normal way to construct the class you'll use this method
public static function getInstance() {
if (NULL === self::$instance) {
self::$instance = new self;
}
return self::$instance;
}
// disable external cloning of the object
private function __clone() {}
}
// get the instance across some of your scripts
$singleton = Singleton::getInstance();
Sounds a bit like you want a singleton, although as an anti-pattern I'd avoid it.
You could do a full static class where every static member calls a self::_isBuilt(); method to do your construct elements. Destruct is a little trickier.
The best case for your needs might be a normal (non-static) class that you build right away and then access from a global... not super neat, but allows construct/destruct and members, and your statics to use $this which could be helpful. If you don't like the global variable, you could also wrap it in a method (a trick used in JS a fair bit) but it's not really any neater.
As a normal global class:
$myClass=new myClass();
//Access anywhere as:
globals['myClass']->myFunction(..);
Wrapped in a function
function my_class() {
static $var=null;
if ($var===null) $var=new myClass();
return $var;
}
//Access anywhere as:
my_class()->myFunction(..);

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

OO PHP where to reference singleton class?

I am going to use singleton classes to manage both DB connections and references to application settings.
It seems a little messy to have to use the following code in every method in order to access the db class.
$db = DB::getInstance();
Is there a more efficient way of going about it?
Any advice appreciated.
Thanks
I often use the Registry pattern, where this behavior occurs as well. I always set a instance variable in the constructor of my models to point to the Registry entry;
class Registry {
private static $_instance;
private $_registry;
private function __construct() {
$_registry = array();
}
public static function getInstance() {
if (!Registry::$_instance) {
Registry::$_instance = new Registry();
}
return Registry::$_instance;
}
public function add($key, &$entry) {
$this->_registry[$key] = &$entry;
}
public function &get($key) {
return $this->_registry[$key];
}
public function has($key) {
return ($this->get($key) !== null);
}
}
Model example;
class MyModel {
private $_db;
public function __construct() {
$this->_db = Registry::getInstance()->get('dbKey');
}
/* Every function has now access to the DAL */
}
Instantiation example;
$dal = new Db(...);
Registry::getInstance()->add('dbKey', $dal);
...
$model = new MyModel();
$model->doDbStuff();
Another approach is to always pass the reference as a parameter to each constructor.
Of course I only use this behavior when most of the methods in my model use the reference, if only a few (one or two) methods have use of the reference, I call the Registry/Singleton like you showed.
It is not messy. This is an intended behavior of Singletons. And, actually, this is just one line of code. Do you wish to make it even more compact? :)
My preferred method is to create a Base class which all the classes that need db access descend from. Base calls the singleton(s) in its constructor. All its children call their parent constructor. e.g.:
class Base {
protected $db;
public function __construct(){
$this->db = DB::getInstance();
}
}
class Achild extends Base {
protected $var1;
public function __construct($arg){
parent::__construct();
$this->var1=$arg;
}
}
I know what you mean... hate that ::getInstance() stuff! So go and use static methods:
class DB {
private static $db;
public static function getInstance() {
if(!self::$db) {
self::$db = new DBconnector();
}
}
public static function query($query) {
return self::$db->query($query);
}
}
Usage is much nicer:
$result = DB::query('SELECT whatever;');
And if you use PHP 5.3 you can write a __callStatic similar to this, to forward all the method calls to the object:
public static function __callStatic($method, $args) {
call_user_func_array(array(self::$db, $method), $args);
}
And to make me happy, add an __autoloader so that you can access DB without any worries any time!

Categories