I am converting a PHP 5.3 library to work on PHP 5.2. The main thing standing in my way is the use of late static binding like return new static($options); , if I convert this to return new self($options) will I get the same results?
What is the difference between new self and new static?
will I get the same results?
Not really. I don't know of a workaround for PHP 5.2, though.
What is the difference between new self and new static?
self refers to the same class in which the new keyword is actually written.
static, in PHP 5.3's late static bindings, refers to whatever class in the hierarchy you called the method on.
In the following example, B inherits both methods from A. The self invocation is bound to A because it's defined in A's implementation of the first method, whereas static is bound to the called class (also see get_called_class()).
class A {
public static function get_self() {
return new self();
}
public static function get_static() {
return new static();
}
}
class B extends A {}
echo get_class(B::get_self()); // A
echo get_class(B::get_static()); // B
echo get_class(A::get_self()); // A
echo get_class(A::get_static()); // A
If the method of this code is not static, you can get a work-around in 5.2 by using get_class($this).
class A {
public function create1() {
$class = get_class($this);
return new $class();
}
public function create2() {
return new static();
}
}
class B extends A {
}
$b = new B();
var_dump(get_class($b->create1()), get_class($b->create2()));
The results:
string(1) "B"
string(1) "B"
In addition to others' answers :
static:: will be computed using runtime information.
That means you can't use static:: in a class property because properties values :
Must be able to be evaluated at compile time and must not depend on run-time information.
class Foo {
public $name = static::class;
}
$Foo = new Foo;
echo $Foo->name; // Fatal error
Using self::
class Foo {
public $name = self::class;
}
$Foo = new Foo;
echo $Foo->name; // Foo
Please note that the Fatal error comment in the code i made doesn't indicate where the error happened, the error happened earlier before the object was instantiated as #Grapestain mentioned in the comments
Related
class A {
public $a = "BooMBa";
public function fun1() {
echo $this->a;
// echo (new self)->a;
}
}
class B extends A {
public static function fun2() {
return (new self)->fun1();
// return static::fun1();
}
}
B::fun2(); // returns BooMBa
If I change fun2() to return static::fun1() then it gives 'Fatal Error: Using $this when not in object context'
But if I change fun1 to echo (new self)->a; then works fine.
Can someone explain why static:: hate $this but not (new self).
PS: Please consider that I went through these below given Q&A sections and some more articles yet couldn't get an exact hold of this particular scenario that what's going on.
What does new self(); mean in PHP?
PHP : Difference b/w new self and new object()
PHP: The Basics Manual
in PHP, what is the difference between self and $this?
PPS: This Q&A PHP Fatal error: Using $this when not in object context has nothing to do with mine other than the same error message. It's totally different context. In that question he simply calls a non-static method statically. Meanwhile my question is more complex with late static bindings and keywords (new self). It's not possible at all to understand my problem with the answer in the above mentioned Q&A so please go through both Q&A before marking it duplicate. Thank you.
This questions comes to "what is difference between class and instance".
I will simplify your example and go step by step.
class A {
public $a = "BooMBa";
public function fun1() {
echo $this->a;
}
public static function fun2() {
return (new self)->fun1();
}
}
A::fun2(); // returns BooMBa
A::func2() - static call to A::func2
(new self)->fun1() - creates instance of A and calls fun1 of that instance
echo $this->a - echo contents of a of current(created in step 2) instance
Every call to A::func2 creates new instance of A in step 2
class A {
public $a = "BooMBa";
public function fun1() {
echo $this->a;
}
public static function fun2() {
return static::fun1();
}
}
A::fun2(); // fails
A::func2() - static call to A::func2
static::fun1() - static call to A::func1, there is no instance. AFAIK this should generate warning since you make static call to instance method
echo $this->a; - echo contents of a of current instance, but there is no instance since we came here from static call, we are in class scope. Error
class A {
public $a = "BooMBa";
public function fun1() {
echo (new self)->a;
}
public static function fun2() {
return static::fun1();
}
}
A::fun2(); // returns BooMBa
A::func2() - static call to A::func2
static::fun1() - static call to A::func1, there is no instance
echo (new self)->a - create new instance of A and echo contents of variable a of just created instance
Every call to A::func2 creates new instance of A in step 3
class A {
public $a = "BooMBa";
public function fun1() {
echo $this->a;
}
public function fun2() {
return $this->fun1();
}
}
$a = new A();
$a->fun2(); // returns BooMBa
$a = new A() - create new instance of A
$a->fun2() - call method fun2 of instance $a
$this->fun1() - call method fun1 of current instance ($a)
echo $this->a - echo contents of a of current instance ($a)
$this refers to current instance of class, but if you static call, there is no instance.
new self creates new instance of class which allows you to use $this since you have instance to refer to
Let's make example on cats. Instance of Cat is some $cat that stands in front of you. You can ask your $cat to purrr and since you refer to concrete instance of cat, inside of method purrr of that cat you can refer to $this and call echo $this->purrrSound.
When you make static call you make call to abstract concept of Cat, there is no particular instance of Cat and there is no $this to refer to.
class Cat {
public $purrrSound = "purrrrr...";
public function purrr() {
echo $this->purrrSound;
}
}
$cat = new Cat();
$cat->purrr(); // kittty purrrr, please?
// Cat::purrr(); // all the Cats in the universe, purrr now?
Static context
In PHP you can call method statically with The Scope Resolution Operator operator ::. So, this expression is just a static call:
return static::fun1()
When you're in a static context (after static call) $this doesn't work - it's a language assertion. Even in a static context this expression is still valid:
(new self)->a
Just because you're creting a new instance of object and then getting it's public property.
Deprecated note:
Caution In PHP 5, calling non-static methods statically generates an
E_STRICT level warning.
Warning In PHP 7, calling non-static methods statically is deprecated,
and will generate an E_DEPRECATED warning. Support for calling
non-static methods statically may be removed in the future.
To your consideration:
Consider not to use static methods, because it's a coupling for other classes, and it's usually just a procedural code closes in a static method. For example implement this function in a new class and use dependency injection if you need it.
I have some code:
class a {
public static function getCl() {
echo __CLASS__;
}
public function test() {
static::getCl();
}
}
class b extends a {
public static function getCl() {
echo __CLASS__;
}
}
$testClass = new b();
$testClass->test();
and this result : b. Then i try this:
class a {
public static function getCl() {
echo __CLASS__;
}
public function test() {
$this->getCl();
}
}
class b extends a {
public static function getCl() {
echo __CLASS__;
}
}
$testClass = new b();
$testClass->test();
this result is still b. I already know the different between static:: and self:: but can someone show me what is the different between static:: and $this-> in my code. Which one should i use?
Your context will produce the same result.
Here is simply description about both.
static:- refers late static binding 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.
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:
While 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 child class from parent class method. It was decided not to introduce a new keyword but rather use static that was already reserved.
$this:- refers current object.
Once inside an object's function, you have complete access to its variables, but to set them you need to be more specific than just using the variable name you want to work with. To properly specify you want to work with a local variable, you need to use the special $this variable, which PHP always sets to point to the object you are currently working with.
Why some developers create one method that returns new static? What is the reason to have a method that returns new static? I am not asking what is the difference between static and self, or what static & self mean. For example, here is one simple class:
<?php
class Expression
{
public static function make()
{
return new static;
}
public function find($value)
{
return '/' . $value .'/';
}
public function then($value)
{
return $this->find($value);
}
public function hi($value)
{
return "hi";
}
}
As you can see, there is a static method make() which returns new static. Then, some developers call other methods like this:
$regex = Expression::make()->find('www');
What is the purpose of this? I see that here we don't use new Expression syntax, and if that's the point - then why not make all methods static? What is the difference, what is the reason to have that one method that returns new static (while other methods are not static)?
new static instantiates a new object from the current class, and works with late static bindings (instantiates the subclass if the class was subclassed, I expect you understand that).
Having a static method on a class which returns a new instance of same is an alternative constructor. Meaning, typically your constructor is public function __construct, and typically it requires a certain bunch of parameters:
class Foo {
public function __construct(BarInterface $bar, array $baz = []) { ... }
}
Having an alternative constructor allows you to provide different defaults, or convenience shortcuts to instantiate this class without having to supply those specific arguments and/or for being able to provide different arguments which the alternative constructor will convert to the canonical ones:
class Foo {
public function __construct(BarInterface $bar, array $baz = []) { ... }
public static function fromBarString($bar) {
return new static(new Bar($bar));
}
public static function getDefault() {
return new static(new Bar('baz'), [42]);
}
}
Now, even though your canonical constructor requires a bunch of complex arguments, you can create a default instance of your class, which will probably be fine for most uses, simply with Foo::getDefault().
The canonical example in PHP for this is DateTime and DateTime::createFromFormat.
In your concrete example the alternative constructor doesn't actually do anything, so it's rather superfluous, but I expect that's because it's an incomplete example. If there's indeed an alternative constructor which does nothing other than new static, it's probably just meant as convenience syntax over (new Foo)->, which I find questionable.
Complete answer here
TLDR
get_called_class().
class A {
public static function get_self() {
return new self();
}
public static function get_static() {
return new static();
}
}
class B extends A {}
echo get_class(A::get_self()); // A
echo get_class(A::get_static()); // A
echo get_class(B::get_self()); // A
echo get_class(B::get_static()); // B
$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
Is there any difference in constructor or unified constructor. I have a class which have a constructor and a unified constructor. When i intialise object of the class then unified constructor call why not normal constructor.
<?php
class test {
function __construct() {
print "In BaseClass constructor\n";
}
function test() {
echo 'Class loeaded';
}
}
$obj = new test();
?>
OUTPUI
In BaseClass constructor
PHP Version 5.2.6
Since PHP 5, the best way to declare a constructor method in a class is to use the standardized
__construct()
So if you have
class myA {
public function __construct() {
echo "hello construct myA";
}
public function myA() {
echo "hello basic way myA";
}
}
$myA = new myA();
It will echo
hello construct myA
because the __constructor() has priority
But, for compatibility reason, the old way may work if there is not __construct() method.
And:
class myA {
//public function __construct() {
// echo "hello construct A";
//}
public function myA() {
echo "hello basic way myA";
}
}
$myA = new myA();
will give you:
hello basic way myA
In all cases, I advise you to use __construct()
the old constructor (method with class name) is only there for compatibility reasons. so if you have the new constructor (__construct) in the class php won't bother to call the old one.
edit
interesting note is that calling parent::__construct when the class being extended has only the old constructor type will still work (it becomes like a alias to the real constructor)
Classes which have a constructor method call this method on each newly-created object, so it is suitable for any initialization that the object may need before it is used.
Read documentation of constructor (link)
Instances of classes are created using the new keyword. What happens during the new call is that a new object is allocated with its own copies of the properties defined in the class you requested, and then the constructor of the object is called in case one was defined. The constructor is a method named __construct(), which is automatically called by the new keyword after creating the object. It is usually used to automatically perform various initializations such as property initializations. Constructors can also accept arguments, in which case, when the new statement is written, you also need to send the constructor the function parameters in between the parentheses.
In PHP 4, instead of using __construct() as the constructor’s name, you had to define a method with the classes’ names, like C++. This still works with PHP 5, but you should use the new unified constructor naming convention for new applications.
We could pass the names of the people on the new line in the following class example :
class Person {
function __construct($name)
{
$this->name = $name;
}
function getName()
{
return $this->name;
}
private $name;
};
$judy = new Person("Judy") . "\n";
$joe = new Person("Joe") . "\n";
print $judy->getName();
print $joe->getName();
Tip: Because a constructor cannot return a value, the most common practice for raising an error from within the constructor is by throwing an exception.
According to documentation As of PHP 5.3.3, methods with the same name as that of class will no longer be treated as constructor .. They are like regular methods ...
<?php
class myclass
{
public function myclass()
{
// treated as constructor in PHP 5.3.0-5.3.2
// treated as regular method as of PHP 5.3.3
}
}
?>
`
For backwards compatibility, if PHP 5 cannot find a __construct() function for a given class, and the class did not inherit one from a parent class, it will search for the old-style constructor function, by the name of the class.
It means that there if you have constructor myclass() and __construct .. then __construct will be searched for first and taken as constructor instead of myclass()
class myclass
{
public function myclass()
{
echo 'hello';
}
function __construct() {
print "new constructor"
}
}
$obj = new myclass(); // will echo new constructor