[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Разница? preg_match("/^[/d]+$",$a) и is_numeric()
Trueplayer
Здравствуйте, изучаю php.

Страхуемся от передачи методом GET ненужных вещей. Короче говоря, в переменной a должно быть число. Предлагается следующая проверка:
if (!preg_match("/^[\d]+$/",$a)) {exit();}
А мне кажется, что намного проще так:
if (!is_numeric($a)) {exit();}

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

Да, и еще... Я не слишком хорошо знаком с регулярными выражениями... Не могли бы вы пояснить, зачем нужны slash`ы с обеих сторон искомого выражения? Вот если нам нужно добавить параметр i, который говорит, что регистр не важен, тогда ясно зачем они нужны. А в данной ситуации?

Спасибо.

P. S. В теме допущена ошибка - slash перед d не в ту сторону smile.gif



Спустя 12 минут, 32 секунды (26.07.2010 - 22:49) inpost написал(а):
$a = intval($_GET['a']);

Спустя 16 минут, 29 секунд (26.07.2010 - 23:06) Trueplayer написал(а):
Ок. И все-таки, есть ли разница между двумя теми, которые я привел (применительно к данной ситуации, разумеется)
?
И еще возникла задачка: нужно проверить на соответствие (опять через GET передаю) ГГГГ-ММ.
У самого получилось ограничить год (от 2001 до 2099 - Уже не надо), а месяц только от 01 до 19: preg_match("/^20\d{2}-[0-1][1-9]/",$_GET['date'])
Помогите, если это возможно.

Спустя 2 минуты, 22 секунды (26.07.2010 - 23:08) inpost написал(а):
Trueplayer Насчет основного вопроса: регулярки зло, и работают медленнее! + по твоему условию регулярки ты выводишь exit(); и человек получает белый лист из-за этого! А если берёшь intval, к примеру, то уже страница будет загружена, но будет взяты лишь цифры!

Спустя 6 минут, 15 секунд (26.07.2010 - 23:14) Trueplayer написал(а):
Неее, пустой не будет - у меня там будет предупреждение - это я осознаю. А если бы был реальный сайт, то еще бы и кнопку повесил с надписью "Назад".
Но, все-таки, посмотрев на то, как работает intval() не скажу, что это рациональное решение - так пользователь вообще может запутаться...
Так прокомментируете идентичность (или ее отсутствие) двух моих вариантов?

Спустя 40 минут, 6 секунд (26.07.2010 - 23:54) Ice написал(а):
Цитата (Trueplayer @ 27.07.2010 - 00:14)
Так прокомментируете идентичность (или ее отсутствие) двух моих вариантов?

Комментирую.

Разницы между подходами нет, но вот с точки зрения целесообразности встает вопрос: "А надо ли...?" Вопрос этот возникает после опыта работы и с тем и с другим подходом или же после выполнения несложного теста:

$a = 100500;
$s1 = microtime( true );
for( $i = 0; $i <= 100000; $i ++ )
$ans = is_numeric( $a ) ? 1 : 0;
$e1 = microtime( true );
$t1 = $e1 - $s1;

$s2 = microtime( true );
for( $i = 0; $i <= 100000; $i ++ )
$ans = preg_match( '/^\d+$/', $ans ) ? 1 : 0;
$e2 = microtime( true );
$t2 = $e2 - $s2;
print $t2 / $t1; // 3.4...3.8


Цитата (Trueplayer @ 26.07.2010 - 23:36)
Не могли бы вы пояснить, зачем нужны slash`ы с обеих сторон искомого выражения?

Эти слеши (не обязательно слеши) - ограничители шаблона подстановки регулярного выражения

Цитата (Trueplayer @ 26.07.2010 - 23:36)
P. S. В теме допущена ошибка - slash перед d не в ту сторону

Слеш перед d в правильную сторону, а вот в символьный класс этот метасимвол положен зря.

Спустя 1 час, 25 минут, 32 секунды (27.07.2010 - 01:20) Trueplayer написал(а):
Цитата
но вот с точки зрения целесообразности встает вопрос: "А надо ли...?"

Надо... мы же мелко плаваем... (признаю, не уточнил, место применения - заметки блога)
Цитата

$a = 100500;
$s1 = microtime( true );
for( $i = 0; $i <= 100000; $i ++ )
    $ans = is_numeric( $a ) ? 1 : 0;
$e1 = microtime( true );
$t1 = $e1 - $s1;

$s2 = microtime( true );
for( $i = 0; $i <= 100000; $i ++ )
    $ans = preg_match( '/^\d+$/', $ans ) ? 1 : 0;
$e2 = microtime( true );
$t2 = $e2 - $s2;
print $t2 / $t1; // 3.4...3.8

Вот, сразу видно - менеджер IT-проектов smile.gif Немного долго разбирался с целью этой программы (просто на русском языке вроде нет сайтов, где сказано именно про атрибут true функции microtime() ). Смысл программы вроде понял... Вы показали, что через регулярные выражения примерно в 3.5 раза медленнее (ну еще можно узнать в абсолютных показателях и по первой и по второй, если добавить print`ы)...

Кстати, вроде у вас ошибка - во втором блоке нужно не переменную ans проверять, а переменную a, по-моему. Но результат только увеличивается - в среднем в 4 раза дольше через регулярные выражения.

И еще, вроде, неправильно (нехорошо, точнее) проверять только заведомо истинные условия ($a = 100500). Вот если так: $a = '100500';, то регулярные выражения только 2.3 раза дольше выполняются.

И потом... а как еще-то? Intval(); не годится, а ничего не предпринимать, кажется, тоже не вариант...

Не удержался все-таки проверить:
$s3 = microtime( true );
for( $i = 0; $i <= 100000; $i ++ )
$ans = intval( $a ) ? 1 : 0;
$e3 = microtime( true );
$t3 = $e3 - $s3;
print $t3 / $t1; // около 1.1
НО, не уверен, что это имеет смысл (я про свой блок кода), так как сам по себе intval() вроде чуть по-другому действует (чувствую это на интуитивном уровне smile.gif)
Цитата
Эти слеши (не обязательно слеши)

Тут все ок - разобрался.
Цитата
Слеш перед d в правильную сторону, а вот в символьный класс этот метасимвол положен зря.

Нет, в неправильную... В СООБЩЕНИИ - в правильную, а в ТЕМЕ - в неправильную (еще в ней одного "закрывающего" слэша не хватает).
А что значит "положить в символьный класс этот метасимвол"? Просто PHP только дней 10 изучаю... Извините за безграмотность.

P. S. Смайл после должности - это не насмешка. Просто я мечтаю каким-нибудь там стажером в этой области работать и люди, уже в ней занятые, вызывают какие-то эмоции smile.gif

P. P. S. Кстати, как IT-manager, не можете дать какое-нибудь конкретное задание? Только не очень сложное... Просто интересно справлюсь или нет. А-то как видят, что тебе 17 лет, сразу дебилом считают smile.gif

Спустя 28 минут, 15 секунд (27.07.2010 - 01:48) Ice написал(а):
Цитата (Trueplayer @ 27.07.2010 - 02:20)
Надо... мы же мелко плаваем... (признаю, не уточнил, место применения - заметки блога)

Не надо, когда есть встроенная функция, предназначенная для поставленных целей. smile.gif

Цитата (Trueplayer @ 27.07.2010 - 02:20)
Кстати, вроде у вас ошибка - во втором блоке нужно не переменную ans проверять, а переменную a, по-моему.

Да, Вы правы, - не углядел. My bad smile.gif

Цитата
ну еще можно узнать в абсолютных показателях и по первой и по второй, если добавить print`ы

Поточный вывод - злая штука при проведении теста на время.

Цитата (Trueplayer @ 27.07.2010 - 02:20)
Вот если так: $a = '100500';

Для РНР это тоже истина. Он осуществляет преобразование типов автоматически. smile.gif
Тест:

$b = '100500';
$ans = is_numeric( $b ) ? 1 : 0;
print $ans; // 1


Цитата (Trueplayer @ 27.07.2010 - 02:20)
Intval(); не годится, а ничего не предпринимать, кажется, тоже не вариант...

Почему не предпринимать? Вы гарантированно здесь получите либо то, что Вам надо, либо ноль.

Цитата (Trueplayer @ 27.07.2010 - 02:20)
НО, не уверен, что это имеет смысл

Правильно:) Так как это не имеет смысла - интвал преобразует а не проверяет. smile.gif
Цитата (Trueplayer @ 27.07.2010 - 02:20)
А что значит "положить в символьный класс этот метасимвол"?

В регвырах есть понятие символьного класса, обозначаемого квадратными скобками, а есть понятие метасимволов, являющихся в каком-то смысле УЖЕ классами, например: \d и [0-9] - одно и тоже.
Цитата (Trueplayer @ 27.07.2010 - 02:20)
P. S. Смайл после должности - это не насмешка.

Да я и внимания не обратил smile.gif

Цитата (Trueplayer @ 27.07.2010 - 02:20)
Просто я мечтаю каким-нибудь там стажером
Удачи и терпения smile.gif

Спустя 7 минут, 40 секунд (27.07.2010 - 01:56) Trueplayer написал(а):
А задание можно? (я добавил в тот коммент уже потом)
Удача что-то поворачивается, как бы это сказать... !$a (где $a = 'лицо')
Цитата
Не надо, когда есть встроенная функция, предназначенная для поставленных целей.
Какая? или под словом встроенная имеется в виду, что php сам "охраняет" базы данных?
Цитата
Поточный вывод - злая штука при проведении теста на время.

Вроде вы меня не так поняли... под словом поточный - это в цикле что ли? я другое имел в виду. Просто вставить в конец блока
print $t1; (у вас ведь отношение $t2:$t1 (относительная величина), а я про абсолютную величину)
Цитата
Почему не предпринимать? Вы гарантированно здесь получите либо то, что Вам надо, либо ноль.

почему "либо ноль"?
echo intval(0x1A); // 26
echo intval('420000000000000000000'); // 2147483647
Цитата
В регвырах есть понятие символьного класса, обозначаемого квадратными скобками, а есть понятие метасимволов, являющихся в каком-то смысле УЖЕ классами, например: \d и [0-9] - одно и тоже.

Ох ты, а я кажется понял, что вы имели в виду: не нужно было там писать [\d], можно просто \d

Спустя 53 секунды (27.07.2010 - 01:57) Ice написал(а):


Тут регулярно проводятся конкурсы, попробуйте принять участие в них smile.gif

Спустя 9 минут, 29 секунд (27.07.2010 - 02:06) Trueplayer написал(а):
Ок.

Спустя 16 минут, 3 секунды (27.07.2010 - 02:22) Ice написал(а):
Цитата (Ice @ 27.07.2010 - 02:48)
Какая?

is_numeric
Цитата (Ice @ 27.07.2010 - 02:48)
почему "либо ноль"?

потому что не-число будет, поэтому ноль.
Цитата (Trueplayer @ 27.07.2010 - 02:56)
echo intval(0x1A); // 26
echo intval('420000000000000000000'); // 2147483647

1. другое основание. Скрипт ожидает число - скрипт его получает
2. максимальное знаковое для х32-систем.
Цитата (Trueplayer @ 27.07.2010 - 02:56)
не нужно было там писать [\d], можно просто \d
Нужно, если кроме него больше никаких подстановок нет

Спустя 1 час, 11 минут, 25 секунд (27.07.2010 - 03:34) gzim9x написал(а):
Trueplayer
1. Если уж вы решили копать глубже, то и intval() и (int) конечно же можно использовать в проверках, например, в виде ($a==intval($a)) или ($a==(int)$a), но is_numeric() разрешает дроби да и работает быстрее.
если дроби вам не нужны (я сужу по \d в регекспе) -- то вам подойдет и is_int() -- быстрее чем is_numeric()... -- это если вы дошли до тестов smile.gif
2. Запись $a = '100500' ускоряет регулярку только из-за того, что регулярки работают со строками, -- а здесь уже не требуется прозрачно менять тип переменной для сравнения.

Спустя 4 часа, 42 минуты, 18 секунд (27.07.2010 - 08:16) linker написал(а):
Никогда так не делайте
$a = intval($_GET['a']);
надо так
$a = (integer)$_GET['a'];

Спустя 2 часа, 49 минут, 9 секунд (27.07.2010 - 11:05) Trueplayer написал(а):
Проверял все возможные варианты... Дроби мне не нужны, поэтому через int шел. Но тут тоже свои особенности...
1.
Цитата
($a==(int)$a)
- не работает. Да я и сам не пойму, почему должна работать. Насколько я понял (int)$a проверяет $a на принадлежность типу integer. Соответственно, должна возвращать или 0 или 1. А мы проверяем 0 или 1 на соответствие какой-то переменной. По-моему, неправильно, если я все правильно понял.
2. is_int() - тоже не работает, хотя у меня последний Денвер. Пишу так:
if (!is_int($cat)) {exit("Неверный формат запроса! Проверьте URL!");}.
3. Нашел один вариант:
if (!(int)$cat) {exit("Неверный формат запроса! Проверьте URL!");}
Так работает.
Кстати, не могли бы вы пояснить, чем отличаются следующие 2 условия:
1. if (!is_int($cat))
2. if (!(int)$cat)
И еще, я уже писал, но вроде никто не помог:
Цитата
И еще возникла задачка: нужно проверить на соответствие (опять через GET передаю) ГГГГ-ММ.
У самого получилось ограничить год (от 2001 до 2099 - Уже не надо), а месяц только от 01 до 19: preg_match("/^20\d{2}-[0-1][1-9]/",$_GET['date'])
Помогите, если это возможно.

Спустя 3 минуты, 58 секунд (27.07.2010 - 11:09) Basili4 написал(а):
linker
А разница в чем ??? я не наежаю мне интересно я видел рекомендации и первого варианта и 2

и немного модифицированный
$a = (int)$_GET['a']; В чем отличия ?

Спустя 7 минут, 52 секунды (27.07.2010 - 11:17) linker написал(а):
intval() - функция, (int)/(integer) работает гораздо быстрее, да и выглядит прилично как приведение к типу.

Спустя 11 минут, 21 секунда (27.07.2010 - 11:28) Ice написал(а):
Что верно, то верно.

Спустя 6 минут, 51 секунда (27.07.2010 - 11:35) Trueplayer написал(а):
Что-то форум тупит - сообщения нет моего...
Я только не пойму, почему второй из нижеприведенных блоков работает неправильно...
<?php
$cat = 5;
if (!is_int($cat)) {echo "Не int";}
else {echo "int";}
?>

Выводит int, как и нужно.
<?php
$cat = 5;
if (!is_int($cat)) {exit("Неверный формат запроса! Проверьте URL!");}
?>

А здесь выводит "Неверный формат запроса! Проверьте URL!" - по-моему, неправильно.
В чем дело?

Спустя 53 минуты, 26 секунд (27.07.2010 - 12:28) gzim9x написал(а):
Цитата (Trueplayer @ 27.07.2010 - 11:05)
Проверял все возможные варианты... Дроби мне не нужны, поэтому через int шел. Но тут тоже свои особенности...
1.
Цитата
($a==(int)$a)
- не работает. Да я и сам не пойму, почему должна работать. Насколько я понял (int)$a проверяет $a на принадлежность типу integer. Соответственно, должна возвращать или 0 или 1. А мы проверяем 0 или 1 на соответствие какой-то переменной. По-моему, неправильно, если я все правильно понял.

сорри, ($a==(string)(int)$a) -- так корректнее rolleyes.gif
(int)$a ничего не проверяет (а приводит значение к целому)-- потому и пришлось городить огород с проверкой на изначальное значение.
<?php
$cat = 5;
if (!is_int($cat)) {exit("Неверный формат запроса! Проверьте URL!");}
?>
этот вариант с is_int() у меня отработал правильно... -- попробуйте проверить вне основного кода.

Спустя 5 минут, 4 секунды (27.07.2010 - 12:33) linker написал(а):
if ($a==(int)$a) {} 
и
($a==(string)(int)$a)
Это глупость.

Спустя 43 минуты, 15 секунд (27.07.2010 - 13:17) gzim9x написал(а):
Цитата (linker @ 27.07.2010 - 12:33)
if ($a==(int)$a) {} 
и
($a==(string)(int)$a)
Это глупость.

rolleyes.gif
анализ почему первый вариант не работает а второй отрабатывает корректно поможет вам больше узнать о PHP.

Спустя 9 минут, 26 секунд (27.07.2010 - 13:26) linker написал(а):
$a==(int)$a - всегда true, даже если $a = 'stroka';
$a===(int)$a - false в случае $a = '1454'; и тому подобных, кроме $a = 1454;

Спустя 7 минут, 53 секунды (27.07.2010 - 13:34) Trueplayer написал(а):
Нет, так и не работает (вынес в отдельный кусок). Например, вот тут:
<?php
$cat = 5;
if (!is_int($cat)) {exit("Неверный формат запроса! Проверьте URL!");}
else {"Идем дальше!";}
?>
Вообще ничего не выводит.
Что-то столько разных вариантов, что я уже запутался... предложите один, удовлетворяющий:
1. Это не функция преобразования, а функция проверки
2. Мне нужно проверять множество всех символов на принадлежность подмножеству: от 1 до N, где N- натуральное и не очень большое (пусть будет до 2000 примерно). Все числа в подмножестве - натуральные. Короче говоря, как проверить, что введенное число - натуральное (преобразовывать его к натуральному не нужно)?

Спустя 9 минут, 19 секунд (27.07.2010 - 13:43) linker написал(а):
<?php
$cat = 5;
if (!is_int($cat)) die("Неверный формат запроса! Проверьте URL!");
echo "Идем дальше!";
?>
Теперь будет выводить "Идем дальше!".
Если $cat может быть таким $cat = '5'; то лучше
<?php
$cat = 5;
if (!is_numeric($cat)) die("Неверный формат запроса! Проверьте URL!");
echo "Идем дальше!";
?>

Спустя 19 минут, 22 секунды (27.07.2010 - 14:03) Trueplayer написал(а):
Нет, $cat не может быть '5'. Если брать как отдельный кусок, то работает (с die()), а вот внутри нужного кода - не работает, хотя, если просто удалить эту строку, то все работает. Как такое может быть?

Спустя 6 минут, 12 секунд (27.07.2010 - 14:09) gzim9x написал(а):
linker
Цитата
$a==(int)$a - всегда true, даже если $a = 'stroka';

все верно -- потому что PHP неявно приведет первый операнд к числу (тот же (int)).
Цитата
$a===(int)$a - false в случае $a = '1454'; и тому подобных, кроме $a = 1454;

опять же все верно -- потому как === в сравнении изначально учитывает тип данных.
Цитата
($a==(string)(int)$a)

если первый операнд строка:
происходит сравнение в виде строк -- отрабатывает корректно.
если первый операнд число:
второй операнд в сравнении опять приведется к числу! несмотря на (string), но все равно проверка будет корректной.

"Особенность оператора == в том, что при сравнении числа и строки, просходит преобразование строки в число. Если строка не представляет собой число, то она преобразуется в числовое значение 0."

Спустя 6 минут, 50 секунд (27.07.2010 - 14:16) linker написал(а):
Короче
$cat = 5;
if (is_numeric($cat)) echo "Число";

Спустя 15 минут, 44 секунды (27.07.2010 - 14:32) linker написал(а):
Цитата
Если строка не представляет собой число, то она преобразуется в числовое значение 0.
Ошибочное утверждение, ибо
$a = '43aaa2bbb4';
echo (integer)$a;
приведет $a к целочисленному значению 43.

Спустя 4 часа, 31 минута, 35 секунд (27.07.2010 - 19:03) gzim9x написал(а):
Цитата (linker @ 27.07.2010 - 14:32)
Цитата
Если строка не представляет собой число, то она преобразуется в числовое значение 0.
Ошибочное утверждение, ибо
$a = '43aaa2bbb4';
echo (integer)$a;
приведет $a к целочисленному значению 43.

согласен -- это просто другая запись числа, на даже с ней проверка ($a==(string)(int)$a) отработает корректно...

Спустя 1 час, 49 минут, 19 секунд (27.07.2010 - 20:52) linker написал(а):
$a= '43aaa2bbb3' - это не другая форма записи числа.
$a==$a - всегда отработает корректно, потому и сказал, что это глупость. Вы можете извращаться как вам душе угодно
хоть $a == (int)$a
хоть $a == (string)(int)$a
хоть $a == (int)(string)$a
хоть $a == (int)(float)$a
...
Любое подобное равенство вернет корректное TRUE, ибо $a всегда равно само себе.

Спустя 1 час, 57 минут, 31 секунда (27.07.2010 - 22:50) gzim9x написал(а):
Цитата (linker @ 27.07.2010 - 20:52)
$a= '43aaa2bbb3' - это не другая форма записи числа.
$a==$a - всегда отработает корректно, потому и сказал, что это глупость. Вы можете извращаться как вам душе угодно
хоть $a == (int)$a
хоть $a == (string)(int)$a
хоть $a == (int)(string)$a
хоть $a == (int)(float)$a
...
Любое подобное равенство вернет корректное TRUE, ибо $a всегда равно само себе.

уфф... сколько же на вас нужно нервов (хотя упрямство по моему мнению одно из ведущих качеств настоящего программера smile.gif ) и тем не менее:
$a="gkjghjg";
if ($a==(string)(int)$a)
print 'не прав gzim9x';
else
print 'не прав linker';

что-то не наблюдаю TRUE в сравнении... а значит кому-то нужно будет углубиться в мануалы wink.gif

Спустя 4 минуты, 28 секунд (27.07.2010 - 22:54) linker написал(а):
Я рассматриваю в контексте текущего сабжа, где переменная является числовым представлением, вы же углубились дальше, где я действительно неправ.

Спустя 4 минуты, 23 секунды (27.07.2010 - 22:59) yurij__ написал(а):
Цитата (linker @ 27.07.2010 - 05:16)
Никогда так не делайте
$a = intval($_GET['a']);
надо так
$a = (integer)$_GET['a'];

а чем первый вариант плох?

Спустя 1 минута, 41 секунда (27.07.2010 - 23:00) linker написал(а):
yurij__
Вторая страница текущего топика, второе сообщение сверху.
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2025 Invision Power Services, Inc.