Singleton design pattern in PHP - php

I have a question about singleton design pattern.
When we apply singleton for our class, we need to set class' constructor private so we can not instantiate the class normally, but we also instantiate it in class context (if the object we need doesnt exist). The question is why dont private constructor prevent us from instantiate class in class context?

Visibility modifiers are for specifying who can be trusted to interact with this method or property. The idea being that each method and property has a specific purpose and should be used in specific ways; e.g. certain methods should only be called at certain times and certain properties should only ever be set to certain values. If each method and property is public, any code can interact with it at any time, even if it's not "qualified" to do so correctly. To minimise problems resulting from that, visibility can be restricted to a family of classes only (protected) or one specific class alone (private).
There is no difference whether this interaction is in a static or object context, or even whether it's the "current" object or another instance of it. The class is expected to "be qualified" to interact with the method correctly, so it is allowed to do so. This might surprise you, but even this works just fine according to this philosophy:
class Foo {
private $bar;
public static baz() {
$obj = new Foo;
$obj->bar = 42;
}
}
The class is not manipulating $this, it's manipulating a private property of an instance of itself, and that's allowed. So is calling its own constructor.

If a class method is set to private you cannot access it outside the class, neither in the child class, but you can access the private method with-in that particular class only.
__construct() is no different, when you set __construct() to private you cannot access it outside the class.
now to clarify a little bit more, when we instantiate an object of a class, PHP automatically invokes its constructor.. which, if set to private, prevents instantiation of a new object. BUT.. if we instantiate an object of a class from with-in that that class, PHP tries to invoke __construct() on it & nothing is preventing it there..
I hope I was able to make it clear for you. :)

Related

Passing variable to a static function inside subclass

I have a class with a variable $x that I want to use in a static function on his subclass.
class people{
protected $x;
function __constructor(){
$this->x = 'cool';
}
}
class person extended people {
function static status() {
'Here I want to use the x variable. I tried $this->x,parent::x..';
}
}
This obviously is not possible, since there is no object referred to inside a static method. That is the whole point of a static method: to be able to use it independent of an instantiated object. But without such object you obviously do not have a property $x...
There are a few alternatives, which one you chose depends on your situation:
you can hand over the value as an explicit argument (so static function status($x)), if you have access to the property of an instantiated object of class people.
you can declare the property as static const inside the class. In that case you obviously do have access from within a static class method. However it obviously is a constant that can be initialized, but which can not change its value over time.
you can design that property outside the class. Yes, this is obvious and changes the point of the class design. But since you already try to use a static method chances are that this method should not depend on any instantiated object at all...
In general one can say that the issue you ran into demonstrates that your class design is not conclusive, does not really make sense in itself in its current state. You will have to redesign the class (or maybe a bigger architecture).
Start by asking yourself a question: "why do you want to make the method status() static at all?"

What's the point of a static method that returns an instance of the class it's a part of?

Sometimes when I look at code other people have written I see something like the following:
<?php
namespace sys\database;
class Statistics {
public function __construct() {
// Database statistics are gathered here using
// private methods of the class and then set to
// class properties
}
public static function getInstance() {
return new \sys\database\Statistics();
}
// ...
}
So the static function getInstance() simply returns an object of the class it belongs to. Then, somewhere else in the code I come across this:
$stats = \sys\database\Statistics::getInstance();
Which simply sets $stats to an instance of the Statistics object, ready for its class properties to be accessed to get various database statistics.
I was wondering why it was done this way as opposed to just using $stats = new \sys\database\Statistics();. At the end of the day, all the logic to gather statistics is in the constructor and the getInstance() method doesn't do anything other than returning a new object.
Is there something I'm missing here?
This is supposed to be an implementation of the Singleton pattern: http://www.oodesign.com/singleton-pattern.html
The pattern is used to never allow more than one instance of the class to be created.
However, there are a couple of flaws with the implementation you provided: the constructor should be private, and there should be a single private static instance of the class, returned every time the getInstance method is called.
This is supposed to be an implementation of the Singleton pattern, which is a term used to describe a class which can only exist once for run-time.
It seems the implementation you have is flawed however because:
there is no check to see if the class exists yet and
code can create multiple instances by calling the constructor directly (it should be made private)
That's a [bad] implementation of the Singleton pattern.
As a rule of thumb, you should avoid such pattern in favour of more convenient Dependency Injection, for instance.

How to create an interface that allows for loading an object?

I have created an interface meant to be implemented by users. The only real requirements I have is that the user's implement a Save() and a Load() method. Now save is simple, but the problem I'm having is with Load().
In order for Load() to be part of the interface it would need to be an instance method. But the nature of it is to return a new object that has been loaded from a database. This would imply that Load() needs to be defined as static. Static methods aren't enforced by the interface.
How can I require users who implement the interface to write their own code for Load()?
I'm using PHP5.4 which does require that constructor definitions are followed in subclasses, so one thought was to change this into an Abstract Class and define a constructor that takes an $id variable. If it's null we create a new object, if it's set then load the object. I'd much prefer to keep this setup as an interface. There also is some concern of ambiguity and some user implementing their constructor incorrectly. It's easier to document and describe what load() should do.
Why does "a method that returns an object" immediately mean that it has to be static? Static isn't a blanket "go-to" on object creation - it actually serves a specific purpose.
Anyway. There is nothing stopping you from defining an interface that requires the implementation of a static method, as follows, if your heart so desires :
interface MyTestInterface {
public static function Load();
}
class MyTest implements MyTestInterface {
public static function Load() {
echo "Test";
}
}
Fiddle: http://codepad.viper-7.com/xcoQZh
There is nothing stopping you from defining a method requiring implementation, either through an interface or an abstract class, when the method is static. However, consider the actual static use in this case....

Private static method vs. static method

I understand that static means that an object doesn't need to be instantiated for that property/method to be available. I also understand how this applies to private properties and methods and public methods. What I'm trying to understand is what static private function gains you. For example:
class Beer {
static private $beertype = "IPA";
private function getBeerType() {
return self::$beertype;
}
static public function BeerInfo() {
return self::getBeerType();
}
}
print Beer::BeerInfo() . "\n";
The private method getBeerType() executes just fine without an instantiated object as long as it's being called from a static public method. If a static public method has access to all private methods (static and non-static), what's the benefit of declaring a method static private?
With strict error reporting turned on, I do get the warning that I should make getBeerType() static, although it still lets me run the code. And I did a little research and it seems like other languages (Java) will force you to declare a private method as static when called by a static public method. Looks like PHP lets you get away with this. Is there a way to force it to throw an error and not execute?
A static private method provides a way to hide static code from outside the class. This can be useful if several different methods (static or not) need to use it, i.e. code-reuse.
Static methods and static variables, sometimes called class methods and class variables, are a way of putting code and data into a kind of namespace. You could also think of class variables as variables attached to the class itself, of which there is (by definition) exactly one, instead of to instances of that class, of which there may be zero, one or many. Class methods and class variables can be useful in working with attributes that not just remain same in all instances, but actually be the same.
An example of a class variable is a database handler in an ORM entity object. All instances are their own object, but they all need access to the same database handler for loading and saving themselves.
Private versus public is a completely separate quality, which is I suspect what you're stumbling over. A private method cannot be called and private variables cannot be accessed from code outside the class. Private methods are usually used to implement "internal" logic on the object that must not be accessible from outside the object. This restriction can be needed by instance methods as well as class methods.
An example of a private class method could be in a factory method. There might be three factory calls for creating an object which might differ in parameters being supplied. Yet the bulk of the operation is the same. So it goes into a private static method that the non-private factory methods call.
I understand static means that an object doesn't need to be instantiated for that property/method to be available.
Everything static just exists. Globally.
I also understand how this applies to public properties and methods and public methods
Are you sure you have understood that it creates a global variable and a standard global function?
What I'm trying to understand is what static private function gains you.
The private is just a specifier of visibilityDocs. So that gains you visibility control.
Is it useful? Depends on the use-case.
it's for preventing OTHERS from consuming it.
Example, you have a Logger static object, then you have two public static methods LogOk and LogError and both benefeit from an "internal" method Log but you don't want the consumers of that class to be able to call Log directly.
You can call Logger::LogOk( "All right." ); but you cannot call Logger::Log( "abc" ); if Log is private.
You you can internally always make use of it from the same class.
Although the code works, it throws a Strict standards error:
Strict standards: Non-static method Beer::getBeerType() should not be
called statically
So, here you get the use of the private static.
Simply said you can declare a private static function if you have a repeated operation in some of the public static functions in the class.
Naturally if you are an inexperienced programmer or new to the OOP putting limitations to your code seem strange. But strict declarations like this will make your code cleaner and easier to maintain.
In large projects and complex classes you can appreciate to know exactly what to expect from a function and exactly how you can use it.
Here is a good read: Single responsibility principle and
God Object
Here's the rule and the best answer,
static methods cannot access non-static variables and methods, since these require an instance of the class. Don't worry about the warning, the rule is set and it will break your code in the future once it's fully enforced. That is why
static public function BeerInfo() {
return self::getBeerType()
is wrong,
you have to declare getBeerType as static.
In your example, you can simplify this by doing the following.
static private $beertype = "IPA";
static public function BeerInfo() {
return self::$beertype;
}
'static' purely means resident in a single region of memory. If you are memory conscious, static implementations are a good strategy.
When you use a public static function, chances are, most of the time, that you don't want to deal with an instance of that class, but want to re-use pre-existing functionality from within that class. Leveraging private static functions is the way to do that without instances.
However, you could have a public static function which accepts an argument which is an instance of said class, e.g.
static public function doSomething(Beer &$ref) {
$ref->instanceLevelFunction(...);
}

Behavior of $this on inherited methods

I always thought I understood how OOP works (and I have been using it for years), but sometimes I realize some concepts are still not so clear to me.
I just came across this question about method visibility in PHP. The accepted answer explains that a private method cannot be overridden by a child class in PHP. Okay, that makes sense. However, the example made me think about the internal inheritance mechanism in PHP, and the way $this behaves on inherited methods.
Consider this code (example from the PHP Manual, also included in the question mentioned above):
class Bar
{
public function test() {
$this->testPrivate();
$this->testPublic();
}
public function testPublic() {
echo "Bar::testPublic\n";
}
private function testPrivate() {
echo "Bar::testPrivate\n";
}
}
class Foo extends Bar
{
public function testPublic() {
echo "Foo::testPublic\n";
}
private function testPrivate() {
echo "Foo::testPrivate\n";
}
}
$myFoo = new foo();
$myFoo->test();
/*
Output:
Bar::testPrivate
Foo::testPublic
*/
Now consider this excerpt from the PHP Manual:
The pseudo-variable $this is available when a method is called from within an object context. $this is a reference to the calling object (usually the object to which the method belongs, but possibly another object, if the method is called statically from the context of a secondary object).
The explanation states that "$this is a reference to the calling object", which is $myFoo. So I expected that $myFoo->test() would always invoke Foo::testPrivate, and never Bar::testPrivate (unless $myFoo were an instance of Bar). I tested $this with get_class, and it always returns Foo, even from inside Bar::testPrivate and Bar::test. However, $this behaves like an instance of Bar when Bar::test calls $this->testPrivate().
That's really confusing, and I am trying to understand why it works that way!
I thought inherited methods (public or protected) were somehow copied from the base to the child class. Private methods would not be copied at all. But this example indicates that it doesn't work like this. It looks like the instance of Foo keeps an internal instance of Bar, and delegates method calls to it when necessary.
I am trying to learn something here, and I only learn when things make sense to me. This one does not. After writing all this, I think I can summarize it with two questions:
Could someone briefly explain how inheritance works internally in PHP? Or at least point me to an article or documentation about that?
Is the behavior or $this discussed here present on other OO languages as well, or is it particular to PHP?
Inheritance in PHP works the same way it does in most object-oriented languages.
When you have a "virtual" method, the method is not bound directly to the caller. Instead, every class contains a little lookup table which says "this method name is bound to that implementation". So, when you say $this->testPublic(), what actually happens is that PHP:
Gets the virtual table for the current class
Looks up the virtual table entry for testPublic in that table
Invokes the method to which that lookup points
Since Foo overrides testPublic, its virtual table contains an entry for testPublic pointing to Foo::testPublic.
Now, with the private methods, the behavior is different. Since, as you correctly read, private methods cannot be overridden, calling a private method never results in a virtual table lookup. That is to say, private methods cannot be virtual and must always be defined in the class which uses them.
So, the effect is that the name is bound at the time of declaration: all Foo methods will call Foo::testPrivate when they say $this->testPrivate, and all Bar methods will call Bar::testPrivate.
To sum up, saying that "inherited methods are copied to the child" is not correct. What actually happens is that the child begins with its method-name-lookup-table being populated with its parent class' entries, and then adds its own functions and replaces any overridden entries. When you call $this->something, this lookup table is consulted for the current object's class. So if $this is an instance of Foo, and Foo overrides testPublic, you get Foo::testPublic. If $this is an instance of Bar, you will get Bar::testPublic.
Well, private methods and properties are exactly that - private. For all intents and purposes, you can consider them "internal", meaning internal to the class they're defined in. This means that they're never inherited, and can never be overridden.
Thus, when using $this in combination with a private method or property, it will always be the method or property within the same class as the reference to $this. This happens because $this called within a parent class cannot access private methods or properties in another class (because they're private), even from child classes.
Hope this helps.

Categories