PHP: Callback "Dynamic" from inside / outside the class

we have a problem [cit.]

I need to assign a callback dynamically inside the class, in the base of the param variable: my goal is to have only one class (not the main class and many subclasses of the class), and inside this class, if the value is X, then funcitonX must be used. if Y is a function of Y.

I know I cannot explain, ok, hope my example will do:

class plzComplicateMyLife{
    public $vehicle;
    public $kindVehicle;
    public $dynamicFunction;
    public function __construct($vehicle, $kindVehicle){
    $this->kindVehicle = $kindVehicle;
    $this->vehicle = $vehicle;
    switch($kindVehicle){
        case 'cycle':
            $this->dynamicFunction = "isACycle";
            break;
        case 'car':
            $this->dynamicFunction = "isACar";
            break;
    }
    //here come the problem, i need to call the callback store in dynamicFunction.
    //i tried:
    //call_user_func($this->$this->dinamicFunction, $this->vehicle);
    //error: Catchable fatal error: Object of class plzComplicateMyLife could not be converted to string in [...]
    //call_user_func("plzComplicateMyLife::".$this->dynamicFunction);
    //Warning: call_user_func(plzComplicateMyLife::isACar) [function.call-user-func]: First argument is expected to be a valid callback in [...]
    //$this->dynamicFunction();
    //Fatal error: Call to undefined method plzComplicateMyLife::dynamicFunction() in [...]
    //so, how can i do that?
    }
    public function isACycle($vehicle){
        echo 'im a cycle, model: '.$vehicle.'<br />';
    }
    public function isACar($vehicle){
        echo 'im a car, model: '.$vehicle.'<br />';
    }
    //i know this has no sense, in this example at least.
    public function printKind(){
        //call_user_func($this->$this->dinamicFunction, $this->vehicle);
        //call_user_func("plzComplicateMyLife::".$this->dynamicFunction);
        //then?
    }
}

$maserati = new plzComplicateMyLife('maserati4', 'car');

//then, maybe, outside the class i'll need to recover the callback:

$maserati->printKind();

      

EDIT

As Rob said, polymorphism would be a really good solution.

But the problem is, in this case, I really should have the same declaration for every instance of the class, changing only the parameters ... for example:

$maserati = new plzComplicateMyLife('maserati4', 'car');
$ducati = new plzComplicateMyLife('maserati4', 'cycle');
//is good
//becose i cant have:
$maserati = new plzComplicateMyLifeWithACar('maserati4');
$ducati = new plzComplicateMyLifeWithACycle('maserati4');

      

0


a source to share


4 answers


In response to your edit, could you do something like this instead?



abstract class MethodOfTransport {
    protected $model;

    public function __construct($model) {
        $this->model = $model;
    }

    abstract public function printKind();

    public static function create($model, $type) {
       $object = new $type($model);
       return $object;
    }
}

class cycle extends MethodOfTransport {
    public function printKind() {
        echo 'im a cycle, model: '.$this->model.'<br />';
    }
}

class car extends MethodOfTransport {
    public function printKind() {
        echo 'im a car, model: '.$this->model.'<br />';
    }
}

$maserati = MethodOfTransport::create('maserati4', 'car');
$maserati->printKind();

$ducati =  MethodOfTransport::create('maserati4', 'cycle');
$ducati->printKind();

      

+1


a source


Polymorphism is the way to go here, but for future reference, you can also do this:



public function printKind() {
    $this->{$this->dynamicFunction}($this->vehicle);
}

      

+2


a source


In PHP you can use a method callback using an array as a callback variable ( see here ), for example:

array( $object, $methodName );

      

So you could do this

$callback = array($this, $this->dynamicFunction);
call_user_func($callback, $this->vehicle);

      

+1


a source


Er, why don't you want to use a simple inheritance structure here? If you want different behavior depending on the object being modeled, then this is pretty much the canonical description of polymorphism.

If you really want to plow with callbacks to the same object, you need to do one of two things:

  • Drop the parameter $vehicle

    from your callbacks, make them private or secure, and call them ok, i.e.

    call_user_func( array( $this, 'isACycle' ) );

  • Mark the callbacks as static, make it private or secure, and call them like this:

    call_user_func( array( __CLASS__, 'isACycle' ), $this );

Within a non-static callback, object properties are accessed through $this

in the usual way. Also note that I suggest marking the callback as private or secure to prevent unnecessary external callers; presumably you don't want them to execute the wrong method for each type.

+1


a source







All Articles