2010-07-01 5 views
2

Рассмотрим следующий фрагмент кода:Обработка отсутствует смещение массива

$tests = array( 
array ("a", "b", "c"), array ("1", "2", "3"), array ("!", "@") 
); 

foreach ($tests as $test) 
test($test[0], $test[1], $test[2]); 

function test($param1, $param2, $param3) { 
// do whatever 
} 

Это будет работать без проблем, пока не дойдет до $ теста [2], что, конечно, не имеет третий элемент в массив, в результате чего PHP выплюнуть:

Notice: Undefined offset: 2 

есть ли способ обойти эту проблему, кроме:

foreach ($tests as $test) { 
if (count($x) == 2) 
    test($test[0], $test[1]); 
else 
    test($test[0], $test[1], $test[2]); 
} 

function test($param1, $param2, $param3=null) { 
// do whatever 
} 

который получает громоздкий A s размер каждого массива $ test становится больше. Или я должен просто игнорировать уведомление в конце концов?

EDIT: Вот что я на самом деле пытается сделать:

// wanted this: 
function validate() { 
    $pass = true; 
    $rules = array (array ('field1', '!=', 'banana'), 
      array('field2', 'notempty') 
    ); 

    for ($i=0; $i<count($rules) && $pass; $i++) 
     $pass = check($rules[$i][0], $rules[$i][1], $rules[$i][1]); 

    return $pass; 
} 

function check($field, $operator, $expected) { 
    $value = $this->getValue($field); 

    switch ($operator) { 
     case '!=': 
      $pass = ($value != $expected); 
      break; 

     case '==': 
      $pass = ($value == $expected); 
      break; 

     case 'empty': 
      $pass = empty($value); 
      break; 

     default: 
      $pass = !empty($value); 
      break; 
    } 

    return $pass; 
} 

//instead of 
function validate() { 
    $pass = true; 

    for ($i=0; $i<count($rules) && $pass; $i++) 
     $pass = check($rules[$i]); 

    return $pass; 
} 

function check($check) { 
    $value = $this->getValue($check[0]); 

    switch ($check[1]) { 
     case '!=': 
      $pass = ($value != $check[2]); 
      break; 

     case '==': 
      $pass = ($value == $check[2]); 
      break; 

     case 'empty': 
      $pass = empty($value); 
      break; 

     default: 
      $pass = !empty($value); 
      break; 
    } 

    return $pass; 
} 

В основном по стилистическим причинам.

+0

Необходимые аргументы функции должны быть обязательными или полностью необязательными. Почему test() должен принимать переменное количество аргументов? И вы пробовали что-то вроде передачи одного аргумента в виде массива, например 'test ($ arr)', где '$ arr' - это что-то вроде' Array ('arg1', 'arg2', 'arg3_if_present') 'и там нужна работа? Просто похоже, что что-то нуждается в рефакторинге. –

ответ

6

Интересно.

Почему бы вам не попробовать что-то подобное?

foreach($tests as $test) { 
    test($test); 
} 

function test($test) { 
    // loop through $test to get all the values as you did originally 
} 

Если у вас динамический размер массива, я не понимаю, почему вы не можете просто передать весь массив в функцию вместо того, чтобы отделенные аргументы.

+0

Теперь я собираюсь с этим, но мне хотелось, чтобы у меня были оригинальные стилистические соображения. – quantumSoup

+0

Это объясняется в отредактированном сообщении выше – quantumSoup

0

Используйте вместо этого:

$tests = array( 
array ("a", "b", "c"), array ("1", "2", "3"), array ("!", "@") 
); 

foreach ($tests as $test) 
test($test); 

function test($test) 
{ 
    for($i=0; $i < count($test); $i++) 
    { 
     if (! isset($test[$i])) 
      $test[$i] = ''; 
    } 

// do whatever 
} 
0

Почему вы используете $ param1, $ param2, а не непосредственно в массиве параметров, например:

$tests = array( 
array('a', 'b', 'c'), 
array('1', '2', '3'), 
array('!', '@') 
); 

foreach ($tests as $test) 
{ 
test($test); 
} 

function test($params) 
{ 
$param1 = $params[0]; // Or use directly $params[index], than you need not to set it. 
} 

Или еще один способ (но этот путь не лучший способ, лучше, чем выше;))

$tests = array( 
array('a', 'b', 'c'), 
array('1', '2', '3'), 
array('!', '@') 
); 

foreach ($tests as $test) 
{ 
test($test); 
} 

function test($params) 
{ 
for($i=0; $i<=count($params)-1; $i++) 
{ 
    $param$i = $params[$i]; 
} 
} 
0

Если вопрос заключается в простоте повторения многомерный массив, а затем сделать

$iterator = new RecursiveIteratorIterator(
       new RecursiveArrayIterator($theArray) 
       RecursiveIteratorIterator::SELF_FIRST); 

foreach($iterator as $key => $val) { 
    echo "$key = $val \n" 
} 

Если вы хотите знать, как передать переменное количество аргументов функции, рассмотрит

function throwItAtMe() 
{ 
    $args = func_get_args(); 
    print_r($args); 
} 
throwItAtMe(1,2,3,4,5, 'foo', 'bar', 'baz'); 

Для ваших правил/утверждение просто использовать Strategy Pattern или иметь посмотрите на Specification pattern.

0

Вы действительно должны пойти раствором Bartek, но для полноты здесь один, то есть, вероятно, больше, как вы хотите:

foreach ($tests as $test) { 
    test($test[0], $test[1], isset($test[2]) ? $test[2] : null); 
} 

Но если честно: Если размеры массивов может увеличиться, вы на самом деле хотите каждый раз менять подпись функции? Наслаждайтесь нашим живым и передайте массив.

Если у вас есть не более 3 записей, то с кодом выше.

0
foreach($tests as $test) { 
    test($test); 
} 

function test($test) { 
    @list($field, $operator, $expected) = $test; 
    // if $test size is 2 then $expected will be NULL, @ is to suppress Notice, if you don't show notices you may ommit it 
} 
0

Существует также некрасиво, но короткий способ сделать это с помощью call_user_func_array:

foreach ($tests as $test) { 
    call_user_func_array('test', $test); 
} 

function test($param1, $param2, $param3 = null) { 
    // ... 
} 

Хотя, скорее всего, я бы предпочел решение Bartek в.

Смежные вопросы