Уменьшить количество условных выражений
у меня есть небольшая функция, которая доставляет значение с более высоким приоритетом, которое на данный момент нигде не определено, только по порядку, как я оцениваю значения:
public function obtenerValorMasImportante($datos = null) {
if ($datos->getDato1()) {
return 'dato1';
}
if ($datos->getDatoX()) {
return 'datox';
}
if ($datos->getLoQueSea()) {
return 'loquesea';
}
if ($datos->getOtraCosa()) {
return 'otracosa';
}
return false;
}
проблема проста: код работает, но Что делать, если у меня есть 100 значений? мне нужно будет написать 100 if
, и это не очень хорошая идея, у меня нет идей в это время дня.
У меня нет большего контроля над объектом $datos
, поэтому это не так возможность изменить или добавить к нему информацию.
¿Как я могу уменьшить количество if? или в противном случае сделать код независимым от количества значений.
3 answers
Речь идет не о том, что eval
является "плохим", другим недостатком является то, что вы не можете легко поймать ошибки, и код не переносится на PHP 7, поскольку оператор return
должен быть обязательно включен или он вернет NULL.
Кроме того, не нужно использовать eval
. Вы можете динамически вызывать метод с помощью call_user_func
.
Хотя в примере имя метода и возвращаемое значение на один 'get' меньше в строке и возвращает strtolower($nombre_metodo)
, предположим, что это не так, и что мы должны сопоставить имена вызываемых методов с разрозненными значениями:
function obtenerValor($datos = null) {
$mapMetodoAValor = [
'Dato1' => 'valorRetorno1',
'DatoX' => 'valorRetornoOtro',
/* siguen más metodos => valor ...*/
];
foreach($mapMetodoAValor as $metodo => $valor) {
if(call_user_func([$datos, 'get' . $metodo])) {
return $valor;
}
}
return false;
}
Если значения всегда равны strtolower($metodo)
массив может быть проще, как пример Альваро, но опять же, нет необходимости использовать eval. Вы всегда предпочитаете call_user_func
Поскольку все условные выражения имеют одинаковую базовую структуру, это случай, когда вы можете использовать eval
. Идея состояла бы в том, чтобы вы изменили функцию, чтобы сделать что-то вроде этого:
- создает массив со списком (отсортированным по порядку приоритета) с именами проверяемых атрибутов
- проходит через список от первого элемента до последнего
- С
eval
присваивает значение геттера переменной вспомогательный - проверяет значение вспомогательной переменной
- если он имеет какое-либо значение, он возвращает имя элемента массива.
- С
Код будет выглядеть так:
function obtenerValorMasImportante($datos = null) {
$aux = array("Dato1", "DatoX", "LoQueSea", "OtraCosa");
$val = null;
for ($x = 0; $x < count($aux); $x++) {
eval('$val = $datos->get' . $aux[$x] . '();');
if ($val)
return strtolower($aux[$x]);
}
return false;
}
Итак, теперь единственное, что вам нужно сохранить, это список атрибутов, отсортированных по приоритету.
Да, я знаю, что будут люди, которые скажут: "но eval
это дьявольски и не должно использоваться", но это не совсем правильно, особенно для этого случая, потому что вы будете контролируйте все, что должно быть оценено, поэтому вы не рискуете сделать eval
с неизвестным входом.
Основываясь на ответах, предоставленных Альваро и Хесусом (новые ответы приветствуются), я закончил тем, что использовал этот код, используя переменные функции:
public function obtenerValorMasImportante($datos = null) {
$valores = ['Dato1', 'DatoX', 'LoQueSea', 'OtraCosa'];
foreach ($valores as $valor) {
$metodo = 'get' . $valor;
if ($datos->{$metodo}()) {
return strtolower($valor);
}
}
return false;
}