Лучший способ сделать PHP-коммутатор с несколькими значениями в каждом случае?
Как бы вы сделали этот оператор PHP switch?
также обратите внимание, что это гораздо меньшие версии, 1 мне нужно создать будет иметь гораздо больше значений, добавленных к нему.
Вариант 1:
switch ($p) {
case 'home':
case '':
$current_home = 'current';
break;
case 'users.online':
case 'users.location':
case 'users.featured':
case 'users.new':
case 'users.browse':
case 'users.search':
case 'users.staff':
$current_users = 'current';
break;
case 'forum':
$current_forum = 'current';
break;
}
Вариант 2:
switch ($p) {
case 'home':
$current_home = 'current';
break;
case 'users.online' || 'users.location' || 'users.featured' || 'users.browse' || 'users.search' || 'users.staff':
$current_users = 'current';
break;
case 'forum':
$current_forum = 'current';
break;
}
обновление-результаты теста
Я провел тест скорости на 10 000 итераций,
Time1: 0.0199389457703 / / если заявления
Time2: 0.0389049446106 / / переключатель заявления
Time3: 0.106977939606 // Массивы
12 ответов:
для любой ситуации, когда у вас есть неизвестная строка, и вам нужно выяснить, какая из группы другое строки он соответствует, единственное решение, которое не медленнее, как вы добавить больше деталей, чтобы использовать массив, но есть все возможные строки в качестве ключей. Таким образом, ваш коммутатор может быть заменен следующим:
// used for $current_home = 'current'; $group1 = array( 'home' => True, ); // used for $current_users = 'current'; $group2 = array( 'users.online' => True, 'users.location' => True, 'users.featured' => True, 'users.new' => True, 'users.browse' => True, 'users.search' => True, 'users.staff' => True, ); // used for $current_forum = 'current'; $group3 = array( 'forum' => True, ); if(isset($group1[$p])) $current_home = 'current'; else if(isset($group2[$p])) $current_users = 'current'; else if(isset($group3[$p])) $current_forum = 'current'; else user_error("$p is invalid", E_USER_ERROR);
это не выглядит так чисто, как
switch()
, но это только быстро решение, которое не включает в себя написание небольшого библиотека функций и классов, чтобы держать его в порядке. По-прежнему очень легко добавлять элементы в массивы.
Версия 2 не работает!!
case 'users.online' || 'users.location' || ...
точно так же, как:
case True:
и
case
будет выбран для любого значения$p
, Если$p
- пустая строка.
||
не имеет никакого особого значения внутриcase
заявление, вы не сравниваете$p
для каждой из этих строк, вы просто проверяете, чтобы увидеть, если это неFalse
.
поместите эти многие значения в массив и запросите массив, так как switch-case, похоже, скрывает основную семантику того, что вы пытаетесь достичь, когда строковая переменная используется в качестве условия, что затрудняет чтение и понимание, например:
$current_home = null; $current_users = null; $current_forum = null; $lotsOfStrings = array('users.online', 'users.location', 'users.featured', 'users.new'); if(empty($p)) { $current_home = 'current'; } if(in_array($p,$lotsOfStrings)) { $current_users = 'current'; } if(0 === strcmp('forum',$p)) { $current_forum = 'current'; }
Если кто-нибудь else когда-либо поддерживал ваш код, они почти наверняка сделали бы двойной захват версии 2-это чрезвычайно нестандартно.
Я бы придерживался версии 1. Я из школы, хотя в этом случае утверждения без собственного блока утверждений должны иметь явное
// fall through
комментарий рядом с ними, чтобы указать, что это действительно ваше намерение провалиться, тем самым устраняя любую двусмысленность того, собираетесь ли вы обрабатывать дела по-другому и забыл, что ли.
для полноты я укажу, что сломанная логика "версии 2" может быть заменена оператором switch, который работает, и и используйте массивы для скорости и ясности, например:
// used for $current_home = 'current'; $home_group = array( 'home' => True, ); // used for $current_users = 'current'; $user_group = array( 'users.online' => True, 'users.location' => True, 'users.featured' => True, 'users.new' => True, 'users.browse' => True, 'users.search' => True, 'users.staff' => True, ); // used for $current_forum = 'current'; $forum_group = array( 'forum' => True, ); switch (true) { case isset($home_group[$p]): $current_home = 'current'; break; case isset($user_group[$p]): $current_users = 'current'; break; case isset($forum_group[$p]): $current_forum = 'current'; break; default: user_error("$p is invalid", E_USER_ERROR); }
Версия 1, безусловно, легче на глазах, яснее о ваших намерениях,и легче добавить case-условия.
Я никогда не пробовал второй вариант. Во многих языках это даже не компилируется, потому что каждая метка case должна вычисляться в константном выражении.
некоторые другие идеи еще не упомянул:
switch(true){ case in_array($p, array('home', '')): $current_home = 'current'; break; case preg_match('/^users\.(online|location|featured|new|browse|search|staff)$/', $p): $current_users = 'current'; break; case 'forum' == $p: $current_forum = 'current'; break; }
кто-то, вероятно, будет жаловаться на проблемы с читаемостью с #2, но у меня не было бы проблем с наследованием такого кода.
Я определенно предпочитаю версию 1. Версия 2 может потребовать меньше строк кода, но это будет очень трудно читать, как только у вас есть много значений там, как вы предсказываете.
(честно говоря, я даже не знал, что версия 2 была права до сих пор. Я никогда не видел, как это делали раньше.)
никакая версия 2 на самом деле не работает, но если вы хотите такой подход, вы можете сделать следующее (вероятно, не самый быстрый, но, возможно, более интуитивный):
switch (true) {
case ($var === 'something' || $var === 'something else'):
// do some stuff
break;
}
if( in_array( $test, $array1 ) ) { // do this } else if( stristr( $test, 'commonpart' ) ) { // do this } else { switch( $test ) { case 1: // do this break; case 2: // do this break; default: // do this break; } }
переключатель в сочетании с переменные даст вам больше гибкости:
<?php $p = 'home'; //For testing $p = ( strpos($p, 'users') !== false? 'users': $p); switch ($p) { default: $varContainer = 'current_' . $p; //Stores the variable [$current_"xyORz"] into $varContainer ${$varContainer} = 'current'; //Sets the VALUE of [$current_"xyORz"] to 'current' break; } //For testing echo $current_home; ?>
чтобы узнать больше, оформить заказ переменные и примеры, которые я представил в руководстве php:
Пример 1: http://www.php.net/manual/en/language.variables.variable.php#105293
Пример 2: http://www.php.net/manual/en/language.variables.variable.php#105282PS: этот пример кода МАЛЕНЬКИЙ И ПРОСТОЙ, просто так, как мне нравится. Это проверено и работает тоже