PHP: What if I call a static method in non-static way
As Baba already pointed out, it results in an E_STRICT
depending on your configuration.
But even if that's no problem for you, I think it's worth mentioning some of the pitfalls which may result from calling static methods in a non-static way.
If you have a class hierarchy like
class A {
public static function sayHello() {
echo "Hello from A!\n";
}
public function sayHelloNonStaticWithSelf() {
return self::sayHello();
}
public function sayHelloNonStaticWithStatic() {
return static::sayHello();
}
}
class B extends A {
public static function sayHello() {
echo "Hello from B!\n";
}
public function callHelloInMultipleDifferentWays() {
A::sayHello();
B::sayHello();
$this->sayHelloNonStaticWithSelf();
$this->sayHelloNonStaticWithStatic();
$this->sayHello();
}
}
$b = new B();
$b->callHelloInMultipleDifferentWays();
This produces the following output:
Hello from A!
// A::sayHello() - obvious
Hello from B!
// B::sayHello() - obvious
Hello from A!
// $this->sayHelloNonStaticWithSelf()
// self alweays refers to the class it is used in
Hello from B!
// $this->sayHelloNonStaticWithStatic()
// static always refers to the class it is called from at runtime
Hello from B!
// $this->sayHello() - obvious
As you can see, it's easy to achieve unexpected behaviour when mixing static and non-static method calls and techniques.
Therefore, my advice also is:
Use Class::method to explicitly call the static method you mean to call.
Or even better don't use static methods at all because they make your code untestable.
How to call non-static method from static method of same class?
You must create a new object inside the static method to access non-static methods inside that class:
class Foo {
public function fun1()
{
return 'non-static';
}
public static function fun2()
{
return (new self)->fun1();
}
}
echo Foo::fun2();
The result would be non-static
Later edit: As seen an interest in passing variables to the constructor I will post an updated version of the class:
class Foo {
private $foo;
private $bar;
public function __construct($foo, $bar)
{
$this->foo = $foo;
$this->bar = $bar;
}
public function fun1()
{
return $this->foo . ' - ' . $this->bar;
}
public static function fun2($foo, $bar)
{
return (new self($foo, $bar))->fun1();
}
}
echo Foo::fun2('foo', 'bar');
The result would be foo - bar
How to call a non-static method from a static function in a class in php
Just create an instance:
public static function staticFun ($data) {
$instance = new ClassName($data);
echo $instance->anotherFun($data);
}
Note: you have a parameter $data
for anotherFun
, but you don't use it anywhere.
PHP Call non static function with static way
You will get Strict standards: Non-static method test::hello() should not be called statically
and your Class declaration is not good, right way is this
class test
{
public function hello()
{
return "say hello";
}
}
class foo
{
public function __construct()
{
echo test::hello();
}
}
$foo = new foo();
Laravel uses Facade
to give illusion that you are using static
method, you can also use Facade
to call method like test::hello();
Here is a good read on Facade
php calling a non static method from a static method
It doesn't make any sense to want to call a non-static method from a static one. To call a non-static method, you need an object instance. When you call a method statically, you have no object instance. I hope the discrepancy is obvious.
The point of non-static methods is that they have access to instance-specific data:
class Foo {
public $bar;
public function baz() {
echo $this->bar;
}
}
$a = new Foo;
$b = new Foo;
$a->bar = 'Hello';
$b->bar = 'World';
$a->baz();
$b->baz();
The $this
keyword is the special sauce here. Since you do not have an object instance in a static method, i.e. no $this
, you cannot call a non-static method:
Foo::baz(); // now what?
If your function uses $this
and requires an object instance, you cannot call it statically. If your function does not use $this
and does not require an object instance, make it static
and call it statically.
Make static out of non-static (Magic Method)
It will not work because you cannot call non static methods statically.
The reason why it works with methods like get()
is because these calls are being delegated to the query instance - they don't actually exist on the model itself.
If you check __call
method, it should all become a bit more clear:
public function __call($method, $parameters)
{
if (in_array($method, ['increment', 'decrement'])) {
return $this->$method(...$parameters);
}
return $this->newQuery()->$method(...$parameters);
}
So even though the default __callStatic
method implementation calls the non static method on itself:
public static function __callStatic($method, $parameters)
{
return (new static)->$method(...$parameters);
}
Your code would fail straight away, because your model would actually contain the public
non-static method with the same name.
You'll see that the __call
method checks whether the name of the method is within the array of increment
and decrement
- and if it is - it calls them.
protected function increment($column, $amount = 1, array $extra = [])
{
return $this->incrementOrDecrement($column, $amount, $extra, 'increment');
}
protected function decrement($column, $amount = 1, array $extra = [])
{
return $this->incrementOrDecrement($column, $amount, $extra, 'decrement');
}
Both of these methods are actually non-static on the instance of the model, but their visibility is set to protected
so you wouldn't be able to call them on the instance of the model anyway - the only way to access them is using magic methods - in this case static call will work just fine.
In other words, if you change visibility of your method to protected
and overwrite the __call
method to also include your method name in the array, then your code should work
protected function callThis()
{
return 'Yo';
}
public function __call($method, $parameters)
{
if (in_array($method, ['increment', 'decrement', 'callThis'])) {
return $this->$method(...$parameters);
}
return $this->newQuery()->$method(...$parameters);
}
Hope this helps.
Related Topics
Pdoexception' with Message 'Sqlstate[22001]: String Data, Right Truncated: 0
Serial Comm with PHP on Windows
Retrieving Get and Post Data Inside Laravel Controller
Loop Through Wordpress Posts, and Wrap Each X Post in a Div
Given an Email as Raw Text, How to Send It Using PHP
Convert a Big Integer to a Full String in PHP
Php: Remote Function Call and Returning the Result
Woocommerce - Overriding Billing State and Post Code on Existing Checkout Fields
No Database Selected - PHP & MySQL
How to Disable PHP Magic Quotes at Runtime
PHP - Fastest Way to Check Presence of Text in Many Domains (Above 1000)
Mysql_Data_Seek Pdo Equivalent
How to Merge Subarray Values and Remove Duplicates
Can You Pass by Reference While Using the Ternary Operator
Getimagesize() Not Returning False When It Should
Fatal Error: Unsupported Operand Types
Warning: File_Get_Contents: Failed to Open Stream: Redirection Limit Reached, Aborting