PHP extension iterate through array
Asked Answered
I

3

6

I'm starting to write a PHP extension and wish to just get my head around how to loop through an array that is passed (with the intention of changing the data value by value). Preferred method would be a for loop so that I can match array1 with array2 data e.g. array1[0] is linked to array2[0], [1] with [1] etc...

Anyone able to help?

modarray.c

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"

extern zend_module_entry modarray_module_entry;
#define phpext_modarray_ptr &modarray_module_entry

PHP_FUNCTION(modarray);

static function_entry modarray_functions[] = {
    PHP_FE(modarray, NULL)
    PHP_FE_END
};

zend_module_entry modarray_module_entry = {
  STANDARD_MODULE_HEADER,
  "modarray",
  modarray_functions,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  "0.1",
  STANDARD_MODULE_PROPERTIES
};

ZEND_GET_MODULE(modarray)

PHP_FUNCTION(modarray)
{
  zval *val, *val2;

  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z", &val, &val2) == FAILURE){
    return;
  }

  SEPARATE_ZVAL(&val);
  SEPARATE_ZVAL(&val2);

  array_init(return_value);

  zval_add_ref(&val);
  zval_add_ref(&val2);
  add_next_index_zval(return_value, val);
  add_next_index_zval(return_value, val2);
}

PHP Code

<?php
$array1 = array(1,2,3,4);
$array2 = array(5,6,7,8);
echo '<pre>';
print_r(modarray($array1,$array2));
echo '</pre>';
?>

PHP Output

Array
(
    [0] => Array
        (
            [0] => 1
            [1] => 2
            [2] => 3
            [3] => 4
        )

    [1] => Array
        (
            [0] => 5
            [1] => 6
            [2] => 7
            [3] => 8
        )

)
Insessorial answered 3/7, 2014 at 14:34 Comment(1)
B
1

There are two ways to do that, one fully "manual" by using the iteration API:

HashPosition pos;
zval *collection, **arg;
uint hash_key_type;
uint string_key_len;
ulong int_key;
char *string_key = NULL;

... get the collection from somewhere, e.g. argument parsing ...

while (!EG(exception) && zend_hash_get_current_data_ex(Z_ARRVAL_P(collection), (void **)&arg, &pos) == SUCCESS) {
    zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(collection), &pos);
    MAKE_STD_ZVAL(key);
    hash_key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(collection), &string_key, &string_key_len, &int_key, 0, &pos);

    // Invoke e.g. zend_hash_update

    zend_hash_move_forward_ex(Z_ARRVAL_P(collection), &pos);
}

The preferred alternative is to use on of three zend_hash_apply*() functions with a callback which is considered more elegant:

static int replace_value(zval **arg, zval ****params TSRMLS_DC)
{
    add_next_index_zval(params, val);

    return ZEND_HASH_APPLY_REMOVE;
}

zval *in, ***out;
... fill in from somewhere from somewhere, e.g. argument parsing ...
array_init(**out);
zend_hash_apply_with_argument(Z_ARRVAL_P(collection, (apply_func_arg_t) replace_value, params TSRMLS_CC);

Note: I didn’t test either of the snippets locally but copied it from different places.

Benadryl answered 5/7, 2014 at 21:30 Comment(0)
P
0
function multi_diff($arr1,$arr2){
  $result = array();
  foreach ($arr1 as $k=>$v){
    if(!isset($arr2[$k])){
      $result[$k] = $v;
    } else {
      if(is_array($v) && is_array($arr2[$k])){
        $diff = multi_diff($v, $arr2[$k]);
        if(!empty($diff))
          $result[$k] = $diff;
      }
    }
  }
  return $result;
}

//example:

var_dump(multi_diff(

array(
  "A"=>array(
    "A1"=>array('A1-0','A1-1','A1-2','A1-3'),
    "A2"=>array('A2-0','A2-1','A2-2','A2-3'),
    "A3"=>array('A3-0','A3-1','A3-2','A3-3')
  ),
  "B"=>array(
    "B1"=>array('B1-0','B1-1','B1-2','B1-3'),
    "B2"=>array('B2-0','B2-1','B2-2','B2-3'),
    "B3"=>array('B3-0','B3-1','B3-2','B3-3')
  ),
  "C"=>array(
    "C1"=>array('C1-0','C1-1','C1-2','C1-3'),
    "C2"=>array('C2-0','C2-1','C2-2','C2-3'),
    "C3"=>array('C3-0','C3-1','C3-2','C3-3')
  ),
  "D"=>array(
    "D1"=>array('D1-0','D1-1','D1-2','D1-3'),
    "D2"=>array('D2-0','D2-1','D2-2','D2-3'),
    "D3"=>array('D3-0','D3-1','D3-2','D3-3')
  )
),

array(
  "A"=>array(
    "A1"=>array('A1-0','A1-1','A1-2','A1-3'),
    "A2"=>array('A2-0','A2-1','A2-2','A2-3'),
    "A3"=>array('A3-0','A3-1','A3-2')
  ),
  "B"=>array(
    "B1"=>array('B1-0','B1-2','B1-3'),
    "B2"=>array('B2-0','B2-1','B2-2','B2-3'),
    "B3"=>array('B3-0','B3-1','B3-3')
  ),
  "C"=>array(
    "C1"=>array('C1-0','C1-1','C1-2','C1-3'),
  ),
  "D"=>array(
    "D1"=>array('D1-0','D1-1','D1-2','D1-3'),
    "    "C3"=>array('C3-0','C3-1')
D2"=>array('D2-0','D2-1','D2-2','D2-3'),
    "D3"=>array('D3-0','D3-1','D3-2','D3-3')
  )
)

));
Pyrenees answered 6/7, 2014 at 2:59 Comment(0)
K
0

You may check out xarray extension or php-src for some C snippets: https://github.com/c9s/xarray

Kilby answered 14/10, 2015 at 21:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.