class t {
public function tt()
{
echo 1;
}
}
t::tt();
See?The non-static function can also be called at class level.So what's different if I add a static keyword before public?
Except that, if you try to use $this in your method, like this :
class t {
protected $a = 10;
public function tt() {
echo $this->a;
echo 1;
}
}
t::tt();
You'll get a Fatal Error when calling the non-static method statically :
Fatal error: Using $this when not in object context in ...\temp.php on line 11
i.e. your example is a bit too simple, and doesn't really correspond to a real-case ;-)
Also note that your example should get you a strict warning (quoting) :
Calling non-static methods statically
generates an E_STRICT level warning.
And it actually does (At least, with PHP 5.3) :
Strict Standards: Non-static method t::tt() should not be called statically in ...\temp.php on line 12
1
So : not that good ;-)
Still, statically calling a non-static method doesnt't look like any kind of good practice (which is probably why it raises a Strict warning), as static methods don't have the same meaning than non-static ones : static methods do not reference any object, while non-static methods work on the instance of the class there're called on.
Once again : even if PHP allows you to do something (Maybe for historical reasons -- like compatibility with old versions), it doesn't mean you should do it !
The Static Keyword
Because static methods are callable without an instance of the object created, the pseudo-variable $this is not available inside the method declared as static.
Static properties cannot be accessed through the object using the arrow operator ->.
Calling non-static methods statically generates an E_STRICT level warning.
Just because you can call non-static methods statically doesn't mean you should. It's bad form.
In general a static method is also called class method while a non-static method is also called object method or instance method.
The difference between a class method and an object method is that class methods can only access class properties (static properties) while object methods are used to access object properties (properties of the very same class instance).
Static methods and properties are used to share common data over or for all instances of that specific class.
You could, for example, use a static property to keep track of the number of instances:
class A {
private static $counter = 0;
public function __construct() {
self::counter = self::counter + 1;
}
public function __destruct() {
self::counter = self::counter - 1;
}
public static function printCounter() {
echo "There are currently ".self::counter." instances of ".__CLASS__;
}
}
$a1 = new A();
$a2 = new A();
A::printCounter();
unset($a2);
A::printCounter();
Note that the static property counter is private so it can only be accessed by the class itself and instances of that class but not from outside.
A main difference that has not been mentioned relates to polymorphic behavior.
Non static methods, when redeclared in a derived class, override the base class method, and allow polymorphic behavior based on the type of the instance they are called on. This is not the case for static methods.
PHP 5.3 introduced the concept of late static binding which can be used to reference the called class in a context of static inheritance.
Yes, the critical difference is that methods declared static do not have access to the object-context variable, $this.
Additionally, invocation of a non-static method when not in object context will trigger an E_STRICT error event. When enabled, that event’s default behavior is to output a message to the error log (or STDERR), but it will allow the program to continue running.
Also, any attempt to reference $this when not in an object context will trigger an E_ERROR event. That event’s behavior is to output a message to the error log (or STDERR) and to exit the program with status 255.
For example:
<?php
error_reporting(-1);
//error_reporting(E_ALL);
class DualNature {
public static function fnStatic() {
if ( isset( $this ) ) {
// never ever gets here
$myValue = $this->_instanceValue;
} else {
// always gets here
$myValue = self::$_staticValue;
}
return $myValue;
}
public function fnInstance() {
if ( isset( $this ) ) {
// gets here on instance (->) reference only
$myValue = $this->_instanceValue;
} else {
// gets here in all other situations
$myValue = self::$_staticValue;
}
return $myValue;
}
public static function fnStaticDeath() {
return $this->_instanceValue;
}
private static $_staticValue = 'no access to $this';
private $_instanceValue = '$this is available';
}
$thing = new DualNature();
echo "==========\n";
printf("DualNature::fnStatic(): \"%s\"\n", DualNature::fnStatic() );
echo "==========\n";
printf("\$thing::fnStatic(): \"%s\"\n", $thing::fnStatic() );
echo "==========\n";
printf("\$thing->fnStatic(): \"%s\"\n", $thing->fnStatic() );
echo "==========\n";
printf("DualNature::fnInstance(): \"%s\"\n", DualNature::fnInstance() );
echo "==========\n";
printf("\$thing::fnInstance(): \"%s\"\n", $thing::fnInstance() );
echo "==========\n";
printf("\$thing->fnInstance(): \"%s\"\n", $thing->fnInstance() );
echo "==========\n";
printf("\$thing->fnStaticDeath(): \"%s\"\n", $thing->fnStaticDeath() );
echo "==========\n";
echo "I'M ALIVE!!!\n";
The output of the above is:
==========
PHP Strict Standards: Non-static method DualNature::fnInstance() should not be called statically in example.php on line 45
DualNature::fnStatic(): "no access to $this"
==========
$thing::fnStatic(): "no access to $this"
==========
$thing->fnStatic(): "no access to $this"
PHP Strict Standards: Non-static method DualNature::fnInstance() should not be called statically in example.php on line 47
==========
DualNature::fnInstance(): "no access to $this"
==========
$thing::fnInstance(): "no access to $this"
==========
$thing->fnInstance(): "$this is available"
==========
PHP Fatal error: Using $this when not in object context in example.php on line 29
Changing the error reporting level to E_ALL will suppress the default E_STRICT warning messages (the event will still be propagated), but the invalid reference to $this will still cause a fatal error and will exit the program.
Besides the syntax and functional differences there is also a performance difference that matters.
You can refer to this more or less detailed comparison of static and non-static methods in PHP.
Related
That's the problem, how can I call a class variable from a class function? Let me explain better:
<?php
class Mine
{
private $g = 'gg';
const COSTANTE = 'valo';
public static function sayHello()
{
echo self::COSTANTE;
echo '<br>';
echo $this->g;
}
}
$h = new Mine();
$h->sayHello();
$h::sayHello();
?>
when I run this, it just print the constant COSTANTE.... Why it doesn't print the variable g?
Turn on error reporting ( error_reporting ( E_ALL ); ), and you should receive the following error:
Fatal error: Using $this when not in object context
The pseudo-variable $this is a reference to the calling object, and is available from within an object context.
self is used to access the current class, since static functions can be called without the actual object instance, when the method is called statically $this reference does not exists.
A method declared as static can be accessed with an instantiated class object ( but it is always executed in a static context ), a property declared as static cannot.
valo will be printed but gg and will not.
The issue is because you have used a non-static variable in a static method which will raise a FATAL error and will stop execution. This is because there is no object context.
Its not encouraged to use non-static variable inside static methods but, in case you need to use one, you have to create an object first.
Your sayHello function will be something like
public static function sayHello()
{
echo self::COSTANTE;
echo '<br>';
$mineObject = new Mine;
echo $mineObject->g;
}
I will also suggest keep error reporting and display errors ON while developing so that you can have a better idea of whats happening out there.
error_reporting(E_ALL);
ini_set('display_errors', 'ON');
I'm not so sure what the following object instantiation is called but it comes from a article that i'm reading.
class foo
{
function out()
{
return 'hello';
}
}
echo (new foo())->out();
The object is instantiated automatically and calls the out method. But what i dont really understand is when i rename the out() method into a fictitious method i get an error like this:
example:
class foo
{
function out()
{
return 'hello';
}
}
echo (new foo())->ou();
Fatal error: Call to undefined method foo::ou() in ...
Is this method somehow being called as a static method?
The :: does not stand for static method, this is a missconception. The :: is a "scope resolution operator", it denotes the identification of a method by its class predicated full name.
So this simply means: "method 'ou' as defined by class 'foo'". Not more, not less.
No. The error just indicates that the method doesn't exist. It always shows the :: for this error, no matter whether you call the method in a static way or not. You would get the same error if you changed the code to:
$foo = new foo();
echo $foo->ou();
Second code example as per request in comments:
$moo = new moo(); // Parentheses optional, I guess
$foo = new foo($moo);
$foo->out();
Why can't I use a method non-static with the syntax of the methods static(class::method) ? Is it some kind of configuration issue?
class Teste {
public function fun1() {
echo 'fun1';
}
public static function fun2() {
echo "static fun2" ;
}
}
Teste::fun1(); // why?
Teste::fun2(); //ok - is a static method
PHP is very loose with static vs. non-static methods. One thing I don't see noted here is that if you call a non-static method, ns statically from within a non-static method of class C, $this inside ns will refer to your instance of C.
class A
{
public function test()
{
echo $this->name;
}
}
class C
{
public function q()
{
$this->name = 'hello';
A::test();
}
}
$c = new C;
$c->q();// prints hello
This is actually an error of some kind if you have strict error reporting on, but not otherwise.
This is a known "quirk" of PHP. It's by design to prevent back-propagation for figuring out if some time ago we actually instantiated an object or not (remember, PHP is interpreted, not compiled). However, accessing any non-static member the via scope resolution operator if the object is not instantiated will issue a fatal error.
Courtesy of PHP.net:
class User {
const GIVEN = 1; // class constants can't be labeled static nor assigned visibility
public $a=2;
public static $b=3;
public function me(){
echo "print me";
}
public static function you() {
echo "print you";
}
}
class myUser extends User {
}
// Are properties and methods instantiated to an object of a class, & are they accessible?
//$object1= new User(); // uncomment this line with each of the following lines individually
//echo $object1->GIVEN . "</br>"; // yields nothing
//echo $object1->GIVE . "</br>"; // deliberately misnamed, still yields nothing
//echo $object1->User::GIVEN . "</br>"; // yields nothing
//echo $object1->a . "</br>"; // yields 2
//echo $object1->b . "</br>"; // yields nothing
//echo $object1->me() . "</br>"; // yields print me
//echo $object1->you() . "</br>"; // yields print you
// Are properties and methods instantiated to an object of a child class, & are accessible?
//$object2= new myUser(); // uncomment this line with each of the following lines individually
//echo $object2->GIVEN . "</br>"; // yields nothing
//echo $object2->a . "</br>"; // yields 2
//echo $object2->b . "</br>"; // yields nothing
//echo $object2->me() . "</br>"; // yields print me
//echo $object2->you() . "</br>"; // yields print you
// Are the properties and methods accessible directly in the class?
//echo User::GIVEN . "</br>"; // yields 1
//echo User::$a . "</br>"; // yields fatal error since it is not static
//echo User::$b . "</br>"; // yields 3
//echo User::me() . "</br>"; // yields print me
//echo User::you() . "</br>"; // yields print you
// Are the properties and methods copied to the child class and are they accessible?
//echo myUser::GIVEN . "</br>"; // yields 1
//echo myUser::$a . "</br>"; // yields fatal error since it is not static
//echo myUser::$b . "</br>"; // yields 3
//echo myUser::me() . "</br>"; // yields print me
//echo myUser::you() . "</br>"; // yields print you
?>
This is PHP 4 backwards compatibility. In PHP 4 you could not differ between an object method and the global function written as a static class method. Therefore both did work.
However with the changes in the object model with PHP 5 - http://php.net/oop5 - the static keyword has been introduced.
And then since PHP 5.1.3 you get proper strict standard warnings about those like:
Strict Standards: Non-static method Foo::bar() should not be called statically
And/Or:
Strict Standards: Non-static method Foo::bar() should not be called statically, assuming $this from incompatible context
which you should have enabled for your development setup. So it's merely backwards compatibility to a time where the language couldn't differ enough so this was "defined" at run-time.
Nowadays you can define it already in the code, however the code will not break if you still call it "wrong".
Some Demo to trigger the error messages and to show the changed behavior over different PHP versions: http://3v4l.org/8WRQH
PHP 4 did not have a static keyword (in function declaration context) but still allowed methods to be called statically with ::. This continued in PHP 5 for backwards compatibility purposes.
You can do this, but your code will error if you use $this in the function called fun1()
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.
Link
Starting on PHP8, this no longer works.
The ability to call non-static methods statically was finally removed in PHP 8.
The ability to call non-static methods statically has been removed. Thus is_callable() will fail when checking for a non-static method with a classname (must check with an object instance).
It was originally deprecated on PHP 7.
Static calls to methods that are not declared static are deprecated, and may be removed in the future.
In most languages you will need to have an instance of the class in order to perform instance methods. It appears that PHP will create a temporary instance when you call an instance method with the scope resolution operator.
Not sure why PHP allows this, but you do not want to get into the habit of doing it. Your example only works because it does not try to access non-static properties of the class.
Something as simple as:
<?php
class Foo {
private $color;
public function bar() {
echo 'before';
$this->color = "blue";
echo 'after';
}
}
Foo::bar();
would result in a fatal error
I have noticed that if you call non-static method self::test() from within a class, no warning for strict standard will be issued, like when you call Class::test(). I believe that this is not related to LSB, since my class was not extended (tested on php 5.5)?
One way for calling the same method both statically and non-statically is using the magic methods __call and __callStatic.
The FluentMath class (code down below) is an example where you can invoke the methods add or subtract both statically and not:
$res1 = FluentMath::add(5) // add method called statically
->add(3) // add method called non-statically
->subtract(2)
->result();
$res2 = FluentMath::subtract(1)->add(10)->result();
FluentMath class
class FluentMath
{
private $result = 0;
public function __call($method, $args)
{
return $this->call($method, $args);
}
public static function __callStatic($method, $args)
{
return (new static())->call($method, $args);
}
private function call($method, $args)
{
if (! method_exists($this , '_' . $method)) {
throw new Exception('Call undefined method ' . $method);
}
return $this->{'_' . $method}(...$args);
}
private function _add($num)
{
$this->result += $num;
return $this;
}
private function _subtract($num)
{
$this->result -= $num;
return $this;
}
public function result()
{
return $this->result;
}
}
If you want the full explanation of how that class works please check:
https://www.danielefavi.com/blog/php-fluent-api-class
https://github.com/danielefavi/php-fluent-api-class/
Why can't I use a method non-static with the syntax of the methods static(class::method) ? Is it some kind of configuration issue?
class Teste {
public function fun1() {
echo 'fun1';
}
public static function fun2() {
echo "static fun2" ;
}
}
Teste::fun1(); // why?
Teste::fun2(); //ok - is a static method
PHP is very loose with static vs. non-static methods. One thing I don't see noted here is that if you call a non-static method, ns statically from within a non-static method of class C, $this inside ns will refer to your instance of C.
class A
{
public function test()
{
echo $this->name;
}
}
class C
{
public function q()
{
$this->name = 'hello';
A::test();
}
}
$c = new C;
$c->q();// prints hello
This is actually an error of some kind if you have strict error reporting on, but not otherwise.
This is a known "quirk" of PHP. It's by design to prevent back-propagation for figuring out if some time ago we actually instantiated an object or not (remember, PHP is interpreted, not compiled). However, accessing any non-static member the via scope resolution operator if the object is not instantiated will issue a fatal error.
Courtesy of PHP.net:
class User {
const GIVEN = 1; // class constants can't be labeled static nor assigned visibility
public $a=2;
public static $b=3;
public function me(){
echo "print me";
}
public static function you() {
echo "print you";
}
}
class myUser extends User {
}
// Are properties and methods instantiated to an object of a class, & are they accessible?
//$object1= new User(); // uncomment this line with each of the following lines individually
//echo $object1->GIVEN . "</br>"; // yields nothing
//echo $object1->GIVE . "</br>"; // deliberately misnamed, still yields nothing
//echo $object1->User::GIVEN . "</br>"; // yields nothing
//echo $object1->a . "</br>"; // yields 2
//echo $object1->b . "</br>"; // yields nothing
//echo $object1->me() . "</br>"; // yields print me
//echo $object1->you() . "</br>"; // yields print you
// Are properties and methods instantiated to an object of a child class, & are accessible?
//$object2= new myUser(); // uncomment this line with each of the following lines individually
//echo $object2->GIVEN . "</br>"; // yields nothing
//echo $object2->a . "</br>"; // yields 2
//echo $object2->b . "</br>"; // yields nothing
//echo $object2->me() . "</br>"; // yields print me
//echo $object2->you() . "</br>"; // yields print you
// Are the properties and methods accessible directly in the class?
//echo User::GIVEN . "</br>"; // yields 1
//echo User::$a . "</br>"; // yields fatal error since it is not static
//echo User::$b . "</br>"; // yields 3
//echo User::me() . "</br>"; // yields print me
//echo User::you() . "</br>"; // yields print you
// Are the properties and methods copied to the child class and are they accessible?
//echo myUser::GIVEN . "</br>"; // yields 1
//echo myUser::$a . "</br>"; // yields fatal error since it is not static
//echo myUser::$b . "</br>"; // yields 3
//echo myUser::me() . "</br>"; // yields print me
//echo myUser::you() . "</br>"; // yields print you
?>
This is PHP 4 backwards compatibility. In PHP 4 you could not differ between an object method and the global function written as a static class method. Therefore both did work.
However with the changes in the object model with PHP 5 - http://php.net/oop5 - the static keyword has been introduced.
And then since PHP 5.1.3 you get proper strict standard warnings about those like:
Strict Standards: Non-static method Foo::bar() should not be called statically
And/Or:
Strict Standards: Non-static method Foo::bar() should not be called statically, assuming $this from incompatible context
which you should have enabled for your development setup. So it's merely backwards compatibility to a time where the language couldn't differ enough so this was "defined" at run-time.
Nowadays you can define it already in the code, however the code will not break if you still call it "wrong".
Some Demo to trigger the error messages and to show the changed behavior over different PHP versions: http://3v4l.org/8WRQH
PHP 4 did not have a static keyword (in function declaration context) but still allowed methods to be called statically with ::. This continued in PHP 5 for backwards compatibility purposes.
You can do this, but your code will error if you use $this in the function called fun1()
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.
Link
Starting on PHP8, this no longer works.
The ability to call non-static methods statically was finally removed in PHP 8.
The ability to call non-static methods statically has been removed. Thus is_callable() will fail when checking for a non-static method with a classname (must check with an object instance).
It was originally deprecated on PHP 7.
Static calls to methods that are not declared static are deprecated, and may be removed in the future.
In most languages you will need to have an instance of the class in order to perform instance methods. It appears that PHP will create a temporary instance when you call an instance method with the scope resolution operator.
Not sure why PHP allows this, but you do not want to get into the habit of doing it. Your example only works because it does not try to access non-static properties of the class.
Something as simple as:
<?php
class Foo {
private $color;
public function bar() {
echo 'before';
$this->color = "blue";
echo 'after';
}
}
Foo::bar();
would result in a fatal error
I have noticed that if you call non-static method self::test() from within a class, no warning for strict standard will be issued, like when you call Class::test(). I believe that this is not related to LSB, since my class was not extended (tested on php 5.5)?
One way for calling the same method both statically and non-statically is using the magic methods __call and __callStatic.
The FluentMath class (code down below) is an example where you can invoke the methods add or subtract both statically and not:
$res1 = FluentMath::add(5) // add method called statically
->add(3) // add method called non-statically
->subtract(2)
->result();
$res2 = FluentMath::subtract(1)->add(10)->result();
FluentMath class
class FluentMath
{
private $result = 0;
public function __call($method, $args)
{
return $this->call($method, $args);
}
public static function __callStatic($method, $args)
{
return (new static())->call($method, $args);
}
private function call($method, $args)
{
if (! method_exists($this , '_' . $method)) {
throw new Exception('Call undefined method ' . $method);
}
return $this->{'_' . $method}(...$args);
}
private function _add($num)
{
$this->result += $num;
return $this;
}
private function _subtract($num)
{
$this->result -= $num;
return $this;
}
public function result()
{
return $this->result;
}
}
If you want the full explanation of how that class works please check:
https://www.danielefavi.com/blog/php-fluent-api-class
https://github.com/danielefavi/php-fluent-api-class/
Up until the yesterday I though that both of these methods for accessing a class where identical. Google turned up noting (either that or my keywords were bad). What is the difference between accessing a class by defining a new instance of the class rather than just calling the class methods directly.
I hardly understood what I just ask, since I have not a clue what I'm asking but allow me to give a few examples to help out.
For as long as I have been using classes in PHP I have been defining a instance of the class then accessing the methods from that variable. Here is an example:
<?php
class Myclass
{
public function my_method() {
return "This is my method";
}
}
$myclass = new Myclass();
echo $myclass->my_method(); // output: This is my method
?>
What is the difference between that and doing this?
<?php
class Myclass
{
public function my_method() {
return "This is my method";
}
}
echo Myclass::my_method(); // output: This is my method
?>
I hope I was clear enough. If not a brief synopsis would be - What is the difference between creating a new instance of a class then calling a method of the class with "$class->mymethod();," or just directly calling the method like so: "Myclass::mymethod();"?
Thanks in advance.
The :: notation is used to call the function as static. See these pages from the PHP manual for more info:
http://www.php.net/manual/en/language.oop5.paamayim-nekudotayim.php
http://php.net/manual/en/language.oop5.static.php.
In essence, static functions are just like regular functions outside classes. The function is not in object context when called as such, so the pseudo-variable $this is not available.
Note that the function should be declared as static if you are planning on calling it as such:
class SomeClass {
static public function StaticFunction() {
...
}
}
The Myclass::my_method() call should be throwing an E_STRICT warning, as you're calling a non-static method in a static context.
Static methods are methods that belong to the class rather than to the instance. These methods cannot access any non-static variables, as they have no reference for them (because non-static variables belong to the instance, not the class).
After using Java and C#, I'm mildly disturbed that this isn't considered an E_WARNING or E_ERROR, particularly since E_STRICT is not logged by default.
First, you should understand the difference between a class and an object, or a class and an instance of a class.
For example, where class is "Circle", an instance might be "this particular circle". Class Circle might have members $center and $radius - every point has these. But the values of these are different for every point.
$class->mymethod() is a call to an instance method, for instance $circle->Length(). You are saying something to a particular instance of an object. This method will have access to class members - variables that belong to the instance. In PHP you gain access to these instance variables using keyword $this.
For instance $circle->Length() might be implemented as return 2*Pi*$this->radius;
What happens when you say Circle::Length()? Nothing. This is syntax for calling static methods. Because you did not say which circle. Circle as a class does not have length.
Static method is declared with keyword static. Whatever it does it has no access to any instances of the class. It's something that a class as a whole does.
For instance, if you want to calculate length of the circle without actually creating one, then there might be static function calculateLength($radius) in the class circle. And you would call it as Circle::calculateLength($myRadius)
In my opinion you should not even think about static methods until you understand the non-static ones.
http://www.php.net/manual/en/language.oop5.paamayim-nekudotayim.php
I don't think you can call methods that way. I thought that was how you called static members of the class.
In my understanding when you create an instance of the class you are creating an object and so you call methods/properties from that object.
When you call a method/property via a static call you are calling on the class itself.
So if you have something like this:
class acs {
public $var = 'bla';
}
and then you do
$a = new acs();
$b = new acs();
echo $a->var . '<br>';
echo $b->var . '<br>';
$a->var = 'hey';
$b->var = 'Yooo';
echo $a->var . '<br>';
echo $b->var . '<br>';
You now have 2 instances of class acs which started with the same values but now have different values.
But if you have this:
class acs {
public static $var = 'bla';
}
And then do:
$a = new acs();
$b = new acs();
echo $a->var . '<br>';
echo $b->var . '<br>';
$a->var = 'hey';
$b->var = 'Yooo';
echo $a->var . '<br>';
echo $b->var . '<br>';
echo acs::$var;
What you are doing is:
You create the instances as before.
You echo nothing, because the public property var does not exist.
You create the public property var in both the instances
You echo their values (hey and Yoo)
You echo the static property var (which is 'bla' and has not changed)
Hope this helps!