Problem with the magic method __call

Asked

Viewed 167 times

7

I’m trying to use the magic method __call and the function call_user_func_array to recover the method name to be able to upload a file. I am doing it as follows

//Classe que importa os objetos

$obj = 'NovoObjeto';

$metodo = 'importarXML';

$objCriado = new $obj();

$objCriado->$metodo();

Each object of mine extends from a class called FullObject and in that class I have the following statement of the magical method:

//FullObject
function __call($name,$arguments = null) {
    if(method_exists($this, $name)) { 
        $this->method = $name;
        return call_user_func_array(array($this,$name),$arguments);
    } else {
        throw new Exception('erro');
    }
}

//Classo NovoObjeto
class NovoObjeto extends FullObject {
    function importarXML() { ... }
}

The problem that happens is that if there is no method, it launches a Exception, but if there is the method it does not pass the method name to the property $this->method.

And I need to save this name, because I will be using it elsewhere, but I want to avoid having to pass it always as a parameter.

  • 1

    "I’m trying to use the magic method __calle the call_user_func_array function to retrieve the method name to load a file." - It was not clear what you want to do, could explain better what you want?

2 answers

9


Your problem, if I understand correctly, boils down to not understanding exactly how the magic __call() method works and therefore have created a logic that would never work as expected.

See what the manual says (free translation):

Overload methods are invoked when interacting with properties or methods that have not been declared or are not visible in the current scope

Can you understand why I highlighted that term?

If the method not exist, __call() will be invoked. But your test launches a Exception if it does not exist, then its logic kills the functionality of this overload method.

If the method exists, __call() will not be invoked and with that, your property will not be populated.

What you could do is name the method somewhat different from the real, as an underline, a number or even by simply changing the visibility of the method (although this is wrong from the point of view of the Information Withholding Principle) and then consider this modification made to __call(), before invoking.

Another possible solution, a little more complex, is to use a Design Pattern called Decorator which, roughly speaking, is an object involving another, altering its functionality in Runtime.

  • so, it was my mistake in typing here, but I use with the two arguments yes... but it’s not working either (already updated my question)

  • 2

    Changing the method visibility to private or protected is also valid.

  • I understood that after reading some posts about.

  • 1

    @gmsantos: Most of the time it’s just enough, although I think it’s wrong from the point of view of the principle of withholding information. But since I don’t have a bigger spectator of the problem... I’ll complement that in the answer too. Three more and I get a little hat :p

  • So, I also understood why the OP wants to use __call ...

  • That’s right... I only use __call() to simulate multiple inheritance for sheer freshness, since in addition to efficient code I need it to be visually beautiful.

Show 1 more comment

2

I decided to do it this way:

$objCriado->{'_'.$metodo}();

//FullObject
public function __call($name, $arguments = null) 
{
  $realName = substr($name, 1);
  if(method_exists($this, $realName)) { 
    $this->method = $realName;
    return call_user_func_array(array($this, $realName), $arguments); 
  }else{ 
    throw new Exception('erro'); 
  } 
} 

I have now discovered that the magical method __call is called only when there is no method found, hence I forced the past methods not to exist so that I called him and could do what I needed.

I don’t know if it’s the best solution or not, but it’s the one I’ve found now so I can continue.

  • Good that solved alone. I was finishing the modified answer just now.

  • "I discovered now that the magic __call method is only called when there is no method found, "... I don’t know if you had noticed, but in Bruno Augusto’s answer explains this...

  • Daniel Omine, I noticed.. but when I wrote my reply and based even on what Bruno Augusto commented in my reply. BEFORE CONTAINING this in his reply, I made this post. " I was finishing the modified response just now" <- if you pay attention to that comment you’ll understand that... That when my response was posted, he was modifying his response to contain that detail... Thank you for paying attention to the details :)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.