tags:

views:

40

answers:

2

I am using the magic __call method in PHP. Sometimes the function I call is a number. For example the class name is example, then sometimes I want to call example::32

Is this possible or should I look at another alternative.

A: 

No, this is not possible as 32 is not a valid property name. You will get a parse error like:

Parse error: syntax error, unexpected T_LNUMBER, expecting T_STRING or T_VARIABLE or '$' in …

Furthermore example::32 would refer to a static attribute and not a method (example::32() would if 32 would be a valid name, but you need to use __callStatic to fetch these calls).

If you want to access non-existing attributes, use the magic methods __get and __set instead.

Gumbo
no sorry I mean example->32()
Saif Bechan
@Saif Bechan: But why would you want to call such a method? What’s the purpose?
Gumbo
For example I have a class 'questions' with a method 'list'. This lists all the questions. questions->list(). Now I want to create a magic function __call. If I call questions->32() I want to display question with id 32.
Saif Bechan
@Saif Bechan: Well, the comprehensive way would be to name the method `get` or `getById` if there are more ways to get a question/several questions.
Gumbo
A: 

Sure it's possible. You just need to change the call syntax. $foo->32() is not valid and will give a fatal error. But $foo->{'32'}() is valid syntax. Now, you can't define a function 32, but you can use __call to execute it...

class Foo {
    public function __call($f, $args) {
        echo $f;
    }
}

$foo = new Foo;

$foo->32();  //Fatal Error

$foo->{32}(); //Fatal Error

$foo->{'32'}(); // "32" is printed

$x = 32;
$foo->$x(); //Fatal Error

$x = '32';
$foo->$x(); // "32" is printed

$x = 32;
$foo->{(string)$x}(); // "32" is printed

call_user_func(array($foo, '32')); // "32" is printed

Or in 5.3 with static methods, it gets a bit harder:

class Foo {
    public static function __callStatic($f, $args) {
        echo $f;
    }
}

Foo::32();  //Fatal Error
Foo::{32}(); //Fatal Error
Foo::{'32'}(); //Fatal Error

$x = 32;
Foo::$x(); //Fatal Error

$x = '32';
Foo::$x(); // "32" is printed

$x = 32;
Foo::{(string)$x}(); //Fatal Error

call_user_func(array('foo', '32')); //Fatal Error
ircmaxell
Do you have any idea if this works in combination with the function method_exists. this does not work: method_exists('Foo','32');
Saif Bechan
`method_exists()` only works with defined functions. So any call that would result in `__call()` being executed will return false...
ircmaxell
do you have any idea how I can check if the function is going to pass. Because I have to check if the function passes for some other methodes, not all are magic.
Saif Bechan
You don't need to check... In `__call()`, check if it can handle the method. If not, `throw new BadMethodCallException('This Function Does Not Exist');`. Then, just try{}catch(){} the exception. That way, you try to process it, and then if it fails, you know the method doesn't exist... Either that, or add a method `isCallable($name){}` that returns a bool. The body would be something like `return method_exists($this, $name) || in_array($this->methods);` where `$this->methods` contains all the methods that __call() can handle...
ircmaxell
I used is_callable and everything works great now. Thanks
Saif Bechan