Как заменить вложенные операторы switch

Меня попросили написать небольшой PHP-скрипт, который берет некоторый ввод POST из нескольких выпадающих списков, которые дают некоторые выбираемые критерии, и в конце выплевывает одну или несколько строковых переменных, содержащих уникальные коды.

Имена переменных имеют форму $ thingPlaceType, и каждая из них уникальна. Выпадающие списки позволяют выбрать:

  • либо одна "вещь", либо все "вещи" вместе
  • либо одно "место", либо все "места" вместе
  • либо один «тип», либо все «типы» вместе

Я не могу понять, как выбрать эти коды, не прибегая к вложенным операторам переключения, где я делаю

switch($_POST['thing'])
{
  case "thing1":
     switch($_POST['place'])
     {
       case "place1":
          switch($_POST['type'])
          {
            case "type1":
               $output = $thing1Place1Type1;
            case "type2":
               $output = $thing1Place1Type2;
            case "alltypes":
               $output = $thing1Place1Type1.$thing1Place1Type2.$thing1PlaceType3;
           }
        case "place2":
        ...
        case "allplaces":
        ...
      }
  case "thing2":
     switch($_POST['place'])
     {
       case "place1":
          switch($_POST['type'])
          {
            case "type1":
               $output = $thing1Place1Type1;
            ...
      ...
  ...
}

Похоже, что код превращается в Антипаттерн Стрелка. Я думаю, что мог бы что-то сделать, используя многомерные массивы или, может быть, один массив, в котором я сопоставляю значения с ключами. Но я чувствую, что он хватается за соломинку и что-то мне не хватает. Не пора ли превратить строки в настоящие объекты со свойствами?


person Biggles    schedule 25.05.2012    source источник
comment
Такие переменные, как «$ thing1Place1Type1» - это просто псевдокод или вам действительно нужно вычислить имя переменной?   -  person Mick Sear    schedule 25.05.2012
comment
Каждый раз, когда у вас есть группа переменных с очень похожими именами, есть большая вероятность, что вам нужно пересмотреть свой дизайн. Например. $thing1place1, $thing1place2 и т. Д. Очень естественно сопоставляются, например, с $things_places = array( 1 => array( 1 => 'some place', 2 => 'another place' ), 2 => ... ); (или вы также можете использовать явные имена ключей, например 'places' => array( 1 => ... )). Перейдите к более разумной модели данных, и вы обнаружите, что с подобными проблемами намного легче справиться, если их вообще не существует.   -  person Jordan Running    schedule 25.05.2012


Ответы (3)


если вы хотите преобразовать их в объекты ... вы можете создать это.

  class Object {
        private $thing;
        private $place;
        private $type;

        public function __construct() {
            $this->thing = $_POST['thing'];
            $this->place = $_POST['place'];
            $this->type  = $_POST['type'];

            $this->processThing($this->thing, $this->place, $this->type);
        }

        public function processThing($thing = false, $place = false, $type = false) {
               //noW that you have all the properties you just need just process it
        }

    }

    if(isset($_POST['thing']) && isset($_POST['place']) && isset($_POST['type'])) {
        $object = new Object();
    }
person Michael Roewin Tan    schedule 25.05.2012
comment
Это было ближе всего к тому, что я должен был сделать в итоге. Я построил объекты и получил свойства Thing, Place, Type из самого имени переменной. Тогда было намного проще просто сделать несколько if ($thing && $place && $type) операторов. - person Biggles; 29.05.2012
comment
Это похоже на ту же логику, которую я использовал бы для написания функции для автоматического заполнения XML-схемы. Возможно, вы только что натолкнули меня на действительно хорошую идею для функции страницы. - person Imperative; 30.09.2013

Вам необходимо преобразовать код в функции. Например:-

switch($_POST['thing'])
{
  case "thing1":
      $result = processThings($thing1);
      break;
  case "thing2":
      $result = processThings($thing2);
      break;
}

function processThings($thing)
{
    //processing code goes here
}

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

person vascowhite    schedule 25.05.2012
comment
Это помогло, но после этого все еще оставалось неразрешимым беспорядком, поэтому мне пришлось переписать весь раздел. - person Biggles; 29.05.2012
comment
@Biggles тоже взгляни на этот ответ. stackoverflow.com/a/106482/212940 - person vascowhite; 29.05.2012

Что ж, если вы можете найти способ избежать компрометации вашего сайта людьми - возможно, используя префиксы в именах целевых переменных, тогда вы сможете сделать это:

$variableName = "A prefix_".$_POST['thing'].$_POST['type'].$_POST['place'];

$evaluatedVariable = $$variableName;

Их называют «переменные переменные». Возможно, меня разозлят за их использование, но в прошлом я находил их полезными, если вы можете использовать их ответственно.

Конечно, это не сработает напрямую для вашего случая «все типы». Вы можете использовать предложение по рефакторингу в функции

person Mick Sear    schedule 25.05.2012
comment
Это ужасно небезопасно и плохое предложение. Возможно, его будет не так много, если вы сначала добавили if (in_array($_POST['thing'],array("thing1","thing2"))){..}, прежде чем использовать. - person UltraInstinct; 25.05.2012
comment
Да, это могло сработать - конечно, это было причиной префикса - он ограничивает возможные переменные, которые могут быть оценены - person Mick Sear; 25.05.2012
comment
Проголосовал за это. Я действительно пробовал идею в этом направлении, потому что я мог достаточно легко проверить ввод, чтобы убедиться, что он безопасен (плюс, в любом случае, это не веб-интерфейс). Однако все усложнилось из-за всех выборов. - person Biggles; 29.05.2012
comment
Спасибо, Biggles :) Это что-то вроде «мармита», и вы определенно должны помнить о безопасности, поскольку люди сразу же на это указывают. Конечно, может быть полезно в некоторых контекстах. - person Mick Sear; 29.05.2012