0

I have to classes and I want to pass a method fro classA to classB constructor and store it on a classB instance variable so as to execute it later.



    class A
    { 
        public function execute()
        {
            $ClassB = new ElgEmpAnalyticsImporterControllerImporterEmporioOrder(ConMW::getDB(), $this -> lPointFile, [$this, 'getLastPoints'] );
            $ClassB -> import();   
        }

        public function getLastPoints(Array $keys)
        {
            $res = [];
            forEach ( json_decode( file_get_contents($this -> lastPointFile) ) as $key => $value ):
                if ( in_array($key, $keys) ):
                    $res[$key] = $value;
                else:
                    $res[$key] = '';
                endif;
            endforeach;
            unset($key);
            unset($value);
            return $res;
        }

    }


    classB
    { 
        public $getLastPoints = null;

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

        public function import()
        {
            $lastPoints = $this -> getLastPoints(['idOrder', 'orderLastExport']);              
        }
    }

Trying to execute it like that I get the error "Call to undefined method getLastPoints()"

I think the problem is on storing the function on the instance variable $getLastPoints of classB. I can conclude this because If I execute the function on the constructor it works. That means if I change the constructor of classB like this



    classB
    { 
        public $getLastPoints = null;

        public function __construct(callable $getLastPoints) 
        {
            $getLastPoints(['idOrder', 'orderLastExport']);
        }


    }

it works.

But what i need is to execute the external function inside the import function.

Can someone please help me?

thanks for your time,

Edit for clarification: My question is why I can execute the function inside the contructor like this :

$lastPoint(a,b)

but when I assign the callable into an instance variable like this:

$this -> lastPoint(a,b)

it does not work.

I read that php uses different storage for variables and function. PHP probably sees the callable $lastPoints as a variable. So can the callable $lastPoints, be added as dynamic function to my instance of classB?

Christoforos

Christoforos
  • 564
  • 3
  • 13
  • 2
    Is this for real `ElgEmpAnalyticsImporterControllerImporterEmporioOrder`? – AbraCadaver Nov 18 '16 at 15:20
  • Just store the value of the method getLastPoints() inside a variable into the class A, then pass that variable when creating a new B object – Damian Dominella Nov 18 '16 at 15:22
  • Sorry AbraCadaver ElgEmpAnalyticsImporterControllerImporterEmporioOrder is ClassB – Christoforos Nov 18 '16 at 18:43
  • Just a very short question: Why? – k0pernikus Nov 18 '16 at 18:47
  • Damian Dominella: I need to be able to run the function at runtime. The above is an sample. This function is called several times in the real program, and I its return value is not the same. – Christoforos Nov 18 '16 at 18:48
  • k0pernikus: as I comment to Damian the above is a sample. This function is called several times in the ClassB so I need reference to It, so as it can be executed. ClassA also uses some other classes except classB. These other classes also using this function several times. So I need to be able to pass this function from classA to ClassB, classC etc, and those classes must be able to execute it. – Christoforos Nov 18 '16 at 18:54

1 Answers1

0

PHP Callable Object as Object Member

$getlastpoints is a property with an array value stored in it, not a function. call_user_func_array($this->getlastpoints, ['idOrder', 'orderLastExport']);

public function import()
    {
        $my_func = $this->getLastPoints;
        $lastPoints = $my_func(['idOrder', 'orderLastExport']);              
    }

In a nutshell, the reason you will have to do this is because you can define properties and methods in a PHP class having the same name. e.g.

class foo {
  public $bar
  public function bar() {}
}

so in this instance, if allowed to directly access a stored callable on the $bar property... What would the call below reference?

$my_foo_obj->bar()  

To avoid the situation, you cannot call it directly.

Community
  • 1
  • 1
Chris Caviness
  • 586
  • 3
  • 10
  • Sorry I get error "getLastPoints() must be of the type array, string given." Any way my question why I can not call the function through another functoin like $this -> getLastPoint(a,b) while I can do it inside the construct like this: $lastPoint(a, b). – Christoforos Nov 19 '16 at 07:56
  • Because you have a reference to the callable which you are using in the constructor. What version of PHP are you using, because the answer will differ between 5 and 7. But basically, in older versions, you want to store an array with the object and method and use the call_user_func. You can also use the invoke method. http://stackoverflow.com/questions/16380745/is-is-possible-to-store-a-reference-to-an-object-method – Chris Caviness Nov 21 '16 at 22:00
  • I am using PHP 7. So the problem is to find a way to use the callable outside the constructor? I am assign the variable $getInstancePoint, which is of type calable, to an instance variable on classB. Shouldn't this instance variable be of the type callable also and be executed directly also? – Christoforos Nov 22 '16 at 08:06
  • Expanded my answer to address the question in your comment. As for the variable assignment and then using that as the function, you may still need to store a reference to the object and use $myobj->$myfunc as I'm uncertain whether assigning the callable to your property is going to maintain the object reference, or just assign a lambda function. You'll have to do some testing to answer that one. – Chris Caviness Nov 22 '16 at 17:32