Having Issues with Magic Static Functions - php

I have a class that I'm trying to create a function that will call a static method that is run through a magic method. The thing is the functions work as long as they are from different types of classes than the class calling them, but if I call a static function of the same class all the function will return is 1.
class Test {
public function static __callStatic($name, $params) {
return 2;
}
public function __call($name, $params) {
return 1;
}
public function Test1() {
return Test::GetTwo();
}
}
class Test2 {
public function Test() {
return Test::GetTwo();
}
}
$t = new Test();
echo $t->Test1(); //prints 1 should be 2
$t2 = new Test2();
echo $t->Test(); //prints 2 as it should
even if the static method GetTwo() returns an object I still get 1 if I'm calling a function in the same scope as Test1(). Any one else run into this?

echo Test::Test1();
You don't need (nor should use) an instance to call a static method. Use the class and the scope resolution operator (::) to do the call.
If you need late static binding use static::Test1();
For an method call on an instance, PHP will try the following:
Find an instance method named X.
Find a magic method __call.
Find a class (static) method named X.
Find a magic class (static) method __callStatic.
In your case, it finds __call at step 2 and goes with that.

Related

How to access non-static method from within a static method?

I have two methods in a class, one of which is static. I want to access the non-static method from within the static method. Is that possible? I tried this:
class Foo {
public function qux(){
}
public static function waldo(){
self::qux(); // Non-static method Foo::qux() should not be called statically
}
}
Is making qux a static method the only way to achieve this? What if the user doesn't want qux() to be a static method?
This should work as you need:
class Foo {
public function qux(){
}
public static function waldo(){
$foo = new Foo();
$foo->qux();
}
}
There is no other way to call a dynamic method/function without creating the object itself first.
Of course, if you will use the object only one-time and call all methods or functions immediately, you could use something like this:
class Foo {
public function qux(){
}
public static function waldo(){
(new Foo())->qux();
}
}
class Foo {
public function qux(){
}
public static function waldo(){
$obj = new Static();
$obj->qux();
}
}

Notify on class call - php

I want a function that will be called every time a class is referenced (called).
The magic function autoload does a similar thing, but works only if the referenced class doesn't exist.
I want to make a function that will work in any case.
For example:
<?php
class Foo {
static function bar () {
...
}
}
function __someMagicFunction ($name) {
echo 'You called class ' . $name;
}
Foo::bar(); // Output: You called class Foo
I want the output to be "You called class Foo".
How can i do it?
Thanks :)
Well, there's no easy way to do this, but it is possible. Still, the way you'll have to go about achieving this is not to be recommended, as it will result in slow code. However, here's a simple way to do this:
class Foo
{
//protected, not public
protected static function bar ()
{
}
protected function nonStaticBar()
{
}
public function __call($method, array $args)
{
//echoes you called Foo::nonStaticBar
printf('You called %s::%s', get_class($this), $method);
//perform the actual call
return call_user_func_array([$this, $method], $args);
}
//same, but for static methods
public static function __callStatic($method, array $args)
{
$calledClass = get_called_class();//for late static binding
printf('You called %s::%s statically', $calledClass, $method);
return call_user_func_array($calledClass . '::' . $method, $args);
}
}
$foo = new Foo;
$foo->nonStaticBar();//output: You called Foo::nonStaticBar
Foo::bar();//output: You called Foo::bar statically
The reason for __callStatic using get_called_class rather than get_class(self); is that it enables you to declare the magic methods as final, and still have them work as expected in child classes:
class Foobar extends Foo
{}
Foobar::bar();//output: You called Foobar::bar statically
demo
more details on magic methods:
The docs, of course
some previous answers of mine explaining why __call & co are slow
and why you should predeclare properties (same reason as why __call is slow) here
use
public function __construct(){
}

PHP return object instance from __getStatic()

PHP has a magic method __getStatic() that allows overloading of static method calls. I have a class with a fluent interface which performs integrity checks. I call it like this:-
$check = new CheckSomeCondition();
$check->forActive()->sites(array(1,2,3))->check();
However, I would like to call it like this:-
CheckSomeCondition::forActive()->sites(array(1,2,3))->check();
I thought that having this magic method in my base class would allow me to do this:-
public static function __callStatic($method, $args)
{
$instance = new self();
return call_user_func_array(array($instance, $method), $args);
}
But new self() produces an instance of the class that the calling code is in, and not the class which __callStatic() exists in, why is this? and how can I get around it?
I have also tried new static and this does the same thing.
I know this must be possible because Laravel's QueryBuilder has an interface like DB::table()->... and this uses method chaining, returning object instances, not static classes. I have had a look at the Laravel code, but I think they create the instances somewhere else in the application and they are stored in a class member ready to be returned.
The magic method __callStatic is only called for methods which don't exist, so in this case it will simply not run.
Consider the following simplified example:
class Foo
{
public function bar()
{
echo "Running instance method bar()";
}
public static function __callStatic($method, $args)
{
echo "__callStatic called for non-existent method $method";
}
}
Foo::bar();
If you run this (here's an online demo) you will see that it is the "real" bar() method that is called.
There can only be one method named bar on the class, so PHP's only other option would be to complain that bar() should be static - which it does, but non-fatally.
The reason you see an instance of the calling class is not that $instance is instantiated with the wrong class, but because when your method is called non-statically, $this "leaks" from the enclosing scope.
In the following example, $this ends up being the instance of Bar:
class Foo
{
public function doSomething()
{
echo get_class($this);
}
}
class Bar
{
public function doSomethingElse()
{
Foo::doSomething();
}
}
$bar = new Bar();
$bar->doSomethingElse();
Live Demo
As #IMSoP pointed out, __getStatic() is only called if there is no method with the name called - not just if there isn't a static method with the name.
So the workaround to allow calls such as CheckClass::forActive->sites() is to give all the non static method names a prefix such as '_' and have a magic method __call() which will add the prefix in.
This means if I do CheckClass::forActive() the method forActive() doesn't exist, so __getStatic() will be called and will create an instance of the object and try to call the desired method. But the method doesn't exist because we've prefix it, so PHP will call the __call() magic method which will add the prefix and call the prefixed method.
So the 2 functions are:-
public static function __callStatic($method, $args)
{
$instance = new self;
return call_user_func_array(array($instance, $method), $args);
}
public static function __call($method, $args)
{
$method = 'prefix_' . $method;
return call_user_func_array(array($instance, $method), $args);
}
// Then all our method names need to be prefixed, like so:-
public static function prefix_SomeMethod($method, $args)
{
// Do something
return $this;
}

Static and Non-Static Calling in PHP

ok I have this code, that I'm studying
class scope{
function printme(){
return "hello";
}
public static function printme(){
return "hello";
}
}
$s = new scope();
echo $s->printme(); //non-static call
echo "<br>";
echo scope::printme(); //static call
Now, this is not really the code of my project but these are the things I want to do
I want to create a class the will contain static and non-static functions.
I want a function to be available both on static and non-static calls.
As non-static function has a lot of operations on it, I also need to call it as a static function so that I will not need to instantiate the class. Is this possible? or I really needed to rewrite the function to another function or class?
NOTE: tell me if I'm doing some bad programming already.
Here is the rule:
A static method can be used in both static method and non-static method.
A non-static method can only be used in a non-static method.
If the instance of your class is rarely needed, you can have the static method create an instance, call the non-static method and return the value.
class Scope {
public function mynonstatic() {
}
public static function mystatic() {
$s = new Scope();
return $s->mynonstatic();
}
}
Remember that a static method is really just a global function with reduced scope. They are useful, but are should not be created without good reason.
As non-static function has a lot of operations on it, I also need to
call it as a static function so that I will not need to instantiate
the class. Is this possible? or I really needed to rewrite the
function to another function or class?
If you need it static, then make it static. If you need it not, then keep it the way it is. It is possible from within non-static function to call static function.
class Foo
{
public function bar()
{
Foo::zex();
// or self::zex() or even $this->zex();
}
public static function zex()
{
}
}
$foo = new Foo;
$foo->bar();
Ant the other way around.
class Foo
{
public function bar()
{
}
public static function zex()
{
$foo = new Foo;
$foo->bar();
}
}
When you should do it or should you do it at all is another question. The most common use of the latter is probably the Singleton pattern.

call a static method inside a class?

how do i call a static method from another method inside the same class?
$this->staticMethod();
or
$this::staticMethod();
self::staticMethod();
More information about the Static keyword.
Let's assume this is your class:
class Test
{
private $baz = 1;
public function foo() { ... }
public function bar()
{
printf("baz = %d\n", $this->baz);
}
public static function staticMethod() { echo "static method\n"; }
}
From within the foo() method, let's look at the different options:
$this->staticMethod();
So that calls staticMethod() as an instance method, right? It does not. This is because the method is declared as public static the interpreter will call it as a static method, so it will work as expected. It could be argued that doing so makes it less obvious from the code that a static method call is taking place.
$this::staticMethod();
Since PHP 5.3 you can use $var::method() to mean <class-of-$var>::; this is quite convenient, though the above use-case is still quite unconventional. So that brings us to the most common way of calling a static method:
self::staticMethod();
Now, before you start thinking that the :: is the static call operator, let me give you another example:
self::bar();
This will print baz = 1, which means that $this->bar() and self::bar() do exactly the same thing; that's because :: is just a scope resolution operator. It's there to make parent::, self:: and static:: work and give you access to static variables; how a method is called depends on its signature and how the caller was called.
To see all of this in action, see this 3v4l.org output.
This is a very late response, but adds some detail on the previous answers
When it comes to calling static methods in PHP from another static method on the same class, it is important to differentiate between self and the class name.
Take for instance this code:
class static_test_class {
public static function test() {
echo "Original class\n";
}
public static function run($use_self) {
if($use_self) {
self::test();
} else {
$class = get_called_class();
$class::test();
}
}
}
class extended_static_test_class extends static_test_class {
public static function test() {
echo "Extended class\n";
}
}
extended_static_test_class::run(true);
extended_static_test_class::run(false);
The output of this code is:
Original class
Extended class
This is because self refers to the class the code is in, rather than the class of the code it is being called from.
If you want to use a method defined on a class which inherits the original class, you need to use something like:
$class = get_called_class();
$class::function_name();
In the later PHP version self::staticMethod(); also will not work. It will throw the strict standard error.
In this case, we can create object of same class and call by object
here is the example
class Foo {
public function fun1() {
echo 'non-static';
}
public static function fun2() {
echo (new self)->fun1();
}
}
call a static method inside a class
className::staticFunctionName
example
ClassName::staticMethod();

Categories