-1

I have an array (class property) which stores PHP methods (i.e., of class 'Closure'). Just like this.

$this->methods[$name]=$action;

$action is the function.

When I try invoking the function like $this->methods[$name](), I'm unable to access $this pointer inside function.

Why is this issue happening and how do I fix it.

Munavir Chavody
  • 489
  • 4
  • 16
  • 1
    Why would you expect the closure to have any `$this`? – deceze Jan 29 '18 at 11:38
  • 1
    I guess you'll need [`Closure::bind`](https://php.net/manual/closure.bind.php) somewhere in your code. – Yoshi Jan 29 '18 at 11:42
  • I want the function to be executed as a class method. Is the term closure confusing? I'm not returning any callbacks. It appends a function to an array, then at a later point of time, same is called inside the class itself. – Munavir Chavody Jan 29 '18 at 11:42
  • If the function wasn't defined as a class method, it doesn't have a `$this`. Just because you execute it from an array which is an object property doesn't make it a class method. This is not Javascript. – deceze Jan 29 '18 at 11:49
  • Or [`Closure::call`](https://php.net/manual/closure.call.php) actually. – Yoshi Jan 29 '18 at 12:11
  • @deceze I have similar class with `$this->pipe_methods[$pipe]=$method;` to append method and `$this->block_methods[$tag]($args,$block,$data);` to call the function. Same code is working with access towards `$this` object. – Munavir Chavody Jan 29 '18 at 13:13

2 Answers2

-1

You should have a look at "magic methods". http://php.net/manual/en/language.oop5.overloading.php#object.call

maybe you can try this implementation (not tested):

class MyClass
{
    public function __call($method_name, $arguments)
    {
        // $method_name is case sensitive
        $this->$method_name($arguments);
    }
   public function doSomethingCool($param){
      echo 'something cool happened';
   }
}

$obj = new MyClass();
$method = 'doSomethingCool';
$obj->$method('robert', 42)
erwan
  • 887
  • 8
  • 17
-1

I don't know if I understood your question. And if I did, I don't know why you would want to do this but:

<?php

class Foo
{
    protected $methods     = [];

    public    $some_number = 42;

    public function callFunction($action)
    {
        if ( ! array_key_exists($action, $this->methods)) {
            throw new Exception(sprintf('Method %s doesn\'t exist!', $action));
        }

        $this->methods[$action]($this);
    }

    public function addFunction(closure $closure, $label)
    {
        $this->methods[$label] = $closure;
    }
}

$foo = new Foo();

$foo->addFunction(function (Foo $context) {
    echo $context->some_number;
}, 'test');

$foo->callFunction('test');
Friedrich Roell
  • 437
  • 1
  • 5
  • 14
  • I'll help you with an example. I'm building a template parser which has some built-in template tags. At some point in time, if the user wants to use his own template tag, we provide a method in which it accepts the function as an argument (which will be tag parsing logic). Now, say, the function has to access any parser object properties, then access to current object should be there, right? I have a working code for the above scenario. @Friedrich Roell – Munavir Chavody Jan 29 '18 at 13:33
  • then why not call the users closure with the ObjectProperites. Or create a helper Model like `MyTemplateVarBag` and then call his function like. `$userClosure(MyTemplateVarBag $var);` – Friedrich Roell Jan 29 '18 at 13:39
  • I need access to class' private methods/properties. So, it'll be better if the closure has access to `$this` pointer. I already wrote a working code for the same. But when I replicate, it's failing. – Munavir Chavody Jan 29 '18 at 14:08
  • Take the same example above. I have a user defined template tag which contains nested template tags in it. To process template blocks inside user defined template we have a private method. I have a working code for the above. I'm trying to replicate same logic, say for argument parsing, but not working. – Munavir Chavody Jan 29 '18 at 14:25