Getting class constant inside class - php

What's the difference between self::CONSTANT_NAME and static::CONSTANT_NAME?
Is calling constant via static:: only 5.3 feature?

When you use static::NAME it's a feature called late static binding (or LSB). More information about this feature is at the php.net documentation page of LSB: http://nl2.php.net/manual/en/language.oop5.late-static-bindings.php
An example is this use case:
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
self::who();
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
?>
This outputs A, which is not always desirable. Now replacing self with static creates this:
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who(); // Here comes Late Static Bindings
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
?>
And, as you might expect, it ouputs "B"

The difference is pretty much what late static bindings are all about.
Short explanation:
self:: will refer to the class type inside which the code using self:: is written.
static:: will refer to the class type of the actual object that on which the code using static:: is being executed.
This means that there's only a difference if we are talking about classes in the same inheritance hierarchy.

Related

Right way to instantiate class in PHP

I am trying to create a method inside class, that will instantiate class that is currently in. But I would also need that from this method to work correctly in all extended classes. As I have learned from this thread, it's not good to use self keyword for this task. So obvious choice would be using static keyword.
But, I've come across different method that also works.
Example:
class SimpleClass
{
private $arg;
public function __construct( $arg ){
$this->arg = $arg;
}
public function getArg(){return $this->arg;}
public function setArg($arg){$this->arg = $arg;}
public function staticInstance()
{
return new static( $this->arg );
}
public function thisInstance()
{
return new $this( $this->arg );
}
public function selfInstance()
{
return new self( $this->arg );
}
}
class ExtendedClass extends SimpleClass
{
}
$c1 = 'SimpleClass';
$c2 = 'ExtendedClass';
$inst1 = new $c1('simple');
$inst2 = new $c2('extended');
$static_instance_1 = $inst1->staticInstance();
$this_instance_1 = $inst1->thisInstance();
$self_instance_1 = $inst1->selfInstance();
$static_instance_2 = $inst2->staticInstance();
$this_instance_2 = $inst2->thisInstance();
$self_instance_2 = $inst2->selfInstance();
echo "SimpleClass Instances\n";
echo get_class($static_instance_1);
echo get_class($this_instance_1);
echo get_class($self_instance_1);
echo "ExtendedClass Instances\n";
echo get_class($static_instance_2);
echo get_class($this_instance_2);
echo get_class($self_instance_2);
As I can see from this example, both staticInstance and thisInstance produce "correct" results. Or do they?
Can someone explain difference between these two methods and which one is "correct" one.
php.net says:
As of PHP 5.3.0, PHP implements a feature called late static bindings which can be used to reference the called class in a context of static inheritance.
More precisely, late static bindings work by storing the class named in the last "non-forwarding call". In case of static method calls, this is the class explicitly named (usually the one on the left of the :: operator); in case of non static method calls, it is the class of the object. A "forwarding call" is a static one that is introduced by self::, parent::, static::, or, if going up in the class hierarchy, forward_static_call(). The function get_called_class() can be used to retrieve a string with the name of the called class and static:: introduces its scope.
This feature was named "late static bindings" with an internal perspective in mind. "Late binding" comes from the fact that static:: will not be resolved using the class where the method is defined but it will rather be computed using runtime information. It was also called a "static binding" as it can be used for (but is not limited to) static method calls.
Limitations of self:
Static references to the current class like self:: or CLASS are resolved using the class in which the function belongs, as in where it was defined:
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
self::who();
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
?>
The above example will output: A
Late Static Bindings' usage:
Late static bindings tries to solve that limitation by introducing a keyword that references the class that was initially called at runtime. Basically, a keyword that would allow you to reference B from test() in the previous example. It was decided not to introduce a new keyword but rather use static that was already reserved.
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who(); // Here comes Late Static Bindings
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
?>
The above example will output: B
$this keyword refers to current object and you cannot use it in static methods. When you say return $this it means that some method returns the same object on which it was invoked.
So the correct way would be using static keyword because if you say return new static() it refers to the class the method is currently in.

How to get child class name from parent class

I'm trying to accomplish this without requiring a function on the child class... is this possible? I have a feeling it's not, but I really want to be sure...
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who(); // Here comes Late Static Bindings
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test(); //returns B
?>
Use get_called_class() instead of __CLASS__. You'll also be able to replace static with self as the function will resolve the class through late binding for you:
class A {
public static function who() {
echo get_called_class();
}
public static function test() {
self::who();
}
}
class B extends A {}
B::test();

PHP5 static methods inheritance. Overloading. Getting called class name

I have good oop understanding but poor understanding of its implementation in php...
I have the following code, hope it's self documented =).
I need to have BB in the output
class A{
// I can't copy function::classname() to all my descendant classes
static function classname(){
echo __CLASS__;
}
}
class B extends A{
static function test(){
self::classname();
}
function test1(){
self::classname();
}
//i have A LOT of static and non-static functions using self::classname() in their code
// I can't copy all them to base class
}
$v = new B();
B::test();
$v->test1();
I'm stuck with static:: and self:: syntax
PS: another crazy question I've come across:
Suppose I have
function doSomething(){
echo $this->id;
}
Sometimes it gets into the static contexts. Yes, I know, that's because my bad application design. But is it possible to create a second(mirror, overloading) function
static function doSomething(){
echo false;
}
It means that using
$obj->doSomething() returns id and using Class::doSomething() returns false
Question 3:
Is it possible to get property default value in static context an property value in non-static context automatically?
Have a look at late static binding.
class A {
static function classname() {
echo __CLASS__;
}
static function test1() {
static::classname();
}
}
class B extends A {
static function classname() {
echo __CLASS__;
}
}
$v = new B();
B::test1();
$v->test1();
Or as pointed out by Long Ears in the comments, assuming php 5.3.0+ you can use get_called_class()
class A {
static function classname() {
echo get_called_class();
}
// this can be defined in either class A or B without affecting the output
static function test1() {
static::classname();
}
}
class B extends A {
}
$v = new B();
B::test1();
$v->test1();
Outputs:
BB
Regarding your second "crazy" question, see the Magic Methods. Basically, you would need to implement something like:
class Foo
{
public function __call($name, $arguments)
{
// call the _$name function
}
public static function __callStatic($name, $arguments)
{
// call the _{$name}_static function
}
private function _bar()
{
}
private static function _bar_static()
{
}
}
$foo = new Foo();
$foo->bar();
Foo::bar();
it's possible to add a static method like this
class Foo {
public static function __callStatic() {
// ....
}
}
// in Other file
// Call the static method
Foo-->__callStatic()
and call it on an other file (In php ) ?

PHP Can static:: replace self::?

I am a little confused with this matter. I am designing an ORM class that tries to behave very similarly to ActiveRecord in ruby on rails, but that's beside the point.
What I'm trying to say is that my class makes extensive use of static attribute inheritance, specially for database and table handling. My question is, should I use self:: at all?
You have to ask yourself: "Am I targeting the problem with the adequated approach?"
self:: and static:: do two different things. For instance self:: or __CLASS__ are references to the current class, so defined in certain scope it will NOT suffice the need of static calling on forward.
What will happen on inheritance?
class A {
public static function className(){
echo __CLASS__;
}
public static function test(){
self::className();
}
}
class B extends A{
public static function className(){
echo __CLASS__;
}
}
B::test();
This will print
A
In the other hand with static:: It has the expected behaviour
class A {
public static function className(){
echo __CLASS__;
}
public static function test(){
static::className();
}
}
class B extends A{
public static function className(){
echo __CLASS__;
}
}
B::test();
This will print
B
That is called late static binding in PHP 5.3.0. It solves the limitation of calling the class that was referenced at runtime.
With that in mind I think you can now see and solve the problem adequately. If you are inheriting several static members and need access to the parent and child members self:: will not suffice.
try to use the code bellow to see the difference between self and static:
<?php
class Parent_{
protected static $x = "parent";
public static function makeTest(){
echo "self => ".self::$x."<br>";
echo "static => ".static::$x;
}
}
class Child_ extends Parent_{
protected static $x = "child";
}
echo "<h4>using the Parent_ class</h4>";
Parent_::makeTest();
echo "<br><h4>using the Child_ class</h4>";
Child_::makeTest();
?>
and you get this result:
using the Parent_ class
self => parent
static => parent
using the Child_ class
self => parent
static => child

static class inheritant not work in PHP?

abstract class base {
abstract public function test();
public function run()
{
self::test();
}
}
class son extends base {
public function test()
{
echo 1;
}
}
son::run();
It reports:
Fatal error: Cannot call abstract
method base::test()
But son::test() works,why and is there a way to fix?
"self" is lexically scoped, that is, if you use "self" in a method of Base, "self" means "Base", no matter how you call this method at run time. php5.3 introduced a new kind of dynamic binding, which, ironically enough, is called "static". The following works as expected in php 5.3
abstract class base {
abstract public static function test();
static public function run()
{
static::test();
}
}
class son extends base {
static public function test()
{
echo 1;
}
}
son::run();
Of course:
Fatal error: Cannot call abstract method base::test()
It has no method body you could call. If run() is supposed to be a Template Method, you refer to the class scope with $this instead of self and then create an instance of $son to call run() on it, e.g.
abstract class BaseClass {
abstract public function test();
public function run()
{
$this->test();
}
}
class Son extends BaseClass {
public function test()
{
echo 1;
}
}
$son = new Son;
$son->run(); // 1
which is rather odd, because then you could have just as well called test() directly.
Also note that in your example
son::run();
is wrong, because the run() method is not declared static and while PHP will execute run() nonetheless, it is considered wrong usage and will raise an E_STRICT error. However, if you were to define run() static, you could no longer reference $this, because a static method is not invoked from instance scope, but class scope.
Edit I was about to add the PHP5.3 solution, but see that #erenon already did that, while I was typing, so I only add the appropriate reference in the PHP Manual on Late Static Binding.
Abstract methods do not have an implementation, and thus cannot be called. If the method is not defined as abstract, and actually has an implementation, then it can be executed by your code. For example:
public function test(){
echo "Hello from base!";
}
Factory/singleton pattern mix:
class Base
{
static private $instance;
static function getSon() {
if (null === self::$instance) {
self::$instance = new Son;();
}
return self::$instance;
}
}
class Son
{
public function test() {
echo 1;
}
}
Base::getSon()->test(); //1

Categories