Задать вопрос
Ответы пользователя по тегу PHP
  • Как писать условие if если очень много значений для проверки, а нужно чтобы они за экран не залезали, не превращались в очень длинную строку?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Это очень хороший вопрос!

    Для длинных условий можно и нужно использовать такую замечательную практику, как именованные условия!
    В большинстве случаев, когда условия не зависят друг от друга, можно просто присвоить результат вычисления условия переменной с обязательно говорящим именем, и дальше уже использовать эти переменные:

    $dateIsValid = $obj->getDate() >= getCurrentDate();
    $balanceOk = $obj->getBalance() > 0;
    // Любые другие условия
    if ($dateIsValid && $balanceOK) ...


    Это повышает читабельность не только сокращая само тело условного оператора, но в первую очередь превращая его в связный текст!

    Если же условия зависят друг от друга, то можно оформлять их в виде функций (методов). И тогда они не будут выполнены, если до них не дойдет очередь.
    Ответ написан
  • Что не так с функцией?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Настал момент познакомиться с такими понятиями, как отладка и безопасное выполнение SQL запросов.

    Программисты не задают посторонним вопрос, "почему мой код не работает".
    Они задают его своему коду.

    Вы уже начали отлаживать свой код, выводя промежуточные результаты. Это очень хорошо. Но почему-то тут же остановились

    Ну если запрос не находит записей - разве не логично вывести его на экран и посмотреть, что с ним не так.

    А после того, разберётесь с запросом, надо будет его переписать на подготовленные выражения. Потому что вот это вот - это какой-то позор
    Ответ написан
    Комментировать
  • Интерфейсы в связке с абстрактными классами?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Смысл простой.
    Интерфейс - это публичный контракт. То, как класс виден внешнему миру.

    Абстрактный класс - это прототип внутренней реализации, то, как он устроен внутри.

    Так что дополнять можно и нужно.
    Ответ написан
    Комментировать
  • Почему не видит файлы, если они не находятся в одной папке с index.php?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Если путь к файлам верный, то всё работает
    Ответ написан
    Комментировать
  • Как правильно ставить куки для авторизации?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Как всегда, здесь подводит логика.
    Если в базе есть что красть, то при "угоне базы" возможность авторизоваться будет самой меньшей из проблем.
    Если в базе кроме логина и взять нечего, то и возможность авторизоваться не поможет. Ну угнал ты скажем аккаунт пользователя интернет-магазина - и какой с этого навар?

    Не говоря уже о том, что "угнать базу" не так легко как кажется. Если это в принципе возможно, то значит проект в принципе ламерский, и в нём и других дыр выше крыши - то есть авторизоваться можно будет скажем через XSS или SQLi

    Во всех нормальных системах никто такими нелепыми страхами не страдает и нормально хэши хранятся в базе, что дает возможность контроля авторизации, в том числе на выбранных устройствах.

    Если же нет уверенности в собственных силах, что удастся защитить базу от слива, то можно использовать JWT токены.
    Ответ написан
    Комментировать
  • Тернарный оператор, ?? вместо ?:, зачем?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Надо включить информирование об ошибках.
    Тогда сразу станет видно, что код работает не точно так же
    Ответ написан
    Комментировать
  • Как совместить elasticsearch и php 7.0?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    > хочется понять насколько сложно сделать апдейт на 3 версии.

    Несложно. Отличия минимальны. В рамках одной мажорной версии вообще никаких проблем. Тут вопрос даже не в трудностях, а в том, что оставаться на 7.0 это вообще не вариант.
    Только переезжать надо на 7.4, потому что поддержка 7.3 прекращается через месяц.

    И вообще, версию надо подтягивать не когда жареный петух в зад клюнет, а планово.
    Ответ написан
    1 комментарий
  • Нужно ли два раза прописывать session_start()?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Не "два", а в каждом скрипте, который использует сессии.
    поэтому обычно её просто кладут в общий файл, который инклюдится во все скрипты

    Ошибка headers already sent к количеству вызовов отношения не имеет, это стандартная ошибка при кривой структуре кода и лечится элементарно. В интернете примерно миллион рекомендаций по её решению.
    Ответ написан
  • Как правильно получить массивы из формы в POST и отправить?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    foreach ($_POST as $key => $value) {
        echo "$key=". (is_array($value) ? implode(",", $value) :  $value)."<br />\n";
      }
    Ответ написан
    2 комментария
  • Apache не открывает страницы .php а отображает их списком файлов, как исправить?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
  • Стоит ли проверять имя и пароль пользователей при каждом запросе к api(guzzle)?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Стоит ли проверять имя и пароль пользователей при каждом запросе к api(guzzle)?

    Вот как всегда, в заголовке вопроса одно, а в тексте - ну совсем же другое.

    В моем случае выдавать токен вообще бессмысленно,верно?

    Верно

    Но в общем случае, на который претендует вопрос судя по заголовку, проверять каждый раз не стоит, а стоит выдавать по логину и паролю ограниченный по времени токен при запросе на отдельную точку входа.
    Ответ написан
  • Насколько целесообразно разбиение на функции и классы?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Это нормально.
    Ну то есть про конкретный код нельзя сказать, не видя его, но " выносить каждые пару строк в отдельную функцию" - это нормально. Куда нормальнее, чем писать всю тысячу в одной.

    Рекомендую найти видео "Как писать код, который понравится вашим тестам" с первой PHPRussia. Там очень доходчиво рассказывается про то, почему надо делать простые методы. Не только для тестов. А ещё и для повторного использования и для упрощения поддержки кода. Когда надо прочитать основную логику модуля, то даже сокращение в два раза (по одному методу вместо двух строк кода) уже сильно облегчает задачу.
    А если уж даже тест понял, что делает ваш код, то человек поймёт и подавно :)

    Как вам написали выше - все дело в именах методов. Если они информативные, то есть если конструкция
    if ($this->function_7($a) && $this->function_8($b))
    читается как связный английскй текст, то mission accomplished! Функции выполняют свою роль: легче всего читать код, которого нет. Вместо того, чтобы разбирать, что делает тот или иной код, можно просто прочитать небольшой текст на английском.
    Ответ написан
    4 комментария
  • Как перехватить любое исключение в php?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    В старых версиях PHP деление на ноль никакое не исключение, а обычная ошибка.
    О чем ясно написано в выводимом сообщении: Warning: Division by zero in ...

    Чтобы перехватывать ошибки, их надо конвертировать в исключения. В простейшем варианте
    set_error_handler(function ($level, $message, $file = '', $line = 0)
    {
        throw new ErrorException($message, 0, $level, $file, $line);
    });

    После установки такого обработчика все ошибки будут автоматически конвертироваться в исключения, и соответственно могут быть пойманы через try..catch:

    Fatal error: Uncaught ErrorException: Division by zero
    Ответ написан
    1 комментарий
  • Зачем использовать filter_input если можно тот же результат получить меньшим кодом?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Мне не нравится ни тот ни другой вариант.

    Сами по себе функции фильтрации - довольно странная часть языка. И нынешний отказ от FILTER_SANITIZE_STRING как раз подтверждает этот тезис. Задумка была в теории неплохая, но реализация получилась так себе. А, главное - все эти функции только насильно меняют значение переменной. Молча.
    А в нормальном современном приложении принято проверять переменную на соответствие правилам и выдавать ошибку

    В случае, если вместо числового id нам приходит вдруг массив, надо не молча его глотать и химичить с превращением в число, а сразу отвечать в репу 400-й ошибкой, не разводя сантименты.

    Поэтому я бы взял какую-нибудь либу для валидации, вот первая же из гугля, https://github.com/rakit/validation
    И нормально проверял входящие параметры.
    В случае, если это пользовательский ввод, типа логина и пароля, то отдавать культурные ошибки
    Если же это чисто внутренняя инфраструктура приложения, типа id из нашей же ссылки, то при наличии ошибок молча отдавал 400.
    Ответ написан
  • Как сделать прогресс бар с отрезками?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Задачка, конечно, очень смешная.
    И как всегда - на арифметику

    Шкала у нас нелинейная, первый шаг 100 единиц, последний - 2000.
    Но при этом для вычислений мы берём не позицию шага, а его значение.
    Ну и разумеется получаем то, что получаем.
    250 от 3000 - это никакие не "примерно 50 единиц", а примерно 8 процентов. Вот эти 8 процентов вам и показывает.

    Длина отрезка при разбивке на 5 частей будет 20%
    И вот 8 от 20 как раз и составляет те самые "примерно 50" процентов длины первого отрезка :)

    Выше товарищ правильно пишет про отладку.
    Но отладка в обязательном порядке состоит из двух вещей:
    1. Надо понимать, что делает твой код. В частности, иметь представление, какое значение каждая переменная должна иметь на каждом этапе.
    2. Запускать код, выводя промежуточные результаты, и сравнивая их с ожидаемыми.

    Без п.1 заниматься отладкой бессмысленно.
    Именно поэтому для программиста очень важно понимать, как работает его код. Иначе он просто не сможет его отладить.
    Ответ написан
  • Как протестировать производительность функций начинающему php-разработчику?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Никак.
    Никакой разницы в использовании системных ресурсов для разных способов вызова функций нет.

    Оценивать тот или иной подход следует с точки зрения архитектуры, а не воображаемой разницы в использовании системных ресурсов.
    Но для этого надо задать другой вопрос, или по крайней мере отредактировать этот, убрав из него все фантазии про системные ресурсы.
    Ответ написан
    7 комментариев
  • Возможно ли сделать конкатенацию к подготовленому sql запросу?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Возможно, но как правильно написал galaxy, prepare() нужно делать после формирования строки $sql, а не до.
    В общем случае это делается так:
    $sql = 'UPDATE product SET quantity = ?';
    $parameters[] = $quantity;
    if (....) {
        $sql .= 'AND name = ?';
        $parameters[] = $name;
    }
    $stmt = $db->prepare($sql);
    $stmt->bind_param(str_repeat("s", count($prameters)), ...$parameters);


    Но в вашем случае вы делаете что-то странное, там явно нужен скорее оператор IN. Но по этому коду очень сложно понять, что на самом деле нужно
    Ответ написан
  • В чём смысл передавать array_reverse в foreach без явной необходимости обратного порядка элементов?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Для ответов на подобные вопросы всегда полезно использовать логику.
    Например:
    Если необходимости в обратном порядке элементов нет, то array_reverse не нужна.
    Если array_reverse используется - значит, скорее всего, необходимость есть, но вы её просто не видите.

    Это универсальный способ, который позволяет ответить на можество подобных вопросов.

    "оставить исходный массив нетронутым" причиной не является.
    Ответ написан
  • Как обработать возникшую ошибку в PHP скрипте загрузки страницы?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Это очень хороший вопрос, по многим причинам.

    Во-первых, очень хорошо что он сам по себе поставлен. Обычно пользователи РНР не задумываются о таких "мелочах". Но на самом деле об этом должен думать каждый программист, делающий сайты
    Во-вторых, здесь мы можем видеть довольно характерный баг Апача, который действительно, почему-то не выполняет директиву ErrorDocument для 500 ошибок, полученных от РНР. Ну и вообще, завязываться на Апач во времена доминирования Нжинкса как-то не очень дальновидно.
    В-третьих, как правильно заметил Stalker_RED, сделать редирект при 500 статусе (или 500 статус при редиректе) невозможно - статус может быть только один. Да это и нет смысла делать - проще сразу на месте нужную страницу и прочитать.
    В-четвертых, текущий подход, прямо скажем, не очень оптимальный:
    - о роботах мы позаботились, о пользователе позаботились, но надо ещё не забыть и программиста. Которому как раз сообщение об ошибке-то нужно видеть во всех подробностях!
    - просто отдать нужный НТТР код недостаточно - надо бы ещё и завершить работу скрипта.
    - ловить все ошибки вручную через try-catch так себе удовольствие. И код раздувает,и поведение потом быстро не поменяешь. А если в какой-то момент захочется для отладки прикрутить whoops - это придётся по всем блокам бегать?

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

    В самом простом варианте это будет что-то вроде такого:

    set_exception_handler(function ($e)
    {
        error_log($e);
        http_response_code(500);
        if (ini_get('display_errors')) {
            echo $e;
        } else {
            include 'pages/error_500.php';
        }
    });

    В теории, конечно, можно заменить error handler на глобальный try-catch который оборачивает точку входа, но это менее удобно. Тем более, что для обработки фатальных ошибок нужен свой отдельный обработчик, и в итоге код обработки ошибок начинает занимать довольно значительный объем и лучше конечно его инициализацию вынести отдельно.
    Ответ написан
    Комментировать
  • Как удалить тег и содержимое с помощью preg_replace?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Лучшие собаководы настоятельно не рекомендуют удалять теги с помощью preg_replace.

    Строить dom дерево и обрезать ветки.
    Ответ написан
    1 комментарий