In first case we called function in object context. In second case we have class context.
Does parent:: work like this and self simultaneously depending on the context?
class par_parent{
private $var='value1';
private static $val='value2';
public function call(){
var_dump('Object '.$this->var);
}
public static function staticCall(){
var_dump('Static '.self::$val);
}
}
class par_child extends par_parent{
public function callObj(){
parent::call();
}
public static function callStatic(){
parent::staticCall();
}
}
$obj=new par_child();
$obj->callObj();
**//string 'Object value1' (length=13)**
par_child::callStatic();
**//string 'Static value2' (length=13)**
The parent:: is binded like the self:: keyword, always sees the context where it have been defined code wise, not from where it's called, so in essence it works like the self:: keyword. If you need it to work like the $this use late static binding provieded static::. Consider this example:
class A {
protected static $v = 'a';
public static function staticsay() {
print static::$v;
}
}
class B extends A {
protected static $v = 'b';
public static function say(){
print parent::$v;
}
}
class C extends B {
protected static $v = 'c';
public static function selfsay(){
print parent::$v;
}
}
C::say(); // prints 'a'
C::selfsay(); // prints 'b'
C::staticsay(); // prints 'c'
Here we call the say() method on C it comes from the class B so it's parent:: means A and the A::$v is 'a' so it prints that.
While the parent:: in C points to the class B and it sees it's $v as 'b'.
With php 5.3 comes late static binding and the static:: keyword that lets you access the static variables and methods in baseclasses static methods so the A::staticsay will see the $v from the class C.
Related
I have a base class with a static function. But I would like to have a way to know the actual class (could be the base class or a derived class) within whose context I am calling the static function.
For example:
<?php
class Foo
{
static function Test()
{
$c = self::class;
echo "Hello, I am creating a new instance of type $c";
return new $c;
}
}
class Bar extends Foo
{
public $someProperty;
}
$b = Bar::Test(); // This should do something different than Foo::Test();
?>
Note that the self::class in the Test() function always results in 'Foo' even if I'm calling it using the Bar:: context.
I understand I could override the Test() function in Bar but that's not what I want, I want to keep the implemented functionality in the base Test() function. But just with the actual static class context that I'm calling it with.
Is there a way for the above Test() function to say "I am creating a new instance of type Bar" and return a Bar instance, rather than a Foo ?
Let me introduced you to late static binding.
Consider the following code, it's not exactly like yours but it highlight's the issue I believe you are facing.
<?php
class A
{
public static $string = 'I am from class A';
public static function getString()
{
return self::$string;
}
}
class B extends A
{
public static $string = 'I am from class B';
}
B::getString(); // returns 'I am from class A' ???!
?>
To get around this you can use late static binding to use the variable at run time context (rather than at compile time context)
<?php
class A
{
public static $string = 'I am from class A';
public static function getString()
{
return static::$string; // note the change here
}
}
class B extends A
{
public static $string = 'I am from class B';
}
B::getString(); // returns 'I am from class B' and all is well
?>
Far more information than I can give you is available here: https://www.php.net/manual/en/language.oop5.late-static-bindings.php
I have a class called Foo with a constructor and I want to have one variable of it to be the name of the child class.
Example:
class Foo {
protected static $name;
protected static $something;
public function __construct( $something ) {
self::$something = $something;
self::$name = strtolower( __CLASS__ );
}
static public function hello() {
echo self::$name;
}
}
class Bar extends Foo {}
new Foo( 'lazy' );
Bar::hello();
The result will be always foo(), because the constructor is called only by new Foo().
So, what is the way? Is there a magic method called when a static method is invoked? Sorry for the bad explanation.
get_called_class() should be used instead of __CLASS__ magic constant.
http://php.net/manual/en/function.get-called-class.php
More info in the manual : late static binding
As #JesusTheHun said, first of all you'll want to change __CLASS__ to either get_called_class() or static::class (as of PHP 5.5). The string __CLASS__ gets read at compile-time, and will always refer to the class in which it's specified. Either of the other options will take effect at run-time.
However, by setting a static class variable in a constructor, you're changing that variable for all instances of the class (past and present) as well as changing it for any static calls. So whenever a instance of any class in the tree is instantiated, all future calls to hello() will display that class name, i.e.
<?php
class Foo {
protected static $name;
protected static $something;
public function __construct() {
self::$name = strtolower( static::class );
}
static public function hello() {
echo self::$name;
}
}
class Bar extends Foo {}
class Baz extends Foo {}
new Foo;
Bar::hello(); // "foo"
new Baz;
Bar::hello(); // "baz"
This seems like it probably isn't the behaviour you're looking for. If all you want is a static method that will echo the class name that called it, then you can use one of the methods above, e.g.
static public function hello() {
echo static::class;
}
Consider a static class (private constructor, only static methods & variables).
Now the rough class definition would look like this:
class A{
private function __construct(){}
public static test(){};
}
class B{
private function __construct(){}
}
Is it somehow possible to call something like B::A::test() ?
Or maybe through a variable? Something like B::$A::test() ?
I guess it is possible by some general call catching, but I can't figure it out...
IMPORTANT: Also, I want to call ANY other static class from B, not just from the A class...
EDIT2: What I want to achieve is to call static class through another static class, if possible... very similar to calling a method from object variable - but static class (obviously) is not ment to be instantiated.
EDIT3: Also possible solution is to call it as B::CLASSNAME_METHOD_NAME and catch it by __callStatic but I would rather do B::CLASSNAME::METHOD_NAME ...
Another possible solution:
If you don't want to create whole singleton, this could be solution - creating a partial singleton - some kind of singleton-hepler, altough using -> to call a static method could be confusing!
class AA{
private function __construct(){}
private static $instance;
public function getInstance(){ return empty(self::$instance)?(new self()):self::$instance; }
public function __call($method_name, $args) {
return AA::$method_name($args);
}
public static function test($a, $b){
echo "TEST: A:".$a." B:".$b;
}
}
class B{
private function __construct(){}
public static function A(){
return AA::getInstance();
}
}
B::A()->test("one", "two");
You would have to use this syntax:
class B {
const A = 'A';
}
$class = B::A;
$class::test()
This is essentially just the syntax for calling a static method on a variable class name. There's no nicer shortcut for it.
Note that I don't think such a pattern makes a lot of sense, your class design is too static at this point. You should be instantiating your classes and call $b->a->test(), which gives you more flexibility in your application design. Realistically B::A is hardcoded, it's not going to be anything other than 'A', so you may as well write A::test() directly.
If instead of a const you'd use a public static property which may vary at runtime, you now introduce global state into your app, which is also undesirable.
calling static function of a class from a static function of an another class
class A{
private function __construct(){}
public static function test()
{
echo 'from class A';
}
}
class B{
private function __construct(){}
public static function test()
{
return A::test();
}
}
A::test(); //outputs 'from class A'
B::test(); //outputs 'from class A'
What is the difference between using self and static in the example below?
class Foo
{
protected static $bar = 1234;
public static function instance()
{
echo self::$bar;
echo "\n";
echo static::$bar;
}
}
Foo::instance();
produces
1234
1234
When you use self to refer to a class member, you're referring to the class within which you use the keyword. In this case, your Foo class defines a protected static property called $bar. When you use self in the Foo class to refer to the property, you're referencing the same class.
Therefore if you tried to use self::$bar elsewhere in your Foo class but you had a Bar class with a different value for the property, it would use Foo::$bar instead of Bar::$bar, which may not be what you intend:
class Foo
{
protected static $bar = 1234;
}
class Bar extends Foo
{
protected static $bar = 4321;
}
When you call a method via static, you're invoking a feature called late static bindings (introduced in PHP 5.3).
In the above scenario, using self will result in Foo::$bar(1234).
And using static will result in Bar::$bar (4321) because with static, the interpreter takes into account the redeclaration within the Bar class during runtime.
// self
var_dump(Foo::$bar);
// (int) 1234
// static
var_dump(Bar::$bar);
// (int) 4321
You typically use late static bindings for methods or even the class itself, rather than properties, as you don't often redeclare properties in subclasses; an example of using the static keyword for invoking a late-bound constructor can be found in this related question: New self vs. new static
However, that doesn't preclude using static with properties as well.
I have small example showing difference between self and static. Using static:: performs Late Static Binding and thus it binds the variable value from child class.
class A { // Base Class
protected static $name = 'ClassA';
public static function getSelfName() {
return self::$name;
}
public static function getStaticName() {
return static::$name;
}
}
class B extends A {
protected static $name = 'ClassB';
}
echo A::getSelfName(); // ClassA
echo A::getStaticName(); // ClassA
echo B::getSelfName(); // ClassA
echo B::getStaticName(); // ClassB
With self call:
class Phone
{
protected static $number = 123;
public function getNumber()
{
return self::$number;
}
}
class Fax extends Phone
{
protected static $number = 234;
}
// Displays: "123"
echo (new Fax)->getNumber();
You can see above, even though we have overridden the $number with our Fax class, getNumber() still returns 123.
This because we have asked PHP to give us the variable where it was defined in -- which will return Phones variable instead.
If we swap the self call with static, we will get Faxs overridden value instead:
With static call:
class Phone
{
protected static $number = 123;
public function getNumber()
{
// return self::$number;
return static::$number;
}
}
class Fax extends Phone
{
protected static $number = 234;
}
// Displays: "234"
echo (new Fax)->getNumber();
As mentioned one of the main differences is that static allows for late static bindings. One of the most useful scenarios that I found was for creating Base classes for Singleton Classes:
class A { // Base Class
protected static $name = '';
protected static function getName() {
return static::$name;
}
}
class B extends A {
protected static $name = 'MyCustomNameB';
}
class C extends A {
protected static $name = 'MyCustomNameC';
}
echo B::getName(); // MyCustomNameB
echo C::getName(); // MyCustomNameC
Using return static::$name in the Base class will return what was statically attached when it was extended. If you were to use return self::$name then B::getName() would return an empty string as that is what is declared in the Base class.
Maybe this self-explained code helps you:
class Foo
{
protected static $bar = 'parent value';
public static function test()
{
var_dump('I am your father');
var_dump('self:: here means '.self::$bar);
var_dump('static:: here means '.static::$bar);
}
}
class Bar extends Foo
{
protected static $bar = 'child value';
public static function test()
{
parent::Test();
var_dump('I am the child');
var_dump('self:: here means '.self::$bar);
var_dump('static:: here means '.static::$bar);
}
}
Bar::test();
Foo::test();
This produces the following output (I have added Line Breaks for clarity):
'I am your father' (length=16)
'self:: here means parent value' (length=30)
'static:: here means child value' (length=31)
'I am the child' (length=14)
'self:: here means child value' (length=29)
'static:: here means child value' (length=31)
'I am your father' (length=16)
'self:: here means parent value' (length=30)
'static:: here means parent value' (length=32)
Using PHP 5.3+ and having something equal to the following I get the output of 'C' instead of 'B':
class A
{
public static function doSomething()
{
echo get_called_class();
}
}
class B extends A
{
public static function doMore()
{
self::doSomething();
}
}
class C extends B {}
C::doMore();
If I had used static::doSomething() that would be the expected result, but when using self::doSomething() I expect this method to get called in the scope of B because it's where the 'self' is defined and not the late static binding.
How is that explained and how do I get 'B' in the doSomething() method?
Thanks in advance, JS
The issue here is late static binding. The get_called_class() function will use late static binding to return the class name, __CLASS__ will use late static binding if called using static::, but not when used with $this-> or self::. I don't know of a way to get it to return B short of having the echo within B instead of A. It sounds like this would be an ideal use of traits if you were using PHP 5.4.
Example:
class A
{
public static function doSomething()
{
echo __CLASS__;
}
}
class B extends A
{
public static function doMore()
{
self::doSomething();
}
}
class C extends B {}
C::doMore();
This returns A instead of C.
Override the method doSomething, to get B
class C extends B
{
public static function doMore()
{
B::doMore();
}
}
Tested