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;
}
Related
I've been reading through Effective Java by Joshua Bloch. I also develop in PHP and I wanted to implement the builder pattern outlined in item 2, but PHP doesn't have inner classes. Is there any way to achieve this pattern in PHP, keeping the constructor for the product private?
Since PHP does not support inner classes, there must be a public method on the product class that creates an instance of it. Consider the following PHP classes:
<?php
class NutritionalFactsBuilder {
private $sodium;
private $fat;
private $carbo;
/**
* It is preferred to call NutritionalFacts::createBuilder
* to calling this constructor directly.
*/
function __construct($s) {
$this->sodium = $s;
}
function fat($f) {
$this->fat = $f;
return $this;
}
function carbo($c) {
$this->carbo = $c;
return $this;
}
function getSodium() {
return $this->sodium;
}
function getFat() {
return $this->fat;
}
function getCarbo() {
return $this->carbo;
}
function build() {
return new NutritionalFacts($this);
}
}
class NutritionalFacts {
private $sodium;
private $fat;
private $carbo;
static function createBuilder($s) {
return new NutritionalFactsBuilder($s);
}
/**
* It is preferred to call NutritionalFacts::createBuilder
* to calling this constructor directly.
*/
function __construct(NutritionalFactsBuilder $b) {
$this->sodium = $b->getSodium();
$this->fat = $b->getFat();
$this->carbo = $b->getCarbo();
}
}
echo '<pre>';
var_dump(NutritionalFacts::createBuilder(10)->fat(23)->carbo(1)->build());
echo '</pre>';
?>
Note that in the above example the constructor of NutritionalFacts is public. Due to the constraints of the language, however, having a public constructor is not at all bad. Since one must call the constructor with a NutritionalFactsBuilder, there are only a limited number of ways to instantiate NutritionalFacts. Let's compare them:
// NutritionalFacts Instantiation #0
$nfb = new NutritionalFactsBuilder(10);
$nfb = $nfb->fat(23)->carbo(1);
$nf0 = new NutritionalFacts($nfb);
// NutritionalFacts Instantiation #1
$nfb = new NutritionalFactsBuilder(10);
$nf1 = $nfb->fat(23)->carbo(1)->build();
// NutritionalFacts Instantiation #2
$nf2 = NutritionalFacts::createBuilder(10)->fat(23)->carbo(1)->build();
// NutritionalFacts Instantiation #3
// $nf3 = (new NutritionalFactsBuilder(10))->fat(23)->carbo(1)->build();
To leverage function chaining to its fullest extent, "NutritionalFacts Instantiation #2" is the preferred usage.
"NutritionalFacts Instantiation #3" shows another nuance of PHP syntax; one cannot chain a method on a newly instantiated object. Update: In PHP 5.4.0, there is now support for the syntax in "NutritionalFacts Instantiation #3." I haven't tested it yet though.
Making the Constructor Private
You could make the constructor private, but I wouldn't recommend it. If the constructor were made private, a public, static factory method would be necessary, as in the following code snippet. Looking at the below code, we might as well make the constructor public instead of introducing indirection just to make the constructor private.
class NutritionalFacts {
private $sodium;
private $fat;
private $carbo;
static function createBuilder($s) {
return new NutritionalFactsBuilder($s);
}
static function createNutritionalFacts($builder) {
return new NutritionalFacts($builder);
}
private function __construct($b) {
$this->sodium = $b->getSodium();
$this->fat = $b->getFat();
$this->carbo = $b->getCarbo();
}
}
Immutability is good and definitely something to strive for, this applies to PHP as it does to any other language no matter what. Immutability gives you certainty that you do not have to fear that the instance suddenly mutates without you knowing.
That being said, there is an easy way to implement the builder pattern to build immutable objects even without inner classes (although available now with PHP 7).
The first important building block is a common base class for the actual immutable class and the builder. This allows them to access each others properties. Something that is also known as friend classes or solvable through extended access modifiers in other languages, something PHP does not have. Note that the clone ability is restricted, it makes no sense to clone immutable objects but more about the protected modifier later.
abstract class NutritionalFactData {
protected $sodium = 0;
protected $fat = 0;
protected $carbo = 0;
protected function __clone() {}
}
The immutable class is straight forward with stupid example getters and the default constructor. Note the final modifier for the class itself and that it is not aware of the builder class at all.
final class NutritionalFacts extends NutritionalFactData {
public function getSodium() {
return $this->sodium;
}
public function getFat() {
return $this->fat;
}
public function getCarbo() {
return $this->carbo;
}
}
Now the actual builder implementation. Note how we operate directly on an instance of the immutable class and that we simply clone it when the build method is called. This ensures that later calls to the setters of the builder will not alter the instances that were previously built and ensures that no receiver of such an instance has to take care of the cloning on their own.
final class NutritionalFactBuilder extends NutritionalFactData {
private $nutritional_facts;
public function __construct() {
$this->nutritional_facts = new NutritionalFacts;
}
public function build() {
return clone $this->nutritional_facts;
}
public function setSodium($sodium) {
$this->nutritional_facts->sodium = $sodium;
return $this;
}
public function setFat($fat) {
$this->nutritional_facts->fat = $fat;
return $this;
}
public function setCarbo($carbo) {
$this->nutritional_facts->carbo = $carbo;
return $this;
}
}
For completeness a usage example:
var_dump(
(new NutritionalFactBuilder)
->setSodium(21)
->setFat(42)
->build()
);
Here is the runnable example.
I think it is obvious that we can now implement as many builder implementations as we like. Not really needed for this example but we can think of other constructs where many more properties are involved. Like the car example given on (the very bad) builder pattern article of Wikipedia. We might want to have pre-configured builders for known car categories.
abstract class CarParts {}
final class Car extends CarParts {}
abstract class CarBuilder extends CarParts {
abstract public function build(): Car;
}
final class CompactCarBuilder extends CarBuilder {}
final class SportsCarBuilder extends CarBuilder {}
final class RaceCarBuilder extends CarBuilder {}
In the Gang of Four description of the Builder pattern, you'll find no requirement for an inner class. The key feature is the aggregate relationship between the Director and Builder interface that provide a "blueprint" for putting together a series of Product implementations.
You can find lots of examples of the PHP Builder pattern here:
http://www.php5dp.com/category/design-patterns/builder/
Cheers,
Bill
Straight to the point:
I've got two singleton classes, both inheriting their singleton nature from a super-class. I initialize some properties on the first singleton, and then have the second singleton retrieve the instance of the first one. That instance, however, does not seem to be the one I initialized in the first place. Some example code might help to explain this:
First, the super-class, providing singleton nature (requires PHP 5.3 or greater):
class Singleton {
protected static $instance;
protected function __construct() { }
final private function __clone() { }
public static function getInstance() {
if (!(static::$instance instanceof static)) {
static::$instance = new static();
}
return static::$instance;
}
}
Then we've got the the first singleton carrying a value:
require_once('Singleton.php');
class SingletonA extends Singleton {
protected $value;
public function SingletonA() {
$this->value = false;
}
public function getValue() {
return $this->value;
}
public function setValue($value) {
$this->value = $value;
}
}
Then the second singleton that references the first singleton:
require_once('Singleton.php');
require_once('SingletonA.php');
class SingletonB extends Singleton {
public function getValue() {
return SingletonA::getInstance()->getValue();
}
}
Now for the test that shows how this fails:
require_once('SingletonA.php');
require_once('SingletonB.php');
SingletonA::getInstance()->setValue(true);
echo (SingletonA::getInstance()->getValue()) ? "true\n" : "false\n";
echo (SingletonB::getInstance()->getValue()) ? "true\n" : "false\n";
The test yields the following output:
true
false
Clearly, the SingletonA instance that the test code references is not the same instance that the SingletonB instance references. In short, SingletonA is not as single as I need it to be. How is this possible? And what magic can I wield to remedy this behaviour, giving me a true singleton?
Try using isset rather than instanceof:
class Singleton {
protected static $instances;
protected function __construct() { }
final private function __clone() { }
public static function getInstance() {
$class = get_called_class();
if (!isset(self::$instances[$class])) {
self::$instances[$class] = new $class;
}
return self::$instances[$class];
}
}
SingletonA and SingletonB are different classes. Although they inherit from the same class, they are separate classes and so they have different static instances.
If you change your code to get 2 instances of SingletonA or 2 instances of SingletonB, you will see the behavior you expect. But because they are different classes, they are not the same singleton.
I'm pretty sure it's because you are using static methods, which are not instanced.
Let's talk OO. :)
SingletonA and SingletonB are of type Singleton
thus it can be said:
SingletonA is Singleton
and
SingletonB is Singleton
i.e. they're both Singleton
The expected meaning of Singleton means there can be only one. Many people from an OO background using your code will be confused.
Usually, implementation of Singleton would be on a per class basis because most OO languages will not be bent to allow the intent of what you are proposing.
That PHP might do (via get_called_class() magic) doesn't mean it should.
I can absolutely accept that from a utilitarian point of view, the accepted answer looks good. Given the niftyness of the accepted answer, I'd propose a name change that doesn't conflict with "standard" Singleton implementation. From a strict OO point of view, one could never inherit from a Singleton, so it really needs a different name.
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
I have always used a Singleton class for a registry object in PHP. As all Singleton classes I think the main method looks like this:
class registry
{
public static function singleton()
{
if( !isset( self::$instance ) )
{
self::$instance = new registry();
}
return self::$instance;
}
public function doSomething()
{
echo 'something';
}
}
So whenever I need something of the registry class I use a function like this:
registry::singleton()->doSomethine();
Now I do not understand what the difference is between creating just a normal static function. Will it create a new object if I just use a normal static class.
class registry
{
public static function doSomething()
{
echo 'something';
}
}
Now I can just use:
registry::doSomethine();
Can someone explain to me what the function is of the singleton class. I really do not understand this.
A static function is a function that can be called without creating an object of a class.
registry::doSomething()
A Singleton is a design pattern, that should prevent the users of the class from creating more than one instance of a class. So, there is usually only one instance of a singleton class. A Singleton's constructor should be declared private and have a static method providing a single instance-object:
class Singleton
{
private Singleton()
{
}
private static var $instance = null;
public static getInstance()
{
if(self::$instance == null)
self::$instance = new Singleton();
return self::$instance;
}
}
For more information see http://en.wikipedia.org/wiki/Singleton_pattern
P.S: Sorry for my bad PHP, the syntax may not be 100% correct, but you should roughly understand what I mean in terms of OOP.
The fact that the Singleton is a design-pattern that restricts instantiation of a class to one single object, it is possible to do some stuff that is slightly more difficult with a static class:
Lazy initialization
Replace implementation internally by sub-classing the Factory
Manage via configuration
However, there are several drawbacks to singletons, so it is better in general to use patterns such as Factory as you get additional benefits such as decoupling.
UPDATE: Rephrasing the question to ask, 'are there too many' static methods (I realize that right now there are only 4 but I originally started with 2) in this class structure? If so, any suggestions on how to refactor these classes to use some sort of Finder class so that I can remove the static functions from the Model classes?
I have the following abstract class:
abstract class LP_Model_Abstract
{
protected static $_collectionClass = 'LP_Model_Collection';
protected $_row = null;
protected $_data = array();
public function __construct($row = null)
{
$this->_row = $row;
}
public function __get($key)
{
if(method_exists($this, '_get' . ucfirst($key)))
{
$method = '_get' . ucfirst($key);
return $this->$method();
}
elseif(isset($this->_row->$key))
{
return $this->_row->$key;
}
else
{
foreach($this->_data as $gateway)
{
if(isset($gateway->$key))
{
return $gateway->$key;
}
}
}
}
public function __set($key, $val)
{
if(method_exists($this, '_set' . ucfirst($key)))
{
$method = '_set' . ucfirst($key);
return $this->$method($val);
}
elseif(isset($this->_row->$key))
{
$this->_row->$key = $val;
return $this->_row->$key;
}
else
{
foreach($this->_data as $gateway)
{
if(isset($this->_data[$gateway]->$key))
{
$this->_data[$gateway]->$key = $val;
return $this->_data[$gateway]->$key;
}
}
}
}
public function __isset($key)
{
return isset($this->_row->$key);
}
public function save()
{
$this->_row->save();
}
abstract public static function get($params);
abstract public static function getCollection($params = null);
abstract public static function create($params);
}
And then this class which provides additional functionality for class table inheritance schemes (where type is important in determining additional functionality in a factory fashion):
abstract class LP_Model_Factory_Abstract extends LP_Model_Abstract
{
protected static $_collectionClass = 'LP_Model_Collection_Factory';
abstract public static function factory($row);
}
These ultimately result in the following type of class declaration:
class Model_Artifact extends LP_Model_Factory_Abstract
{
protected static $_artifactGateway = 'Model_Table_Artifact';
public static function create($params)
{
}
public static function get($params)
{
$gateway = new self::$_artifactGateway();
$row = $gateway->fetchArtifact($params);
return self::factory($row);
}
public static function getCollection($params = null)
{
$gateway = new self::$_artifactGateway();
$rowset = $gateway->fetchArtifacts($params);
$data = array(
'data' => $rowset,
'modelClass' => __CLASS__
);
return new self::$_collectionClass($data);
}
public static function factory($row)
{
$class = 'Model_Artifact_' . $row->fileType;
}
}
When do you know that you have too many static methods in a class? And how would you refactor the existing design so that the static methods are perhaps encapsulated in some sort of Finder class?
I'd have to agree with Brubaker and add that to my thinking it isn't the number of methods so much as the functionality of said methods. If you start thinking that your class has to many methods (static or otherwise) then you might find they can be re-grouped and refactored into a more intuitive architecture.
The first indicator I use when determining if I have to many static methods is if the methods functionality is not stateless. If the static methods change the state of the object they reside in, they probably shouldn't be static.
I agree with BaileyP and I'll add my couple of pennies:
I always work with the idea that a class should have a single reason for existing; it should have one job that it does, and it should do it well. After deciding that, and figuring out what the interface to that class should be, I go through and mark any functions that don't change the state of an instance of the class as static.
If you want to build reusable and testable code, you should avoid static methods altogether. Code which calls static methods (or constructors of non-data-like classes) cannot be tested in isolation.
Yes, you will have to pass around alot more objects if you eliminate static methods. This is not necessarily a bad thing. It forces you to think about the boundaries and cooperation between your components in a disciplined way.
Personally I find that any number of static methods are a sign of trouble. If your class has instance methods and static methods, then most likely you could split the class into two separate entities and change the static methods to instance methods.
Think of a class as a special kind of object, with the distinctive property that it is global by nature. Since it's a global variable, it implies a very strong level of coupling, so you would want to reduce any references to it. Static members will need to be referred, meaning that your code will get a strong level of coupling to the class.
I'll throw in my 2 cents.
First of all, I'll agree that setting some sort of arbitrary limit is not helpful, such as "Once I have more than 10 statics in a class that's too many!". Refactor when it makes sense but don't start doing it just because you've hit some imaginary boundary.
I wouldn't 100% agree with Brubaker's comment about stateful vs. stateless - I think the issue is more about classes vs instances. Because a static method can change the value of another static property which is a stateful change.
So, think of it like this - if the method/property is of or pertaining to the class, then it should probably be static. If the method/property is of or pertaining to an instance of the class, it should not be static.