Лучший способ сделать PHP-переключатель с несколькими значениями для каждого случая?
Как вы это сделаете с помощью инструкции PHP?
Также обратите внимание, что это гораздо меньшие версии, у меня 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;
}
ОБНОВЛЕНИЕ - Результаты тестирования
Я провел некоторое испытание скорости на 10000 итераций,
Время1: 0.0199389457703//Если утверждения
Time2: 0.0389049446106//switch statements
Time3: 0.106977939606//Массивы
Ответы
Ответ 1
В любой ситуации, когда у вас есть неизвестная строка, и вам нужно выяснить, какая из нескольких строк она соответствует, единственное решение, которое не становится медленнее, когда вы добавляете больше элементов, - это использовать массив, но имеют все возможные строки в качестве ключей. Поэтому ваш коммутатор можно заменить следующим:
// 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
Версия 2 не работает!
case 'users.online' || 'users.location' || ...
точно такая же, как:
case True:
и что case
будет выбрано для любого значения $p
, если только $p
- пустая строка.
||
Не имеет особого значения внутри оператора case
, вы не сравниваете $p
с каждой из этих строк, вы просто проверяете, не является ли это False
.
Ответ 3
Поместите эти многие значения в массив и запросите массив, поскольку случай переключения, похоже, скрывает основную семантику того, что вы пытаетесь достичь, когда в качестве условия используется строковая переменная, что затрудняет чтение и понимайте, например:
$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';
}
Ответ 4
Если кто-либо еще когда-либо будет поддерживать ваш код, они почти наверняка сделают двойной вариант версии 2 - это крайне нестандартный.
Я бы придерживался версии 1. Я из школы, хотя утверждения этого случая без собственного блока операторов должны иметь явный комментарий // fall through
рядом с ними, чтобы указать, что это действительно ваше намерение провалиться, тем самым устраняя любую двусмысленность того, будете ли вы обращаться с делами по-разному и забыли или что-то в этом роде.
Ответ 5
Версия 1, безусловно, проще в глазах, более ясная, чем ваши намерения, и проще добавить кейсовые условия.
Я никогда не пробовал вторую версию. На многих языках это даже не компилируется, потому что метки каждого случая должны оцениваться в константном выражении.
Ответ 6
Для полноты, я укажу, что сломанная логика "Версия 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);
}
Ответ 7
Я определенно предпочитаю версию 1. Версия 2 может потребовать меньше строк кода, но будет очень трудно читать, как только у вас будет много значений там, как вы предсказываете.
(Честно говоря, я даже не знал, что версия 2 была законной до сих пор. Я никогда раньше не видел, чтобы это делалось раньше.)
Ответ 8
Нет версии 2 на самом деле не работает, но если вы хотите такой подход, вы можете сделать следующее (возможно, не самое быстрое, но, возможно, более интуитивное):
switch (true) {
case ($var === 'something' || $var === 'something else'):
// do some stuff
break;
}
Ответ 9
Некоторые другие идеи еще не упомянуты:
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, но у меня не будет проблем с наследованием такого кода.
Ответ 10
Я думаю, что версия 1 - это путь. Это намного легче читать и понимать.
Ответ 11
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;
}
}
Ответ 12
Переключение в сочетании с переменными даст вам больше гибкости:
<?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#105282
PS: Этот примерный код МАЛЕНЬКИЙ И ПРОСТОЙ, так, как мне нравится. Он протестирован и работает тоже