How do I use a class method as a callback function?
Asked Answered
T

5

48

If I use array_walk inside a class function to call another function of the same class

class user
{
   public function getUserFields($userIdsArray,$fieldsArray)
   {

     if((isNonEmptyArray($userIdsArray)) && (isNonEmptyArray($fieldsArray)))
     {
         array_walk($fieldsArray, 'test_print');
     }
   }


  private function test_print($item, $key)
  {
         //replace the $item if it matches something
  }

}

It gives me the following error -

Warning: array_walk() [function.array-walk]: Unable to call test_print() - function does not exist in ...

So, how do I specify $this->test_print() while using array_walk()?

Trichinopoly answered 1/10, 2010 at 14:50 Comment(2)
Any reason you've created a function isNonEmptyArray instead of just using !empty(...)?Intervale
yes, it returns true only if the param is an array with at least one non-empty valueTrichinopoly
I
105

If you want to specify a class method as a callback, you need to specify the object it belongs to:

array_walk($fieldsArray, array($this, 'test_print'));

From the manual:

A method of an instantiated object is passed as an array containing an object at index 0 and the method name at index 1.

Intervale answered 1/10, 2010 at 14:52 Comment(6)
Yes I tried this before but it gives me this error - Warning: array_walk() [function.array-walk: Unable to call Array() - function does not exist in However this is working array_walk($fieldsArray,'user::test_print');. So what is wrong. I wanted to use $thisTrichinopoly
Can you show the exact code that doesn't work (that issues that warning)?Commonalty
Oh I found the issue... please don't downvote guys... I did not initiate user object... was doing user::getUserFields()Trichinopoly
Something to have in mind, the method being called must receive the elements by reference, otherwise the changes do not get sent through the callback to array_walk()Distract
This worked also with the php native sorting function usort($someArray, array($this,'some_function_of_class'))Sturdy
Unable to call Array() - function does not exist in - it's case sensitive, it should be array(), thus the error.Bibbs
E
7

If you need to call a static method without instantiating the class you could do so:

// since PHP 5.3
array_walk($fieldsArray, 'self::test_print');

Or from outside:

// since PHP 5.5
array_walk($fieldsArray, User::class.'::test_print');
Emanate answered 7/9, 2016 at 16:53 Comment(1)
For static calls, array_walk( $forms, array( 'self', 'method_name' )) also works. I am not sure which version of PHP brought this, but I guess that array-method is older than the 'self::method_name' string-parsing-thing.Pannier
V
3

To call a class method as a callback function in another class method, you should do :

public function compareFucntion() {
}

public function useCompareFunction() {
  usort($arrayToSort, [$this, 'compareFucntion'])
}
Valonia answered 28/6, 2017 at 15:4 Comment(0)
M
1

This is the class which looks for a specific key in a multidimensional array and returns its value:

class Find_value_by_key  {
  protected $look_by_key;
  protected $look_in_array = array();
  public $result_value;

  public function get_array($look_in_array, $look_by_key) {
    $this->look_by_key = $look_by_key;
    $this->look_in_array = $look_in_array;
    $this->run_walk_through_array($this->look_in_array);

  }

  protected function walk_through_array($value, $key) {

    if (is_array($value)) {
      if ($key === $this->look_by_key) {
        $this->result_value = $value;
      } else {
        array_walk($value,[$this,'walk_through_array']);
      }
    } 

  }

  protected function run_walk_through_array($look_in_array) {
    array_walk($look_in_array,[$this,'walk_through_array']);
  }

} 

You need to pass the Array and the specific Key into get_array(). Then call for $result_value:

$this->load->library('find_value_by_key');
$this->find_value_by_key->get_array($my_array, 'my_key');
$key_Value = $this->find_value_by_key->result_value;
Mendelsohn answered 23/9, 2021 at 17:42 Comment(0)
E
0

Below are four examples of ways to do your callback functions.
If you're like me, one of these will be the most intuitive for you.
Look closely at the difference in how $callable is defined in each one. It's important to remember that array_walk() returns a boolean.

<?php

namespace App\MiscTests;

class User
{
    protected $fieldsArray = [];
    protected $result = "";

    public function setUserFields(array $fieldsArray)
    {
        $this->fieldsArray = $fieldsArray;
    }

    public function getResult()
    {
        return $this->result;
    }

    private function test_printOne($item, $key)
    {
        echo $key.$item;
        $this->result = $key.$item;
    }

    private function test_printTwo(){
        $callThis = function ($item, $key){
            echo $key.$item;
            $this->result = $key.$item;
        };
        return $callThis;
    } 

    public function callbackMethodOne()
    {                
        $callable = array($this, 'test_printOne');
        return array_walk($this->fieldsArray, $callable, null);
    }

    public function callbackMethodTwo()
    {        
        $callable = $this->test_printTwo();
        return array_walk($this->fieldsArray, $callable, null);
    }

    public function callbackMethodThree()
    {
        $callable = function ($item, $key){
            echo $key.$item;
            $this->result = $key.$item;
        };
        return array_walk($this->fieldsArray, $callable, null);
    }

    public function callbackMethodAnonymous()
    {
        return array_walk($this->fieldsArray, function ($item, $key){
            echo $key.$item;
            $this->result = $key.$item;
        }, null);
    }

}
?>

Here's the unit tests I used:

<?php

namespace Tests\Unit;

use PHPUnit\Framework\TestCase;

class MiscUserTest extends TestCase
{
    /**
     * This will test the User class
     *
     * @return void
     */
    public function test_print_with_callback_method_one()
    {
        $userObject = new \App\MiscTests\User;
        $userObject->setUserFields(['Foo'=>'Bar1']);
        $this->assertEquals(1, $userObject->callbackMethodOne());
        $result = $userObject->getResult();
        $this->assertEquals(0, strcmp('FooBar1', $result));
    }

    public function test_print_with_callback_method_two()
    {
        $userObject = new \App\MiscTests\User;
        $userObject->setUserFields(['Foo'=>'Bar2']);
        $this->assertEquals(1, $userObject->callbackMethodTwo());
        $result = $userObject->getResult();
        $this->assertEquals(0, strcmp('FooBar2', $result));
    }

    public function test_print_with_callback_method_three()
    {
        $userObject = new \App\MiscTests\User;
        $userObject->setUserFields(['Foo'=>'Bar3']);
        $this->assertEquals(1, $userObject->callbackMethodThree());
        $result = $userObject->getResult();
        $this->assertEquals(0, strcmp('FooBar3', $result));
    }

    public function test_print_with_callback_method_anonymous()
    {
        $userObject = new \App\MiscTests\User;
        $userObject->setUserFields(['Foo'=>'Bar4']);
        $this->assertEquals(1, $userObject->callbackMethodAnonymous());
        $result = $userObject->getResult();
        $this->assertEquals(0, strcmp('FooBar4', $result));
    }

}
Erin answered 19/2, 2022 at 18:17 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.