What is the point of using self::$_instance = new self() - php

I'm working on learning OOP PHP and have come across this:
//Store the single instance
private static $_instance;
/*
Get an instance of the database
#return database
*/
public static function getInstance () {
if (!self::$_instance) {
self::$_instance = new self();
}
return self::$_instance;
}
What is the point of setting $_instance to a new self()? I know that all this line is doing is creating a new instance of the class it's in but why would one need to do this? Is there any reason this would ever be needed? I don't ever even call it again in the class. Thanks for any help in advanced.

The idea is that whenever you call getInstance() throughout your code, you will always get the same instance.
This is useful in some cases where you only want to get access to the same object. Often objects like this might have a private constructor, which effectively forces you to always act on the same instance (also known as a singleton).
Generally people say 'Singletons are evil'. They are good to avoid because they can cause major design issues. In some cases they can still be a good idea though.

work example
class Singleton
{
public $data;
private static $instance = null;
public function __construct()
{
$this->data = rand();
}
public static function getInstance()
{
if (is_null(self::$instance))
self::$instance = new self;
return self::$instance;
}
//no clone
private function __clone() {}
//no serialize
private function __wakeup() {}
}
$singleton = Singleton::getInstance();
echo $singleton->data;
echo '<br>';
$singleton2 = Singleton::getInstance();
echo $singleton2->data;
echo '<br>';

This is the Singleton pattern.
It is used when you have an object that requires initialization and/or tear-down work and that work should be performed just once.
The instance cache forces there to only be one instance of the class, ever.

Related

Singleton pattern returns different objects

So I am in a big mess here. I can say that my questions are few. I tried to make a singleton pattern but it returns me two different objects. This is what I made (saw in another post) and tried to test it.
class Singleton
{
private static $instance = [];
public function __construct(){}
public function __clone(){}
public function __wakeup(){
throw new Exception("Cannot unserialize singleton");
}
public static function getInstance()
{
$class = get_called_class();
if(!isset(self::$instance[$class])){
self::$instance[$class] = new static();
}
return self::$instance[$class];
}
}
class Dog extends Singleton
{
public $name;
public function __construct($name)
{
$this->name = $name;
}
}
$dog = new Dog("Jorko");
$dog2 = new Dog("Peshko");
echo $dog->name; // returns "Jorko"
echo $dog2->name; // returns "Pesho"
I thought the second object ($dog2) should not be created and I would get $dog again. And why are we creating empty __constructor in the class Singleton? Also, why are we using this get_called_class? I mean according to php manual Gets the name of the class the static method is called in.. That is what it returns but isn't new static. I thought that new static do the same thing. I am in a real mess. I searched around the web but can't get it clear in my head. Thank you a lot!
Actually this is not correct. To implement the singleton pattern correct the constructor has to be protected to prevent the creation of an object with the new operator. The magic methods __clone and __wakeup should be private to prevent cloning and unserializing of the object.
If you set the accessibility on these methods like i said, you can get an instance of the singleton object by using the static method getInstance() which is there for that very reason.

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;

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(..);

PHP: If many objects use instance of the same object - what is an efficient way to pass it?

For example, my app is using instance of a User object, and different other objects have to access some attributes and methods. And these objects instantiate other objects, which in turn also have to access User. What's the best way to manage this? Pass User object as reference when I instantiate these new objects?
Here's example of how this is done now:
class App {
private $user;
private $controller;
public function __construct() {
$this->user = new User();
$this->controller = new Controller();
$this->controller->setUser(& $this->user);
}
}
Is this the right way to do it?
EDIT: Is there a way to make User instance a global var?
Just to make my suggestion in the comments to an answer
You can implement the singleton pattern
class User {
protected static $instance = null;
protected function __construct () { /* disable external instanciation */ }
private function __clone () { /* disable clone */ }
public static function getInstance () {
if (is_null(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
}
Here is something to read :)
http://en.wikipedia.org/wiki/Singleton_pattern
Is there a way to make User instance a global var?
It sounds like a singleton would be helpful:
class User
{
private static $instance;
private function __construct() { }
public function instance()
{
return self::$instance ? self::$instance : (self::$instance = new self());
}
}
$user = User::instance();
Basically anything that needs the user, can just call User::instance() instead of new User(). They will all be operating on the same instance of the object, so this is only applicable of the User object represents the same data throughout the duration of the script.
Update
With your comment "No, it's possible for one user to perform actions on other user," then this pattern is not applicable for every usage.
Sounds like you just need to pass the $user object along to anybody that needs it. (Of course, you could still use a singleton to represent the authenticated user.)

Protecting PHP classes from undesired instantiation?

I am working on a PHP library in which we will be supplying our clients with encrypted code. The code will include a main classes which they can instantiate that will handle license verification and expose methods for their use. The main class will instantiate several sub classes each contained in their own file. How can I prevent our clients from including the subclass files and instantiating the sub classes themselves for use? Is there a way to prevent a sub class from being instantiated except from our main class?
Wild guess, but use a Singleton for the main class, and factory/Singleton with dependency injection (of the main class) for all the subclasses. That way the subclasses won't even load without a valid reference to an instance of your primary class.
EDIT: Since this answer was accepted I've decided to provide an example, for the benefit of future readers. Also, don't forget to mark all of your classes as final.
Primary Class:
final class myPrimaryClass {
private static $instance = null;
private function __construct() {
// do something or not
return $this;
}
public static function getInstance() {
if (is_null(self::$instance) || !(self::$instance instanceof myPrimaryClass))
self::$instance = new myPrimaryClass;
return self::$instance;
}
}
Singleton Subclass:
final class mySingletonSubClass {
private static $instance = null;
private function __construct(myPrimaryClass $primaryClassInstanceRef) {
return $this;
}
public static function getInstance(myPrimaryClass $primaryClassInstanceRef) {
if (is_null(self::$instance) || !(self::$instance instanceof mySingletonSubClass))
self::$instance = new mySingletonSubClass($primaryClassInstanceRef);
return self::$instance;
}
}
Factory Subclass:
final class myFactorySubClass {
private function __construct(myPrimaryClass $primaryClassInstanceRef) {
return $this;
}
public static function getNewInstance(myPrimaryClass $primaryClassInstanceRef) {
return new myFactorySubClass($primaryClassInstanceRef);
}
}
Two notes about this example; first, of course I'm grossly oversimplifying the matter. Second, one neat trick you could employ is to modify the subclasses slightly so that the getInstance() methods do not always need to have an instance of the primary class passed as an argument after the first time. I'll provide an example here with the singleton class:
final class mySingletonSubClass {
private static $instance = null;
private static $classInstanceRef = null;
private function __construct(myPrimaryClass $primaryClassInstanceRef) {
return $this;
}
public static function getInstance(myPrimaryClass $primaryClassInstanceRef = null) {
if (!is_null($primaryClassInstanceRef))
self::$classInstanceRef = $primaryClassInstanceRef;
if (is_null(self::$instance) || !(self::$instance instanceof mySingletonSubClass))
self::$instance = new mySingletonSubClass(self::$classInstanceRef);
return self::$instance;
}
}
Please note, this relies heavily on PHP's type-hinting mechanism. As such, you should read the manual entry on it so you understand the nuances (e.g. default null).
I don't think there's a language-supported way, so it'll be down to tricks.
What you could do is add a secret argument to your private class's constructors, which is only known by your main class. If that's not present, throw a NotAllowed exception.
I know it's ugly, and not very safe (yes no-one likes security-through-obscurity), but it might work enough for your specific case...
I know this topic is a little old by now, but I was just thinking that how I'd do this in Java is with Caller Stack Inspection, and doesn't PHP have something similar? In fact it does, though it's a PECL module:
http://www.php.net/manual/en/function.apd-callstack.php
Get the call stack, check it against your code points, throw an exception if it doesn't match. You could even create a common superclass that does this checking for you.

Categories