PHP Don't allow object to instantiate more than once - php

I have an abstract class that is inherited by a number of other classes. I'd like to have it so that instead of re-instantiating (__construct()) the same class each time, to have it only initialize once, and utilize the properties of the previously inherited classes.
I'm using this in my construct:
function __construct() {
self::$_instance =& $this;
if (!empty(self::$_instance)) {
foreach (self::$_instance as $key => $class) {
$this->$key = $class;
}
}
}
This works - sort of, I'm able to get the properties and re-assign them, but within this, I also want to call some other classes, but only one time.
Any suggestions for a better way to go about doing this?

Thats a Singleton construct:
class MyClass {
private static $instance = null;
private final function __construct() {
//
}
private final function __clone() { }
public final function __sleep() {
throw new Exception('Serializing of Singletons is not allowed');
}
public static function getInstance() {
if (self::$instance === null) self::$instance = new self();
return self::$instance;
}
}
I made the constructor and __clone() private final to hinder people from cloning and directly instanciating it. You can get the Singleton instance via MyClass::getInstance()
If you want an abstract base-singleton class have a look at this: https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/system/SingletonFactory.class.php

You're referring to the Singleton pattern:
class Foo {
private static $instance;
private function __construct() {
}
public static function getInstance() {
if (!isset(static::$instance)) {
static::$instance = new static();
}
return static::$instance;
}
}

Related

PHP syntax for static attribute of attribute

I have implemented a singleton pattern class, and who can be used in another classes like this :
class myClass {
private $attr;
public function __construct() {
$this->attr = Singleton::getInstance;
echo $this->attr::$sngtAttr; // Throw an error
// witch syntax use whithout pass by a temp var ?
}
}
Is $sngtAttr a static property?
If not, then just:
echo $this->attr->sngtAttr; instead of echo $this->attr::$sngtAttr;
will do it.
Otherwise since is static:
echo Singleton::$sngtAttr;
What is your question exactly ?
This is how you do a singleton :
<?php
class ASingletonClass
{
// Class unique instance. You can put it as a static class member if
// if you need to use it somewhere else than in yout getInstance
// method, and if not, you can just put it as a static variable in
// the getInstance method.
protected static $instance;
// Constructor has to be protected so child classes don't get a new
// default constructor which would automatically be public.
protected final function __construct()
{
// ...
}
public static function getInstance()
{
if( ! isset(self::$instance)) {
self::$instance = new self;
}
return self::$instance;
}
// OR :
public static function getInstance()
{
static $instance;
if( ! isset($instance)) {
$instance = new self;
}
return $instance;
// In that case you can delete the static member $instance.
}
public function __clone()
{
trigger_error('Cloning a singleton is not allowed.', E_USER_ERROR);
}
}
?>
Also don't forget the () when you call getInstance, it's a method, not a member.

Instance as a static class property

Is it possible to declare an instance of a class as a property in PHP?
Basically what I want to achieve is:
abstract class ClassA()
{
static $property = new ClassB();
}
Well, I know I can't do that, but is there any workaround beside always doing something like this:
if (!isset(ClassA::$property)) ClassA::$property = new ClassB();
you can use a singleton like implementation:
<?php
class ClassA {
private static $instance;
public static function getInstance() {
if (!isset(self::$instance)) {
self::$instance = new ClassB();
}
return self::$instance;
}
}
?>
then you can reference the instance with:
ClassA::getInstance()->someClassBMethod();
An alternative solution, a static constructor, is something along the lines of
<?php
abstract class ClassA {
static $property;
public static function init() {
self::$property = new ClassB();
}
} ClassA::init();
?>
Please note that the class doesn't have to be abstract for this to work.
See also How to initialize static variables and https://stackoverflow.com/a/3313137/118153.
This is a few years old, but I just ran into a issue where I have a base class
class GeneralObject
{
protected static $_instance;
public static function getInstance()
{
$class = get_called_class();
if(!isset(self::$_instance))
{
self::$_instance = new $class;
}
return self::$_instance;
}
}
That has a Child Class
class Master extends GeneralObject
{
}
And another Child class
class Customer extends Master
{
}
But when I try to call
$master = Master::getInstance();
$customer = Customer::getInstance();
then $master will be Master as expected, but $customer will be Master because php uses the GeneralObject::$_instance for both Master and Customer
The only way I could achieve what I want was to change the GeneralObject::$_instance to be an array and adjust the getInstance() method.
class GeneralObject
{
protected static $_instance = array();
public static function getInstance()
{
$class = get_called_class();
if(!isset(self::$_instance[$class]))
{
self::$_instance[$class] = new $class;
}
return self::$_instance[$class];
}
}
I hope this helps someone else out there. Took me a few hours to debug what was going on.

How can I create a singleton in PHP?

I'm using PDT and Aptana on Eclipse Indigo with PHP 5.3 and I want to create a singleton in a class.
By singleton, I mean I want to just have one instance of that object, and for other objects or classes to get that single instance via a function that returns that object (so this would mean I'm trying to create an object within the class that defines that object, ie: creating objA within the class objA)
I understand you can't just go a head and do this:
public $object = new Object();
with in a class definition, you have to define it in the constructor.
How can I go ahead and do this? I'm coming from Java, so it could be I'm confusing some basic stuff. Any help is greatly appreciated. Here's the code:
<?php
class Fetcher{
private static $fetcher = new Fetcher(); //this is where I get the unexpected "new" error
static function getFetcherInstance(){
return $this->$fetcher;
}
}
?>
Solved! Thanks for all the help guys!
try this:
<?php
class myclass{
private static $_instance = null;
public static function getInstance() {
if (self::$_instance === null) {
self::$_instance = new myclass();
}
return self::$_instance;
}
}
?>
and call it with:
<?php
$obj = myclass::getInstace();
?>
You cannot assign a class property in PHP like that. It must be a scalar, or array value, or the property must be set in a method call.
protected static $fetcher;
static function getFetcherInstance(){
if (!self::$fetcher) {
self::$fetcher = new Fetcher();
}
return self::$fetcher;
}
Also, notice that I did not use $this->, as that only works for object instances. To work with static values you need to use self:: when working within the class scope.
You might want to just read common design patterns on the php site. There are pretty good examples with good documentation:
http://www.php.net/manual/en/language.oop5.patterns.php
Else, a singleton is simply a method that returns one single instance of itself:
class MySingletonClass {
private static $mySingleton;
public function getInstance(){
if(MySingletonClass::$mySingleton == NULL){
MySingletonClass::$mySingleton = new MySingletonClass();
}
return MySingletonClass::$mySingleton;
}
}
Building on #periklis answer you might want separate singletons for different application scopes. For example, lets say you want a singleton of a database connection - fine. But what if you have TWO databases you need to connect too?
<?php
class Singleton
{
private static $instances = array();
public static function getInstance($name = 'default')
{
if ( ! isset(static::$instances[$name]))
{
static::$instances[$name] = new static();
}
return static::$instances[$name];
}
}
Class DB extends Singleton {}
$db_one = DB::getInstance('mysql');
$db_two = DB::getInstance('pgsql');
Alse define __clone method
class Fetcher {
protected static $instance;
private function __construct() {
/* something */
}
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new Fetcher();
}
return self::$instance;
}
private function __clone() {
/* if we want real singleton :) */
trigger_error('Cannot clone', E_USER_ERROR);
}
}
Basically implementing a singleton pattern means writing a class with a private constructor and a static method to build itself. Also check PHP site for it: http://www.php.net/manual/en/language.oop5.php and http://it2.php.net/manual/en/book.spl.php
class A {
protected $check;
private function __construct($args) {
}
static public function getSingleton($args) {
static $instance=null;
if (is_null($instance)) {
$instance=new A();
}
return $instance;
}
public function whoami() {
printf("%s\n",spl_object_hash($this));
}
}
$c=A::getSingleton("testarg");
$d=A::getSingleton("testarg");
$c->whoami(); // same object hash
$d->whoami(); // same object hash
$b= new A("otherargs"); // run time error
<?php
class MyObject {
private static $singleInstance;
private function __construct() {
if(!isset(self::$singleInstance)) {
self::$singleInstance = new MyObject;
}
}
public static function getSingleInstance() {
return self::$singleInstance;
}
}
?>
class MyClass {
private static $instance;
public static function getInstance() {
if( !isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
}
Then call get instance using
MyClass::getInstance();

Best practice to implement static class inheritance? (singleton)

From php manual:
[...] Static method calls are resolved at compile time.
When using an explicit class name the method is already identified completely and no
inheritance rules apply. If the call is done by self then self is translated to
the current class, that is the class the code belongs to.
Here also no inheritance rules apply [...]
..so im looking for a way to emulate the standard oop inheritance with static singleton.
Code explain better:
// Normal inheritance: my goal.
class Foo{
public function test(){
echo "Foo->test()\n";
}
}
class Bar extends Foo{
public function other_test()
{
echo "Bar->other_test()\n";
}
}
$obj = new Bar();
echo get_class($obj) . "\n";
$obj->test();
$obj->other_test();
/*
Output:
Bar
Foo->test()
Bar->other_test()
*/
// How i would love to do:
class Foo2{
public static function test2()
{
echo "Foo2::test2()\n";
}
// Singleton?
public static $_instance;
public static function get_instance()
{
if(is_null(self::$_instance))
{
self::$_instance = new self();
}
return self::$_instance;
}
}
class Bar2 extends Foo2{
public static function other_test2()
{
echo "Bar2::other_test2()\n";
}
}
$obj2 = Bar2::get_instance();
echo get_class($obj2) . "\n";
$obj2::test2();
$obj2::other_test2();
/*
Output:
Foo2
Foo2::test2()
Fatal error: Call to undefined method Foo2::other_test2()
*/
echo "\n-------\n";
// How im doing actually:
interface Foo3{
public static function get_instance();
}
class Bar3 implements Foo3{
// Singleton?
public static $_instance;
public static function get_instance()
{
if(is_null(self::$_instance))
{
self::$_instance = new self();
}
return self::$_instance;
}
public static function test3()
{
echo "Bar3::test3()\n";
}
public static function other_test3()
{
echo "Bar3::other_test3()\n";
}
}
$obj3 = Bar3::get_instance();
echo get_class($obj3) . "\n";
$obj3::test3();
$obj3::other_test3();
/*
Output:
Bar3
Foo3::test3()
Bar3::other_test3()
*/
The last 'way' force me to avoid the get_instance and static variables to be placed in the parent class, so I do not consider it as a best solution.. if for some reason my get_instance() function will change in the future, i dont want to edit all classes (inheritance! inheritance! we all want inheritance!)
So, is there a way or a best practices to solve this problem?
p.s: php5.3.2
The Singleton pattern in PHP is something like this:
class Singleton {
private static $instance = null;
// Constructor is private, so class cannot be instantiazed from outside
private function __construct() {
}
public static function getInstance() {
if (static::$instance === null) {
static::$instance = new Singleton();
}
return static::$instance;
}
public static function test() {
echo 'Singleton::test()';
}
public function __sleep() {
throw new Exception('Serialization is not alowed.');
}
public function __wakeup() {
throw new Exception('Serialization is not alowed.');
}
public function __clone() {
throw new Exception('Cloning is not alowed.');
}
}
For you is important that keyword static, then this:
class B extends Singleton {
public static function test2() {
echo 'B::test2()';
}
}
$b = B::getInstance();
B::test();
B::test2();
// Singleton::test()
// B::test()
Is this you looking for?

Can 2 singleton classes reference each other?

Why does this not work? Shouldn't each instance simply reference each other once?
class foo {
private static $instance;
private function __construct() {
$test = bar::get_instance();
}
public static function get_instance() {
if (empty(self::$instance)) {
self::$instance = new foo();
}
return self::$instance;
}
}
class bar {
private static $instance;
public function __construct() {
$test = foo::get_instance();
}
public static function get_instance() {
if (empty(self::$instance)) {
self::$instance = new bar();
}
return self::$instance;
}
}
$test = foo::get_instance();
You have what's known as a circular-dependency. A needs B to complete to construct, and B needs A to complete to construct. So it goes round and round forever.
Basically, what's happening is that self::$instance on each class doesn't get populated until new class() finishes. So in the constructor, you're calling the other getInstance. But every time you hit get_instance(), self::$instance is still null because the previous new never finsihed. And round and round you go. It will keep going until the end.
Instead, add it in after construction:
class foo {
private static $instance;
private function __construct() {
}
private function setBar(bar $bar) {
$this->bar = $bar;
}
public static function get_instance() {
if (empty(self::$instance)) {
self::$instance = new foo();
self::$instance->setBar(bar::get_instance());
}
return self::$instance;
}
}
class bar {
private static $instance;
public function __construct() {
}
private function setFoo(foo $foo) {
$this->foo = $foo;
}
public static function get_instance() {
if (empty(self::$instance)) {
self::$instance = new bar();
self::$instance->setFoo(foo::get_instance());
}
return self::$instance;
}
}
However, I would really suggest re-architecting your relationships and classes so that you Inject the Dependencies rather than making self-dependent singletons.
You will have an infinite recursion:
foo::get_instance(); -> foo constructor -> bar::get_instance() -> bar constructur -> foo::get_instance(); -> ...
Because neither constructor ever returns. Neither foo or bar instance is ever created, because they keep refernecing each other.
What you have here is a case of recursion. The call stack looks like this:
foo::get_instance()
foo::__construct()
bar::get_instance()
bar::__construct()
foo::get_instance()
foo::__construct()
...
The reason this is happening is that when foo::get_Instance is called from the bar constructor, it is still in the context of the initial call to foo::get_Instance and has not set the $instance value yet.
There are a number of ways you can address this, but I would first ask why you need to have them as members of each other.
If you don't need to, you would simply call foo::get_instance and bar::get_instance at the points that you need to access them.

Categories