Задать вопрос
Ответы пользователя по тегу PHP
  • Авторизация PHP. Как исправить Warning: Undefined array key "login" in?

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

    Чтобы исправить первый вариант, и вообще для порядка, надо добавить проверку на метод POST.
    Чтобы получить помощь для второго варианта, надо догадаться добавить в свой вопрос код формы.

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

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Тут проблема скорее не в том, что 4-5 лет, а в том, что за редчайшими исключениями, любые видеокурсы - это отборный говнокод. Конкретно про Дмитрия Лаврика не скажу, но простая статистика говорит о том, что учить РНР по видеокурсам не стоит.

    Лучше потратьтесь на книжку, Джон Дакетт, PHP&MySQL. Там очень толково, на примерах даётся не только язык, но и все важные аспекты программирования - обработка ошибок, отладка, рефакторинг, структура приложения, SQL, обработка изображений, и куча всего остального. В последних главах весь материал даётся на примере создания простой но рабочей социальной сети.
    Ответ написан
    1 комментарий
  • Как правильно настроить права для веб-сервере apache2+php-fpm?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Самое первое, что стоит проверять в таких случаях - это selinux.
    Самое второе - что все папки в цепочке от корня читаемы для пользователя пхп.

    А если говорить в целом, запускать пхп от пользователя хттп довольно бессмысленно. Пользователь фпм должен совпадать с владельцем файлов. То есть запускать надо от девопса.

    Лично я делаю так: веб-сервер работает под своими группой/пользователем, а пхп - под SSH логином пользователя сайта. У вас это может быть видимо этот девопс.
    Чтобы их поженить, просто добавляем пользователя веб-сервера в группу пользователя, usermod -a -G devops www-data, а папочке веб-сервера соответственно выставляются права 750. Веб-серверу нужно только чтение, и он его имеет через группу. Таким образом можно соорудить такой мини-хостинг, разные ползователи не могут ходить в папки друг друга, и при этом нет обычной чехарды, когда пользователь ssh/ftp и пользователь пхп-фпм разные.
    Ответ написан
    2 комментария
  • Как выбрать максимальное значение во вложенных массивах?

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

    Перебрать массив и получить максимальное значение - это три строчки. Куда проще-то?

    Есть какая-то функция или сочетание функций

    Есть поговорка. "Дурная голова ногам покою не даёт". И ещё есть принцип, KISS, который переводится как "не надо пытаться выглядеть умнее, чем ты есть, дурачок - опозоришься".

    Самый простой и красивый код - это тот который ты написал сам и понимаешь, как он работает. И сможешь в случае чего исправить. А не побежишь снова на Хабр, "мне тут пацаны дали красивое, а можно чтобы оно ещё и работало?"
    Ответ написан
    2 комментария
  • Что лучше использовать для связей в бд?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Ну разумеется, что в общем случае через SQL-запросы. Они для того и придуманы.
    Но есть нюансы, иногда связанные данные приходится доставать другими методами.
    Например, чтобы не делать 500 отдельных запросов, берутся id нужных записей и выбираются одним запросом через where in()

    Кстати, лучше всё-тиаки разделить код на модели и контроллеры. SQL убрать в модели, а в контроллерах оставить только вот это вот if ($pools) {
    Ответ написан
  • Deprecated: Implicit conversion from float to int loses precision in что не так?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Знаю, что надо как-то подставить (int) intval () floor() или round() на худой конец, но как?


    Предлагаю сразу два варианта
    1. разбить вызов imagecopy на строки, чтобы каждый операнд был на своей строке, включая и арифметические. ну то есть
    imagecopy (
    $img,
     $font,
     $x
     - 
    $shift,
    $y
    ...

    Так сразу будет видно, на какой строчке флот окопался.
    2. скопировать строчку, вместо imagecopy написать var_dump и заменить все минусы на запятые, с той же целью
    Ответ написан
  • Почему не работает Cron?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Почему не работает Cron?

    Наверное, вместо бессмысленного /dev/null надо указать путь к файлу, в котором появится ответ на этот вопрос?
    Ответ написан
    Комментировать
  • Положительно ли скажется на производительности перевод бд на utf8mb4 и удаление из after_connect_d7.php соответствующих директив?

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

    character-set-server и collation-server вообще ни на что не влияют. А только задают умолчания, если при создании БД и таблиц ленивый программист не указал кодировку. Поэтому трогать их нет смысла вообще.

    Добавлять utf8mb4 в соединение также бессмысленно, если сами данные в utf8. Расширенные символы она всё равно сохранить не сможет.
    И наоборот - если таблицы в utf8mb4, то указывать её при соединении надо в обязательном порядке. Не потому что вдруг "конвертация на лету" а потому что если соединение будет utf8, то расширенные символы клиент не получит.

    (В теории, всё может работать нормально и без установки utf8mb4 для соединения, поскольку она в пыхе в какой-то момент начала использоваться по умолчанию, но лучше всё-таки задавать явно)
    Ответ написан
    Комментировать
  • Почему аутентификация возвращает форму авторизации?

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

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    1. Гуглим simplexml_load_string ошибки
    2. Открываем страницу https://www.php.net/manual/ru/simplexml.examples-e...
    3. Берём с неё код и немного модицифируем

    libxml_use_internal_errors(true);
    
    $sXML = download_page($url);
    $xml = simplexml_load_string($sXML);
    
    if ($xml === false) {
        throw new RuntimeException(
            "XML parsing errors: ". implode("", array_column(libxml_get_errors(), 'message'))
        );
    }


    Смотрим ошибки, исправляем.
    Ответ написан
    Комментировать
  • Как передать имя таблицы как параметр?

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

    Таблица должна быть одна. И все проблемы сразу исчезнут как по волшебству.
    Ответ написан
    Комментировать
  • Как правильно вывести ошибки регистрации?

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


    Такова жизнь. Вью - это логика представления. Вот логику мы и добавляем. И это ещё цветочки, бывает куда больше.

    Упростить вьюшку можно перенеся необязательную логику в контроллер. Например явно задавая все используемые значения.

    foreach ($rules as $key => $throwaway) {
        $errors[$key] = $_SESSION['errors'][$key] ?? '';;
        $input[$key] = $_POST[$key] ?? $_SESSION['input'][$key] ?? '';
    }
    unset($_SESSION['errors'], $_SESSION['input']);


    И в шабалоне уже ничего не проверять

    <p>
        Имя: <input type="text" name="name" value="<?= h($input['name']) ?>">
        <?= h($errors['name']) ?>
    </p>


    И сделаю одно замечание. У вас при выводе в HTML экранируются не все значения. А должны - все.
    Чтобы не ломать пальцы, набирая htmlspecialchars каждый раз, сделать функцию-хелпер.
    Ответ написан
  • Как правильно перебрать вложенный массив и вывести результат?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Так и выводить. Во внутреннем фориче только категории, а не всё подряд.
    echo "<ul>\n";
    foreach ($goods as $name => $categories) {
        echo "<li>$name: ";
        foreach ($categories as $i =>$category) {
            echo $i ? ", " : "";
            echo $category;
        }
        echo "</li>\n";
    }
    echo "</ul>\n";
    Ответ написан
  • Как в php получить Последнее значение из таблицы mysql определенной даты даты?

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

    Если в БД хранится только дата, то чтобы получить все строки за определённую дату, код будет такой.
    $sql = "SELECT * FROM название таблицы WHERE  DATE = ?";
    $result = $conn->execute_query($sql, [$dateNew]);
    $usersArray = $result->fetch_all(MYSQLI_ASSOC);

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

    SELECT * FROM название таблицы WHERE  DATE BETWEEN ? AND ?

    и в него подставлять значения "$dateNew 00:00:00" и "$dateNew 23:23:59"

    Чтобы получить одну запись, надо добавить в запрос оператор LIMIT 1, а fetch_all(MYSQLI_ASSOC) поменять на fetch_assoc()
    Чтобы получить "последнюю" запись, надо добавить в запрос сортировку по тому полю, по которому считается последовательность добавления. И сделать сортировку в обратном порядке
    Ответ написан
    1 комментарий
  • Как тестировать запросы и ответы из базы данных через phpunit?

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

    Если говорить про "запросы к БД", то для таких тестов "массив с данными" использовать просто глупо. Это получится какой-то формальный тест: "проверяем, что метод возвращает массив из трех строк - и тут же возвращаем этот самый массив". В чем смысл? Если вы тестируете запрос к БД, то и надо тестировать запрос к БД. По-другому никак.

    Здесь я отвлекусь, и порассуждаю на тему того, что на самом деле тестирование - это гораздо более трудоёмкая задача, чем обычно считается. И как следствие, большая часть тестов - это такая вот туфта. Либо тест заранее возвращает нужные данные, либо тестирует один-два кейса. А вариантов неправильных входящих данных ведь может быть огромное количество. То есть по-хорошему на такой заведомо сложный (и принципиально неделимый!) метод нужно десятка два тестов.

    И сюда же использование для тестов БД другой системы. Например основная БД MySQL, а для тестов используется Sqlite. Тут сразу можно сказать, что это профанация. Различие даже в какой-то одной настройке БД может повлиять на результаты запроса (и теста как следствие) - а тут и вовсе используется совсем другая БД.

    С другой стороны, работу с БД скорее стоит тестировать не в юнит тестах, а скажем в интеграционных. Но не будем углубляться.


    Массив же "с данными, симулирующими ответ из базы данных" используется на следующему уровне, там где требуется "ответ из базы данных". Взьмём метод, который использует данные, полученные из БД. Например авторизация юзера. Этот метод должен не сам лезть в базу, а дёргать отдельный метод, вполне возможно, что совсем другого класса. И вот чтобы протестировать авторизацию, вы и мокаете метод для работы с БД, и из этого мока возвращаете тот самый массив без всякого обращения к бд.

    Здесь нелишне будет напомнить название доклада с одной из последних конференций по пхп. Дословно не помню, но что-то вроде "Делайте методы как можно короче. Ваши тесты скажут вам спасибо." Собственно, именно при тестировании очень быстро начинаешь понимать удобство атомарных (то есть выполняющих какую-то одну простую операцию) методов. А без тестов пройдёт довольно много времени, пока не понадобится этот длинный метод отрефакторить, и по итогам менять кучу кода, который его вызывает.

    Так что разбивайте ваши длинные методы на мелкие, и тогда вопрос, как их тестировать, в большинстве случаев отпадёт сам собой.
    Ответ написан
    1 комментарий
  • Почему после отправки формы обратной связи на почту приходят иероглифы?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    mail("info@grillgrad.ru", "order", "Имя: $name. Телефон: $phone" ,"Content-Type: text/plain; charset=UTF-8");

    Вместо вот этого всего
    Ответ написан
  • Почему код некорректно работает с кириллицей?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Неэффективность этого решения просто вопиёт к небу. Перебирать строку столько раз, сколько в ней букв - это же кощунство. Неужели нельзя за один проход посчитать символы, а за второй вывести их веса? И получить условные O(n*3) вместо O(n*3 + n^2).
    $len = mb_strlen($string);
    $counts = array_count_values(mb_str_split($string));
    foreach ($counts as $letter => $count) {
        echo "$letter: " . round($count / $len * 100, 1). "\n";
    }

    И заодно не придётся выковыривать из строки отдельные символы, которые мы уже выковыряли через mb_str_split.

    А для практики будет полезнее реализовать подсчет символов самостоятельно, без использования встроенной функции РНР
    Ответ написан
    Комментировать
  • Почему не работают cookie на хостинге?

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

    Главная проблема всех программистов-любителей в отсутствии логики. Вы делаете утверждения, которые вообще никак не следуют из приведённой информации. А зачастую и противоречат ей.

    Чтобы утверждать, что не работают именно куки, а не что-то ещё, в "функции" не должно быть никаких "$keys", "$a" и "$_SESSION". Это самая простейшая, базовая логика. Если мы проверяем какой-то функционал, то проверяем только его. Не внося никаких дополнительных сущностей.

    Учитывая, что сессионная кука ставится, это означает, что куки работают. А не работает "функция". И разбираться надо с ней. С помощью отладки.

    В принципе, неплохо проверить содержимое всех этих $keys", и "$_SESSION". Но в первую очередь надо сравнить НТТР заголовки, устанавливающие и ту и другую куку. При проблемах с куками надо смотреть не в Storage, а в Request. Там написано, какие и как именно куки ставятся, и какие куки браузер возвращает. И вот там-то и надо смотреть. А если самому непонятно, то в своем вопросе привести все заголовки Set-cookie из запроса. А не "функцию".
    Ответ написан
    1 комментарий
  • Есть ли в PHP готовый инструмент для получения элемента массива вложенность которого хранится в другом массиве?

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