47

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()?

hjpotter92
  • 78,589
  • 36
  • 144
  • 183
Sandeepan Nath
  • 9,966
  • 17
  • 86
  • 144

5 Answers5

103

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.

Abel
  • 2,371
  • 3
  • 15
  • 29
Daniel Vandersluis
  • 91,582
  • 23
  • 169
  • 153
  • 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 `$this` – Sandeepan Nath Oct 01 '10 at 14:54
  • 1
    Can you show the exact code that doesn't work (that issues that warning)? – ircmaxell Oct 01 '10 at 15:01
  • Oh I found the issue... please don't downvote guys... I did not initiate user object... was doing `user::getUserFields()` – Sandeepan Nath Oct 01 '10 at 15:08
  • 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() – Alejandro Moreno Sep 30 '16 at 16:57
  • This worked also with the php native sorting function `usort($someArray, array($this,'some_function_of_class'))` – kiltek Mar 14 '17 at 08:53
  • `Unable to call Array() - function does not exist in` - it's case sensitive, it should be `array()`, thus the error. – inarilo Apr 13 '17 at 08:33
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');
Klesun
  • 12,280
  • 5
  • 59
  • 52
  • 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. – Aleksandar Dec 18 '18 at 12:25
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'])
}
Denise Ignatova
  • 465
  • 4
  • 7
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;
Serj
  • 41
  • 1
  • 9
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));
    }

}
Adam Winter
  • 1,680
  • 1
  • 12
  • 26