Search code examples
phparraysbyref

PHP modifying array elements by reference


I have a large data-set that I'm checking the contents of; I do this validation while creating an internal array of the data; to avoid looping over the array again later, I would like the validation to change the contents of the array. Now the problem is that I'm calling the validation routines through call_user_func and this seems to pose some problems with passing by reference. Or maybe I'm doing something else wrong.

Here's a stripped down example:

public function index( )
{
    $arr = array( 
        array('a' => 'aap', 'n' => 'noot', 'm' => 'mies'), 
        array('a' => 'ding', 'b' => 'flof', 'c' => 'bips'), 
        array( 'd' => 'do', 'e' => 're', 'c' => 'mi') 
    );

    $func = array( $this, '_user_func' );

    $errors = 0;
    $new_arr = array();
    foreach ($arr as $key => &$value) {
        $new_arr[$key] = &$value; // Simulate production-code manipulation
        //if ( !$this->_do_callback($func, $new_arr[$key], $key) ) $errors++; // No exception but array not modified afterwards
        if ( !call_user_func( $func, $new_arr[$key], $key ) ) $errors++; // Exception: Parameter 1 to TestRef::user_func() expected to be a reference, value given
    }
    unset($value);
    var_dump($new_arr);
    print_r('Errors: '.$errors);
}

private function _do_callback( $func, array &$row, $row_id )
{
    if ( is_callable( $func ) )
    {
        return call_user_func( $func, $row, $row_id );
    }
    else
    {
        throw new Exception( "Error doing callback. Callback empty or not a callable function." );
    }
}

private function _user_func( &$arr, $index = 0 )
{
    // "Validation" routine
    foreach ($arr as $key => &$value) {
        if ($key == 'b') return FALSE; // Simulate validation error for error count
        $arr[$key] = 'replaced';
    }
    unset($value);
    //var_dump($arr); // Works!
    return TRUE;
}

Solution

  • i think you're trying to redefine an existing php function which is array_walk. And especially in your case, you'll need array_walk_recursive.

    Here's a rewritten (simplified ?) version of your code.

        public function index( )
        {
            $arr = array( 
                array('a' => 'aap', 'n' => 'noot', 'm' => 'mies'), 
                array('a' => 'ding', 'b' => 'flof', 'c' => 'bips'), 
                array( 'd' => 'do', 'e' => 're', 'c' => 'mi') 
            );
    
            $func = array( $this, '_user_func' );
    
            var_dump($arr); // BEFORE WALK
            array_walk_recursive($arr, $func);
            var_dump($arr); // AFTER WALK
        }
    
        /**
         *  Does something to a row from an array (notice the reference)
         */
        private function _user_func( &$rowValue, $rowIndex )
        {
                $rowValue = 'replaced';
        }
    

    You can see this code in action here --> http://ideone.com/LcZKo