За последние 24 часа нас посетили 22863 программиста и 1272 робота. Сейчас ищут 809 программистов ...

Получение числовых данных из GET/POST/etc

Тема в разделе "Прочие вопросы по PHP", создана пользователем Vladson, 10 ноя 2010.

  1. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    Уж слишком часто проскакивает этот момент, предлагаю всё-же обсудить.

    Допустим мы ожидаем число из $_GET['num'], и нам надо его использовать...

    Многие считают что правильно так: (даже в рнрВВ2 так реализовано)
    PHP:
    1. <?php
    2. $num = isset($_GET['num']) ? intval($_GET['num']) : 0;
    Или тоже самое
    PHP:
    1. <?php
    2. $num = isset($_GET['num']) ? (int)$_GET['num'] : 0;
    Я считаю не так, и вот почему.
    1 - Числа более 2млрд или менее -2млрд уже не прокатят
    (на 64-х битных системах говорят ограничения по выше, но как бы то ни было оно есть, и это нелогично)
    2 - '2фывапро' будет равняться 2
    (а это не одно и тоже)
    Грубо говоря всё это не проблема, а проблема в том что такие действия не являются логичными.

    И если первое можно исправить так: (Если отрицательные значения не нужны)
    PHP:
    1. <?php
    2. $num = isset($_GET['num']) ? abs($_GET['num']) : 0;
    Или так: (если отрицательные значения могут быть)
    PHP:
    1. <?php
    2. $num = isset($_GET['num']) ? 0+$_GET['num'] : 0;
    Или даже так: (разврат, но работает)
    PHP:
    1. <?php
    2. $num = 0+@$_GET['num'];
    то второе остаётся в силе...

    На мой взгляд, задачу надо разделить на несколько важных моментов.
    1 - Для чего мы ждём это число ? (могут ли например там быть отрицательные значения)
    2 - Обязательно ли мы ждём число, или есть значение по умолчанию если ничего не пришло ?
    3 Что делать если что-то пришло, но не то что мы не ждём ?

    Все эти моменты очень важны, и влияют на оптимальность решения.
    На мой взгляд данные надо не "приводить к нужному нам виду" а проверять "нужные данные пришли или шлак"

    Таким образом если мы решим получить число то.
    Во всех случаях надо:
    - Убедиться что число именно пришло // isset($_GET['num'])
    Если нужно именно число, то надо:
    - Убедиться что пришло именно число // is_numeric если допустимы отрицательные или ctype_digit если недопустимы
    Для конкретно постраничной разбивки надо:
    - Убедиться что число не меньше 1 // $_GET['num'] >= 1
    - Убедиться что число не больше количества страниц // $_GET['num'] <= $pages
    (№4 кстати игнорируют вообще почти все, хотя это неправильно с точки зрения логики)

    Т.е даже самая простая постраничная разбивка должна быть как минимум не хуже этого примера...
    PHP:
    1. <?php
    2. // Шаг 1
    3. if ( !isset($_GET['page']) ) {
    4.     die('выводим ошибку 404 или редирект на первую страницу, итд');
    5. }
    6. // Шаг 1 альтернативный (если по умолчанию есть значение, в нашем случае 1)
    7. $_GET['page'] = isset($_GET['page']) ? $_GET['page'] : 1;
    8.  
    9. // Шаг 2 и 3 можно объединить
    10. if ( !ctype_digit($_GET['page']) || $_GET['page'] < 1 ) {
    11.     die('выводим ошибку но так-же посылаем нафик кулхацкера который
    12.     пихает в URL всякую фигню, хотя может кто-то опечатался просто');
    13. }
    14. // Шаг 4 (теперь уже можно подконектиться к базе и)
    15. if ( $_GET['page'] > $pages ) {
    16.     die('Сообщаем что страницы нету, например пишем что страница
    17.     могла быть удалена и ссылка устарела, или просто 404 по вкусу');
    18. }
    19. // замечу так-же что я не копирую $_GET['page'] в просто $page
    20. // Зачем ? Кому станет проще если у нас будет 2 одинаковые переменные ?
    Кто со мной, а кто хочет с этим аргументированно поспорить ?
     
  2. Апельсин

    Апельсин Активный пользователь

    С нами с:
    20 мар 2010
    Сообщения:
    3.645
    Симпатии:
    2
    обычно, "ожидаю" положительно число и != 0.
    Следующая фишка отрабатывается на ура:
    ничего другого и не нужно придумывать. С миллиардами дел не имел.
    А abs() чаще не юзаю, так как проверка есть, типа:
    if($id > 0)
    else $error = '';
     
  3. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    Чем тогда $num = 0+@$_GET['num']; хуже ?
    (случаев когда отсутствие нотисов в логах из-за собаки быть не может физически, тогда почему бы не упростить лишьний раз код ?)
     
  4. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.553
    Симпатии:
    631
    is_numeric наше все!
    PHP:
    1. <?
    2. is_numeric('8728473889823432489789987890894329084'); // true
    3. is_numeric('-8728473889823432489789987890894329084'); // true
    4. is_numeric('+8728473889823432489789987890894329084'); // true
    5. is_numeric('8728473889823432489789987890894329084bla'); // false
     
  5. Апельсин

    Апельсин Активный пользователь

    С нами с:
    20 мар 2010
    Сообщения:
    3.645
    Симпатии:
    2
    тем что это говнокод :)
     
  6. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    Апельсин
    Поясни. Собака это вполне официальная конструкция языка, почему её использование так тебя пугает ?
    Ты можешь привести пример когда (в этом примере) она явится причиной какого либо бага ?

    Или просто какой-то умник так сказал, а ты повторяешь ?
     
  7. Апельсин

    Апельсин Активный пользователь

    С нами с:
    20 мар 2010
    Сообщения:
    3.645
    Симпатии:
    2
    Vladson
    причем тут баг. Говнокод - это не всегда бажный кусок кода, он просто неграмотно/неудобно/некрасиво написан, но работать может точно также как и конфетка.
    Собака не есть хорошим тоном. Да, заюзать можно, когда это точно не вызовет какихто последствий. Например:

    Гуд:
    $var = null;
    for($i = 0; $i < $some; $i++)
    {
    $var .= ' word';
    }

    Не есть гуд:
    for($i = 0; $i < $some; $i++)
    {
    @$var .= ' word';
    }

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

    UP
    Если умник сказал толковую мысль, то почему бы не повторять :)
     
  8. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    $var = ""; в этом случае правильнее, и в твоём примере собака действительно говнокод потому что переменная должна быть (иначе будет уязвимость)

    Где неграмотность ?
    Где неудобство ?
    Кто сказал что строка в чёрт знает сколько символов с условиями красивее чем коротенькое объявление переменной ?

    У него должны были бы быть аргументы, и у тебя ибо ты с ним согласился. Не вижу их.

    Повторяю, приведи пример того когда моя собака (в отличии от твоей) сделает хуже ?
    (принимаются даже нелепые отмазы что "когда выйдет РНР 99.9.9 её отменят итд")
     
  9. Апельсин

    Апельсин Активный пользователь

    С нами с:
    20 мар 2010
    Сообщения:
    3.645
    Симпатии:
    2
    нет, именно null. И проверку делаю через null

    $text = isset($_POST['text'])?$_POST['text']:null;

    а это
    поповщина.
    Еще напиши:
    if(isset($_POST['text'])) $text = $_POST['text'];
    else $text = '';
    попов именно так рекомендовал.

    далее
    @ - это подавление ошибок. Обработка ошибок и подавление их - это разные вещи. В первом случае у тебя под контролем то что ты ожидаешь получить, во втором (твоем) это называется - А хyй его знает что там прийдет, заглушу на всякий случай.
    В твоем случае можно через @, твое дело. Только негласно принято придерживаться какогото одного стиля именования переменных, функция, точно так же и обработки стандартных (число, строка) переменных. А не один раз через @, второй раз через тернарный оператор.

    какие аргументы должны быть у хорошего тона написания кода? давай все в одну километровую строку писать, один хрен, все обработается правильно и без багов. Это ты предлагаешь?
    пхп позволяет писать ногами, какие конечности у человека более развиты - теми пусть пишет.
     
  10. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    Твоё право, но изменение типа таким образом не является хорошим тоном. В строго типизованных например языках пришлось бы делать типа
    var = convert2string(null);
    (а РНР однажды уже думали сделать более типизованным, хотя и передумали, но в некоторых случаях даже нотисы выскакивают)
     
  11. Gromo

    Gromo Активный пользователь

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    главное чтобы работало без ошибок и было удобно. сам пользуюсь

    $id = (isset($_POST['id']) && $_POST['id']>0) ? (int)$_POST['id'] : 0;

    Согласен с Апельсин, что собака - это конструкция, которую не нужно использовать где попало.
     
  12. Апельсин

    Апельсин Активный пользователь

    С нами с:
    20 мар 2010
    Сообщения:
    3.645
    Симпатии:
    2
    пришлось бы и тебе со свою конструкцию $var = ""; переписывать в таком соответствии с указанием типа переменной.
     
  13. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    Ладно отложим собаку, я в принципе согласен что это "не к месту" в хорошем проекте, о чём написал сразу
    А что касается всего остального ???

    Ошибки будут при больших числах, о чём я и написал.

    Код (Text):
    1. $test = "";
    2. var_dump( $test);
    HTML:
    1. string(0) ""
     
  14. Апельсин

    Апельсин Активный пользователь

    С нами с:
    20 мар 2010
    Сообщения:
    3.645
    Симпатии:
    2
    выделенный кусок излишний.
     
  15. Gromo

    Gromo Активный пользователь

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    нифига, айди не может быть отрицательным.
    хотя... в принципе нулём тоже быть не должен :)
     
  16. Апельсин

    Апельсин Активный пользователь

    С нами с:
    20 мар 2010
    Сообщения:
    3.645
    Симпатии:
    2
    Gromo
    как я уже говорил юзаю такое:
    $id = isset($_POST['id'])?(int)$_POST['id']:0;
    if($id > 0)//action
    else //error

    таким методов двух зайцев шлёпаю - и проверка на отрицательное число, и не равняется нулю.
    потому в твоем случае тот кусок излишний
     
  17. Зверь

    Зверь Активный пользователь

    С нами с:
    2 ноя 2010
    Сообщения:
    80
    Симпатии:
    0
    Адрес:
    Екатеринбург
    Апельсин vs Vladson - 1:0
    Если нужен только положительные числа, то все верно.
     
  18. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    Да нет, это 1:0 по офтопу, и 0:1 по теме (в его подходе баг который проявится при больших числах)
     
  19. Зверь

    Зверь Активный пользователь

    С нами с:
    2 ноя 2010
    Сообщения:
    80
    Симпатии:
    0
    Адрес:
    Екатеринбург
    А в реальном приложении, ты ведь ожидаешь определенные числа и если у тебя реально не должны приходит большие числа, то ...
    Вообщем ничья 1:1 )))
     
  20. Апельсин

    Апельсин Активный пользователь

    С нами с:
    20 мар 2010
    Сообщения:
    3.645
    Симпатии:
    2
    если нужны только положительные числа, следовательно, должна следовать еще одна проверка на то что число > 0
    в итоге тот выделенный кусок будет продублирован
     
  21. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    Если столько есть в базе то должны любые, иначе рано или поздно сайт рухнет и придётся его поднимать
     
  22. Зверь

    Зверь Активный пользователь

    С нами с:
    2 ноя 2010
    Сообщения:
    80
    Симпатии:
    0
    Адрес:
    Екатеринбург
    Апельсин
    Согласен
     
  23. Апельсин

    Апельсин Активный пользователь

    С нами с:
    20 мар 2010
    Сообщения:
    3.645
    Симпатии:
    2
    to Зверь
    to Vladson

    в своем первом сообщении я написал про то что это не "миллиардный" подход. Нечего мое решение для чисел, максимум до миллиона "натягивать" на решение псевдопроблемы, описанное Владсоном.
     
  24. Apple

    Apple Активный пользователь

    С нами с:
    13 янв 2007
    Сообщения:
    4.984
    Симпатии:
    2
    Медитируем:
    PHP:
    1. <?php
    2.  
    3. $id = &$_GET["id"];
    4.  
    5. if(preg_match('/^[0-9]+$/i', $id)) {
    6.     echo 'a';
    7. }
    8.  
    9. ?>
     
  25. Апельсин

    Апельсин Активный пользователь

    С нами с:
    20 мар 2010
    Сообщения:
    3.645
    Симпатии:
    2
    [​IMG]