Access property of 'singleton' class PHP - php

I am not sure whether the technique I use is appropriate or not.
I have a class, singleton, with a subinstance like this:
final class Singleton {
public $subinstance;
private static $instance = NULL;
private function __construct() {
$this->subinstance = new subinstance();
}
public static function getInstance() {
if (NULL === self::$instance) {
self::$instance = new self;
}
return self::$instance;
}
private function __clone() {}
}
And now if I want to access the subinstance from outside the class in another class, I do:
$s = singleton::getInstance();
$s->subinstance->....
Is this the right way to do this?
And what happens when I do $s=singleton::getInstance();, does the entire singleton class gets copied into $s or is this more like a pointer?

What you are doing is fine, although in your example code I'm assuming you meant to write:
$s = Singleton::getInstance(); // with the S capitalized
When you call the getInstance method, the class is looking to see if a version of itself has already been instantiated. If it has, it will return a reference to that instance instead of creating an entirely new instance. If the instance has not been created yet, it will create the instance and then return a reference to it.
I'm not sure why sixeightzero has stated that you shouldn't instantiate a class in the constructor of your instance. You shouldn't experience any issues when doing so.

If you do $a = singleton, $a will be a reference to the singleton class. Any changes in $a will reflect in access by singleton:: etc.. (pointer)
Why are you doing a subinstance in the constructor? This can cause issues, and should create a method to handle the subinstance outside the constructor inside a protected method. What does your subinstance look like?

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.

PHP new static($variable)

$model = new static($variable);
All these are within a method inside a class, I am trying to technically understand what this piece of code does. I ran around in the Google world. But can't find anything that leads me to an answer. Is this just another way of saying.
$model = new static $variable;
Also what about this
$model = new static;
Does this mean I'm initializing a variable and settings it's value to null but I am just persisting the variable not to lose the value after running the method?
static in this case means the current object scope. It is used in late static binding.
Normally this is going to be the same as using self. The place it differs is when you have a object heirarchy where the reference to the scope is defined on a parent but is being called on the child. self in that case would reference the parents scope whereas static would reference the child's
class A{
function selfFactory(){
return new self();
}
function staticFactory(){
return new static();
}
}
class B extends A{
}
$b = new B();
$a1 = $b->selfFactory(); // a1 is an instance of A
$a2 = $b->staticFactory(); // a2 is an instance of B
It's easiest to think about self as being the defining scope and static being the current object scope.
self is simply a "shortcut name" for the class it occurs in. static is its newer late static binding cousin, which always refers to the current class. I.e. when extending a class, static can also refer to the child class if called from the child context.
new static just means make new instance of the current class and is simply the more dynamic cousin of new self.
And yeah, static == more dynamic is weird.
You have to put it in the context of a class where static is a reference to the class it is called in. We can optionally pass $variable as a parameter to the __construct function of the instance you are creating.
Like so:
class myClass {
private $variable1;
public function __construct($variable2) {
$this->variable1 = $variable2;
}
public static function instantiator() {
$variable3 = 'some parameter';
$model = new static($variable3); // <-this where it happens.
return $model;
}
}
Here static refers to myClass and we pass the variable 'some parameter' as a parameter to the __construct function.
You can use new static() to instantiate a group of class objects from within the class, and have it work with extensions to the class as well.
class myClass {
$some_value = 'foo';
public function __construct($id) {
if($this->validId($id)) {
$this->load($id);
}
}
protected function validId($id) {
// check if id is valid.
return true; // or false, depending
}
protected function load($id) {
// do a db query and populate the object's properties
}
public static function getBy($property, $value) {
// 1st check to see if $property is a valid property
// if yes, then query the db for all objects that match
$matching_objects = array();
foreach($matching as $id) {
$matching_objects[] = new static($id); // calls the constructor from the class it is called from, which is useful for inheritance.
}
return $matching_objects;
}
}
myChildClass extends myClass {
$some_value = 'bar'; //
}
$child_collection = myChildClass::getBy('color','red'); // gets all red ones
$child_object = $child_collection[0];
print_r($child_object); // you'll see it's an object of myChildClass
The keyword new is used to make an object of already defined class
$model = new static($variable);
so here there is an object of model created which is an instance of class static

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 Singleton instantiation with String class name

Im building a small MVC system and i want my controllers to be Singletons. I made the base controller "Controller" a singleton and every other controller extends from that. My Router processes the request from the URL and grabs the controller string name.
This is where im getting the private constructor error because i am trying to do this:
class IndexController extends Controller {
//the "Index" part comes from the url
}
class Controller {
private $instance;
/**
* Initializes a new Singleton Controller
*/
private function __construct() {
}
/**
* Get the instance of the Controller
*/
public static function getInstance(){
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
}
$className = "Controller";
$inst = new $className; //here is where i get the error
$inst = $className::getInstance() //also fails
I have done my research and i stumbled upon this (http://www.php.net/manual/en/reflectionclass.newinstancewithoutconstructor.php), however I am not sure if that will work or is the best method if it does.
$inst = new $className; //here is where i get the error
This error is right, as the constructor is private.
$inst = $className::getInstance() //also fails
This error is also right, as this syntax is not allowed.
If you want your conrollers to be singletons, you can, but you need to "twist" the rules for that.
b.t.w
Why on earth would you want to do this?
Why not just use an existing MVC (you do not need the entire FW).
replace the self with static as this will reference the actual controller you try to instantiate and not the Controller class, as static references only the class it is written in.
Twisting the rules: You will need to instantiate your controllers through a factory (it is a pattern). Usually the front controller is used for that.
A couple things really in regards to errors in using the "pattern"
class Controller {
private static $instance;
/**
* Initializes a new Singleton Controller
*/
private function __construct() {
}
/**
* Get the instance of the Controller
*/
public static function getInstance(){
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
}
Note that the property is now static and the constructor is private as necessary for this anti-pattern.
Second your calling code should look like
$instance = Controller::getInstance();
You should never have to instantiate 'Controller' from the outside; the point of the pattern is to only allow access through Controller::getInstance()
That being said Singleton is little better than global state. Misko Hevery talks about it in this Google Clean Code Talk: Global State and Singleton. It is a really good video and explains far better than I can why Singletons are bad news. sourcemaking.com also has a good write-up on Singletons where they say that Singletons are unnecessary most of the time
class Controller {
/**
* Let the __construct method be private to prevent new instance though new.
*/
private function __construct() {}
/**
* Get the instance of the Controller
* Here use the lazy loading. (need php >= 5.3)
*/
public static function getInstance(){
if (null === static::$instance) {
static::$instance = new static();
}
return static::$instance;
}
}
class ControllerA extends Controller {
//You need an static property to hold the instance.
protected static $instance;
}
var_dump($a = ControllerA::getInstance());
var_dump($b = ControllerA::getInstance());
var_dump($a === $b);
If your Controller Name is a string, You can do like this:
$classname = "ControllerA";
call_user_func(array($classname, 'getInstance'));
call_user_func($classname .'::getInstance'); // As of 5.2.3
On this line:
$inst = $className::getInstance() //also fails
You are using the scope resolution operator. You should be using this '->' for access to object data members/methods.
$inst = $className->getInstance() //also fails
Otherwise, you need to use the scope resolution operator on the class rather than the object:
$inst = Controller::getInstance() //also fails
I do not know where you are getting the value off $className as a class. There is no class called IndexController.

what is the exact difference between PHP static class and singleton class

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.

Categories