Функция PHP с дополнительными параметрами

107

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

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

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

user481826
источник
4
Связанный: stackoverflow.com/questions/2112913
Пекка
Это странно. Встроенные функции в php могут иметь необязательные параметры. Так почему мы не можем создавать такие функции?
Родриго
2
Обратите внимание, что многие из этих ответов УСТАРЕНЫ ... PHP теперь поддерживает функции со списками аргументов переменной длины .
ashleedawg

Ответы:

62

Сделайте так, чтобы функция принимала один параметр: массив. Передайте фактические параметры как значения в массиве.


Изменить: ссылка в комментарии Пекки почти подводит итог.

Мэтт Болл
источник
1
Это странно. Встроенные функции в php могут иметь необязательные параметры. Так почему мы не можем создавать такие функции?
Родриго
1
@Rodrigo, такие функции можно определить. Однако они позиционно необязательны, что довольно мерзко для чего-либо, кроме одного необязательного параметра.
Мэтт Болл,
1
Хорошо, я пытался с [], теперь я вижу, как это сделать здесь: stackoverflow.com/a/34869/1086511
Родриго
Есть еще кое-что, что можно сделать, кроме предложения «использовать массив» - взгляните на ответ
Уолфа
63

В этом случае я передал массив, где ключ - это имя параметра, а значение - это значение.

$optional = array(
  "param" => $param1,
  "param2" => $param2
);

function func($required, $requiredTwo, $optional) {
  if(isset($optional["param2"])) {
    doWork();
  }
}
Rabbott
источник
В вашем примере, разве не нужно устанавливать глобальную переменную $ optional внутри функции?
user481826
1
Глобальный? нет ..? Вы создаете этот массив перед вызовом функции и передаете его. Мой код - это пример описания Мэттом Боллом того, что нужно делать.
Rabbott
Можно сделать еще
кое-что, кроме
45

Чтобы выполнить то, что вы хотите, используйте массив, как сказал Rabbot (хотя это может стать проблемой для документирования / поддержки при чрезмерном использовании). Или просто используйте традиционные необязательные аргументы.

//My function with tons of optional params
function my_func($req_a, $req_b, $opt_a = NULL, $opt_b = NULL, $opt_c = NULL)
{
  //Do stuff
}
my_func('Hi', 'World', null, null, 'Red');

Однако я обычно обнаруживаю, что когда я начинаю писать функцию / метод с таким количеством аргументов - чаще всего это запах кода, и его можно преобразовать / абстрагировать во что-то более чистое.

//Specialization of my_func - assuming my_func itself cannot be refactored
function my_color_func($reg_a, $reg_b, $opt = 'Red')
{
  return my_func($reg_a, $reg_b, null, null, $opt);
}
my_color_func('Hi', 'World');
my_color_func('Hello', 'Universe', 'Green');
Кайла Роуз
источник
В 2010 году такие понятия, как «запах кода», «рефакторинг» или «обслуживание кода» не были популярны в нашем сообществе. Ты был на шаг впереди большинства из нас :)
Биллал Бегерадж
15

В PHP 5.6 и более поздних версиях списки аргументов могут включать токен ... для обозначения того, что функция принимает переменное количество аргументов. Аргументы будут переданы в данную переменную в виде массива; например:

Пример использования ... для доступа к переменным аргументам

<?php
function sum(...$numbers) {
    $acc = 0;
    foreach ($numbers as $n) {
        $acc += $n;
    }
    return $acc;
}

echo sum(1, 2, 3, 4);
?>

Приведенный выше пример выведет:

10

Списки аргументов переменной длины Документация по PHP

Mentos1386
источник
Этот ответ заслуживает большего количества очков. Не подходит для моего конкретного случая, но хорошая информация и проста для понимания. Скоро выйдет PHP 7.3! 5.6 и 7 - EOL.
AdheneManx
12

Вы можете просто установить значение по умолчанию на null.

<?php
function functionName($value, $value2 = null) {
// do stuff
}
Блейк Стивенсон
источник
2
Лучший ответ, но замените, пожалуйста, небитами nullтипа даты. например, array()для массивов
Мохамед хешам
Спасибо ... Это то, что я искал
Давиде Де Маэстри
12

ПРИМЕЧАНИЕ. Это старый ответ для PHP 5.5 и ниже. PHP 5.6+ поддерживает аргументы по умолчанию

В PHP 5.5 и ниже вы можете добиться этого, используя один из следующих двух методов:

  • с помощью функций func_num_args () и func_get_arg () ;
  • с использованием аргументов NULL;

Как пользоваться

function method_1()
{
  $arg1 = (func_num_args() >= 1)? func_get_arg(0): "default_value_for_arg1";
  $arg2 = (func_num_args() >= 2)? func_get_arg(1): "default_value_for_arg2";
}

function method_2($arg1 = null, $arg2 = null)
{
  $arg1 = $arg1? $arg1: "default_value_for_arg1";
  $arg2 = $arg2? $arg2: "default_value_for_arg2";
}

Я предпочитаю второй метод, потому что он понятен и понятен, но иногда вам может понадобиться первый метод.

Даниэль Лурейро
источник
1
Вам нужен двойной знак "=", иначе все выражения вернут истину. Кроме того, выражения во 2-м примере всегда будут возвращать истину, потому что переменная всегда равна самой себе.
chuckieDub
хороший момент, но это действительно работает. В PHP этот код $x = null; if ($x) echo "true"; else echo "false";будет печатать «false», даже если $ x var имеет значение («null» в этом коде). Кроме того, в обоих методах мы используем тернарный оператор, поэтому правильно использовать только один знак «=». Если вы проверяете с помощью method(); method(1); method(1, 2);, то первый вызов свяжет arg1 и arg2 со значениями по умолчанию, второй вызов свяжет второй аргумент со значением по умолчанию и "1" для первого аргумента. Последний вызов не связывает значения по умолчанию.
Daniel Loureiro
1
function method_2 ($ arg1 = "default_value_fot_arg1", $ arg2 = "default_value_fot_arg2") {так что php работает с параметрами, а также вы можете передавать null в качестве параметра (почему люди используют null, я не знаю)
nerkn
1
@nerkn, ты прав, PHP сейчас поддерживает аргументы по умолчанию. Лол, я помню, когда нам нужно было найти много обходных путей для достижения простых вещей. Хорошие времена: P Однако вы все еще можете увидеть эти подходы в старых кодах (до 5.5).
Даниэль Лоурейро
4

Думаю, вы тоже можете использовать объекты как params-transportes.

$myParam = new stdClass();
$myParam->optParam2 = 'something';
$myParam->optParam8 = 3;
theFunction($myParam);

function theFunction($fparam){      
  return "I got ".$fparam->optParam8." of ".$fparam->optParam2." received!";
}

Конечно, вы должны установить значения по умолчанию для «optParam8» и «optParam2» в этой функции, в противном случае вы получите «Notice: Undefined property: stdClass :: $ optParam2»

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

function theFunction($fparam){
   $default = array(
      'opt1' => 'nothing',
      'opt2' => 1
   );
   if(is_array($fparam)){
      $fparam = array_merge($default, $fparam);
   }else{
      $fparam = $default;
   }
   //now, the default values are overwritten by these passed by $fparam
   return "I received ".$fparam['opt1']." and ".$fparam['opt2']."!";
}
psad
источник
2

Если для создания объекта с допустимым состоянием требуются только два значения, вы можете просто удалить все другие необязательные аргументы и предоставить им сеттеры (если вы не хотите, чтобы они изменялись во время выполнения). Затем просто создайте экземпляр объекта с двумя обязательными аргументами и настройте остальные по мере необходимости с помощью установщика.

дальнейшее чтение

Гордон
источник
2

Я знаю, что это старый пост, но у меня была проблема, такая как OP, и это то, что я придумал.

Пример массива, который вы можете передать. Вы можете повторно заказать это, если требуется конкретный заказ, но в этом вопросе это будет делать то, что вам задают.

$argument_set = array (8 => 'lots', 5 => 'of', 1 => 'data', 2 => 'here');

Это управляемо, легко читается, а точки извлечения данных могут быть добавлены и удалены в любой момент в любом месте кодирования и при этом избежать масштабной перезаписи. Я использовал целочисленные ключи, чтобы соответствовать исходному вопросу OP, но строковые ключи можно было использовать так же легко. Собственно для читабельности я бы посоветовал это.

Вставьте это во внешний файл для удобства

function unknown_number_arguments($argument_set) {

    foreach ($argument_set as $key => $value) {

        # create a switch with all the cases you need. as you loop the array 
        # keys only your submitted $keys values will be found with the switch. 
        switch ($key) {
            case 1:
                # do stuff with $value
                break;
            case 2:
                # do stuff with $value;
                break;
            case 3:
                # key 3 omitted, this wont execute 
                break;
            case 5:
                # do stuff with $value;
                break;
            case 8:
                # do stuff with $value;
                break;
            default:
                # no match from the array, do error logging?
                break;
        }
    }
return;
}

поместите это в начало, если файл.

$argument_set = array(); 

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

$argument_set[1][] = $some_variable; 

И наконец передаем массив

unknown_number_arguments($argument_set);
Крис
источник
1
function yourFunction($var1, $var2, $optional = Null){
   ... code
}

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

Null по-прежнему является значением, если вы не вызываете функцию со значением для этой переменной, она не будет пустой, поэтому ошибки нет.

Антуан Серри
источник
2
Вы можете объяснить все это дальше? Данный код синтаксически недействителен, так как имена переменных не могут начинаться с числа,
Нико Хаасе,
0

Если вы обычно просто передаете 8-е значение, вы можете изменить порядок параметров так, чтобы оно было первым. Вам нужно только указать параметры до последнего, который вы хотите установить.

Если вы используете разные значения, у вас есть 2 варианта.

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

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

Алан Гелейнсе
источник
0

PHP допускает аргументы по умолчанию ( ссылка ). В вашем случае вы можете определить все параметры от 3 до 8 как NULL или как пустую строку "" в зависимости от кода вашей функции. Таким образом, вы можете вызвать функцию только с использованием первых двух параметров.

Например:

<?php
  function yourFunction($arg1, $arg2, $arg3=NULL, $arg4=NULL, $arg5=NULL, $arg6=NULL, $arg7=NULL, $arg8=NULL){
echo $arg1;
echo $arg2;
if(isset($arg3)){echo $arg3;}
# other similar statements for $arg4, ...., $arg5
if(isset($arg8)){echo $arg8;}
}
Андрес Луна
источник
Интересная идея ... однако ваше предложение проблему не решает. Фактически, если вы добавите информацию о том, какой аргумент отображается эхом (например, используя echo " this is arg3: " . $arg3;и т. Д., Вы увидите, что вызов, например, yourFunction(3, 2, $arg8=5);будет печатать 32 this is arg3: 5. Проблема в том, что положение параметра все еще имеет значение при передаче дополнительных параметров в PHP ... имена параметров недостаточно для сопоставления значений параметров с именами параметров.
mastropi
0

Просто установите Null, чтобы игнорировать параметры, которые вы не хотите использовать, а затем установите необходимый параметр в соответствии с положением.

 function myFunc($p1,$p2,$p3=Null,$p4=Null,$p5=Null,$p6=Null,$p7=Null,$p8=Null){
    for ($i=1; $i<9; $i++){
        $varName = "p$i";
        if (isset($$varName)){
            echo $varName." = ".$$varName."<br>\n";
        }
    }
}   

myFunc( "1", "2", Null, Null, Null, Null, Null, "eight" );
ФЕРНАНДО БАРАЦЗЕТТИ
источник