Pull to refresh

Comments 68

Второй вариант не работает. Если первай case найден, то остальные выполняются игнорируя case, до breakа.

Иначе,

switch ($x)
{
case 1:
echo 1;
case 2:
echo 2;
case 3:
echo 3;
}

Выведет 123, если икс=1.
Вообще, я пробелами делал выравнивание. Думал, <code> их не вырежет. ^_^

В любом случае, я не вижу выигрыша перед

$errors = array();
if (!is_numeric($phone)) $errors[] = 'badphone';
if (!is_email($email)) $errors[] = 'email';
if (!foo($bar)) $errors[] = 'quux';

if (!empty($errors)) boo();
Действительно...
Пожалуй, уберу эту часть вообще...
Программисты, млин... :)
А break за тебя кто будет ставить? Мама?
switch ($x)
{
case 1:
echo 1; break;
case 2:
echo 2; break;
case 3:
echo 3; break;
}
Если бы вы прочитали, что я написал, поняли бы, что я как раз и указывал на ошибку в коде, который написал автор статьи.
Легче написать статичный класс для валидации данных.
Проверка полей, прослешивание и т.д. осуществляется у меня набором простых функций. Например:
validator::text($param, 1). Первый параметр является строкой или массивом строк. Второй (необязательный) проверяет допустимость пустого значения (0 - может быть пустым, 1 - поле является обязательным). Так же для всех остальных типов. Если, допустим, мне надо проверить правильность заполения поля Emial, то выполняется то просто:

if ($email = validator::email($email, 1)) {
     //выполяняем нужные нам действия
} else {
     // Выводим сообщение об ошибке
}
аха, фреймворки рулят
из статьи можно вынести только интересный switch
валидация и классы уже давно обогнали описываемое

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

$error_flag = true;
switch (true)
{
  case($_chck->field_empty('name')):
    $error_text = 'Вы не заполнили поле Имя.';
    break;
  case($_chck->field_numeric('age')):
    $error_text = 'Вы не заполнили, или неправильно заполнили поле Возраст.';
    break;
  default:
    $error_flag = false;
    $error_text = NULL;
}

если уж использовать switch, то по полной...
а вообще хорошая замена ifelse'ам, спасибо
А разве при таком подходе мы не получим ситуацию, что когда пользователь ошибся одновременно в нескольких полях, то ему выведется уведомление об ошибке только в том поле, которое в блоке проверок будет идти первым? И дальше по кругу, заставив пользователя по одной отловить все ошибки в форме?
Да, именно так и задумано.
Чтобы получить все ошибки, можно использовать такой подход...
Просто мне казалось, что с точки зрения удобства валидации для конечного пользователя, было бы неплохо сообщать ему обо всех ошибках сразу?
UFO landed and left these words here
Это зависит от конкретного проекта.
UFO landed and left these words here
Если не сложно, примеры таких проектов?
Например, если ошибки выводятся в модальном окне.
Только наверное речь идет о выводе предупреждений в процессе заполнения конкретного поля (а не о финальное проверке валидности)?
Тут, опять же, вопрос выбора конкретного программиста. Можно вызывать скрипт в процессе заполнения, но тогда нельзя будет проверять заполненность полей, а только соответствие данных (т.к. на момент заполнения поля a, поля b, c, d, ... точно еще не заполнены). А можно вызывать скрипт при сабмите формы, тогда если что-то заполнено не так, выдается модальное окно и пользователь остается исправлять данные.
UFO landed and left these words here
Да пишите хоть на Хаскле, меня это совершенно не волнует.
Я предложил лишь одно решение, которое мне кажется достаточно изящным, чтобы иметь право на жизнь.
Использовать, или нет — это личное дело каждого, я никому ничего не навязываю. А вот вы лезете со своим уставом в чужой монастырь...
UFO landed and left these words here
Вы говорите, как вы бы стали решать такую вещь.
Это две большие разницы.
UFO landed and left these words here
По-моему не здорово заставлять пользователя 5-6 раз закрывать модальное окно с единственным сообщением об ошибке. А на сложных формах это будет выглядеть откровенным издевательством.
UFO landed and left these words here
Может и так, но о велосипедах человек правильно сказал. Только это уже не от языка зависит, а от познаний программиста.
UFO landed and left these words here
Не нравится - не читайте, зачем в каждом топике хаять все на чем свет стоит.
Потому что кто-то из начинающих может принять это (содержимое топика) "за чистую монету", за best practice.
Они наверняка почитают обсуждение тоже.
Для этого здесь и оставлен коммент, не правда ли?
Так кто вам мешает создать рядом топик, в котором вы сможете высказать вашу точку зрения на этот вопрос, помогая начинающему пользователю найти действительно чистую монету!?
Готов поспорить, что найдется масса "профессионалов", которые испачкают ваш best practice...
Я не понимаю, Вы на что обиделись-то? На то, что ваше решение критикуют? Что оно кому-то не нравится?
А кто вам сказал, что я обиделся? (:
Я всего лишь, здесь, как и вы, отстаиваю свою точку зрения...
Мне показалось, что Вы како-то очень болезненно восприняли критику в адрес вашего примера. "Создайте другой топик рядом", "со своим уставом в чужой монастырь". Рад, если это не так.
А я всегда думал, что ф-ция field_empty выглядит примерно так:
public function isEmpty($field)
{
return (!isset($this->data[$field]) || strlen(trim($this->data[$field])) == 0);
}
Акваланг?
Логику исходной функции автора я не трогал, потому что это не главное здесь.

Про empty я знаю, спасибо.
Простите, не хотел обидеть. ,)

Просто иногда банальные функции из головы вылетают, думал, мало ли. :)
Я тоже был резок, пожалуй :)
empty() не выловит, например, введенный пробел, а для приведенного поля это будет ошибкой
Это уже сугубо личное дело каждого. Когда таких функция сотня, все-таки хочется, чтобы они были более читаемыми...
Если честно, то я не понимаю, как семь лишних, ничего не делающих строчек, могут повысить читаемость кода. Хотя, вы, разумеется, правы — хозяин барин.
Может стоит вместо switch использовать полиморфизм: код будет понятней и легко расширяемый + не будет дублирования, если проверок несколько.
Очень красиво.
В конструкторе можно воткнуть
foreach($a as &$value) {
   $value=trim($value);
}
Ваша конструкция работает только в PHP >= 5.

В любом случае, есть лучшее решение:

$a = array_map('trim', $a);
UFO landed and left these words here
У меня опять глупый вопрос.
В чем разница (с точки зрения PHP) между конструкцией
if (func1($a)) {...}
elseif (func2($a)) {...}
elseif (func3($a)) {...}

и такой:
switch(true)
{
case (func1($a)):
...;
break;
case (func2($a)):
...;
break;
case (func3($a)):
...;
break;
}

Не с точки зрения синтаксиса, а с т.з. отработки интерпретатором.
Трудно дать точный ответ... Лично я не нашел четкого описания такого подхода, встречал только примеры в комментариях... Но, я предполагаю, что ровным счетом никакой разницы нет...
Разница есть между:
<?php
if (myFunc($x) == 1)
{
echo 1;
}
elseif (myFunc($x) == 2)
{
echo 2;
}
elseif (myFunc($x) == 3)
{
echo 3;
}
else
{
echo 4;
}
?>
и
<?php
switch (myFunc($x))
{
case(1):
echo 1;
break;
case(2):
echo 2;
break;
case(3):
echo 3;
break;
default:
echo 4;
break;
}
?>

Тогда, в первом случае функция myFunc() (возможно) будет вызвана 3 раза, тогда как во втором случае только 1 раз.
Собственно, в этом и состоит основной смысл оператора switch().
Ну за первый вариант я бы вообще отбирал клавиатуру и отправлял учиться на юриста (no offence).
Возвращаясь к исходным примерам (в моём комменте), по-моему разницы никакой нет, а вариант с elseif'ами читается (тут ИМХО, конечно) не в пример лучше.
К тому же конструкция switch(true) - это вообще что-то по ту сторону добра и зла.
Да уж, так в жизни заведено: все самое интересное всегда по ту сторону добра и зла (:
Да ну, что в этой конструкции интересного-то? :) В практическом плане, а не в "перловом" ;)
Интересно то, кто когда спрашивают "как сделать несколько проверок" большинство отвечает "elseif"...
Можно сказать "нестандартный, но верный" подход...
большинство отвечает "elseif"...

Большинство отвечает решительно верно :)
Можно сказать "нестандартный, но верный" подход...

Верный только в том смысле, что работает :) С такой формулировкой соглашусь.
UFO landed and left these words here
Я могу ошибаться, но по-моему, по скорости они совершенно идентичны (т.к. одни и те же операции совершаются).
Скорость зависит от расположения проверок, например, если мы знаем, что наибольшая вероятность, что пользователь не заполнил какое-то поле, то нужно эту проверку поставить как можно выше (как в switch, так и в elseif конструкции). Хотя, разница в скорости будет настолько ничтожно мала, что этим вполне можно пренебречь.
ЕМНИП, switch раскладывается в дерево, что немного более ресурсозатратно elseif'ов, которые выполняются "в порядке поступления" и, конечно, не является идентичным.
Но пока что мне решение понравилось и уже довелось использовать;)
чОрт
Тысяча извинений, способ непригоден.
Switch действительно разворачивается в дерево - находятся значения всех case'ов, после чего switch проходит по этому дереву, ища совпадения.
Соответственно, у нас получается значительное замедление, плюс нежелательные вызовы. Ситуация должна быть редкой, чтобы затмить эти минусы. И уж точно этот способ не подходит для цепочки условий, в которой первое же нарушение должно прерывать выполнение.

"Эх..." сказали суровые сибирские мужики и пошли дальше писать elseif'ами
Вы меня прямо заинтриговали фразой «разворачивается в дерево». Даже мой воспаленный мозг не может представить, как это (:

Вот небольшой бенчмарк (если можно так сказать) для сравнения скорости работы двух методов:
<?php
function getmicrotime()
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}

function check1()
{
sleep(1);
return false;
}

function check2()
{
sleep(2);
return false;
}

function check3()
{
sleep(3);
return true;
}

function check4()
{
sleep(4);
return false;
}

/* ============ */

$ie_time_start = getmicrotime();

if (check1())
{
echo '1';
}
elseif (check2())
{
echo '2';
}
elseif (check3())
{
echo '3';
}
elseif (check4())
{
echo '4';
}

$ie_time = getmicrotime() - $ie_time_start;

/* ============ */

$sw_time_start = getmicrotime();

switch (true)
{
case(check1()):
echo '1';
break;
case(check2()):
echo '2';
break;
case(check3()):
echo '3';
break;
case(check4()):
echo '4';
break;
}

$sw_time = getmicrotime() - $sw_time_start;

/* ============ */

echo '<hr />';
echo 'ElseIf has taken ' . round($ie_time, 4);
echo '<br />';
echo 'Switch has taken ' . round($sw_time, 4);
?>
Можете попробовать сами, но у меня этот скрипт выводит:
ElseIf has taken 5.9997
Switch has taken 6.0001
Хотя, по вашей древесной теории switch в данном случае должен занимать никак не меньше 10 секунд, «проходя по всему дереву, ища совпадения»...
Более того, запустив скрипт более 3 раз можно увидеть, что зачастую switch отрабатывает быстрее, нежели elseif, но это уже причуды интерпретатора...
Предлагаю все-таки остановиться на предыдущем утверждении: «по скорости они совершенно идентичны (т.к. одни и те же операции совершаются)»
Разницы никакой. К elseif народ привычнее, нужно всегда помнить о человеке, которому возможно ваш код перейдет в наследство.
Угу, именно.
Лично я бы на строчке switch(true) при просмотре кода запнулся бы и вместо того, чтобы разобираться с сутью программы, начал бы анализировать, как оно работает.
Начинаешь в мозгу невольно бегать по строчкам как интерпретатор. Вообщем не есть гуд.
UFO landed and left these words here
Sign up to leave a comment.

Articles