Задать вопрос
  • Что лучше использовать для связей в бд?

    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 для соединения, поскольку она в пыхе в какой-то момент начала использоваться по умолчанию, но лучше всё-таки задавать явно)
    Ответ написан
    Комментировать
  • В чем различие между phpMyAdmin, MySQL workbench и Microsoft SQL Server?

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

    • Microsoft SQL Server - это сервер. То есть программа, которая постоянно висит в памяти и принимает запросы от клиентов. Условно говоря - то, что и называется базой данных. Ну или точнее - СУБД, системой управления базами данных
    • MySQL workbench и phpMyAdmin - это клиенты, то есть программы, которые могут посылать запросы на сервер. Но на Microsoft SQL Server они посылать запросы не могут, потому что работают с другим сервером - MySQL.
    • при этом отличия между MySQL workbench и phpMyAdmin минимальные - обе являются графическими клиентами для СУБД MySQL, позволяя администрировать базу данных, редактировать таблицы в визуальном редакторе и выполнять SQL запросы. Только первое это десктопная программа, а второе - убогий веб-интерфейс, которому для работы нужен веб-сервер. И вместо которого всегда надо использовать нормальный клиент, например DataGrip, ну или хотя бы тот же Workbench.
    Ответ написан
    5 комментариев
  • Как удалить записи входа?

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

    elena@192.168.1.100 (ну или там elena@example.com)

    Загрузите сохранённое соединение и отредактируйте поле с хостом, либо убрав имя с собакой совсем (и тогда удалённый сервер будет каждый раз запрашивать логин), либо вписав другое имя (и тогда в дальнейшем будет подставляться уже оно).

    Ну или как вариант - нажмите Load и потом Delete - чтобы совсем удалить соединение и создать его заново.

    А тот accept, который вы нажали - он про другое. Это отпечаток сервера, который путти сохраняет чтобы отличать подделки. Но когда соединение происходит в первый раз, это окошко тоже показывается.
    Ответ написан
    3 комментария
  • Почему аутентификация возвращает форму авторизации?

    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
    Потомок старинного рода Ипатьевых-Колотитьевых
    Проблема явно высосана из пальца.
    Если нужны "самодостаточные архивы", то и запаковывать надо по файлам/папкам, а не вот это вот мракобесие. В общем случае проходим по папкам и архивируем каждую

    for i in */; do zip -r "${i%/}.zip" "$i"; done

    В данном конкретном случае 99% объема раздачи составляют файлы .db. Вот их и надо заархивировать, по отдельности. А всё остальное оставить как есть. И тогда этим "облаком" можно будет хоть как-то пользоваться, без нанайских национальных плясок, распаковывая по 10 чемоданов, чтобы достать один файл.
    find . -type f -name '*.db' -exec zip -m {}.zip {} \;

    В винде всё это тоже легко пишется.

    Но сначала надо оценить саму необходимость возиться с архивирванием, чтобы сэкономить 30 гигов из 180.
    Ответ написан
    4 комментария
  • Как передать имя таблицы как параметр?

    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
    Потомок старинного рода Ипатьевых-Колотитьевых
    Чтобы информация бессмысленно не повторялась, надо не дурацкий JSON городить, а просто не писать заголовок в теле статьи. А выводить его отдельно.
    preview, как правильно сказали выше, лучше писать отдельно, а не брать первый абзац статьи - тогда она будет выглядеть по-дурацки.

    Теги должны лежать в отдельной таблице. Читать про отношение многие ко многим.

    Писать url который slug в базу - занятие дурацкое. slug надо генерить на лету, а искать статью по идентификатору. и чтобы адрес был вида /666/pop-upal-s-kolokolni-i-slomal-nogu
    текст для красоты, id для идентификации
    Ответ написан
    Комментировать
  • Как правильно перебрать вложенный массив и вывести результат?

    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";
    Ответ написан
  • Как передать массив в Bash-скрипт?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Так и передать, а потом разбить на элементы
    Вариантов разбивки много, например из головы такой
    #!/bin/bash
    echo $1
    for lang in $(echo $2 | tr "," "\n")
    do
      echo $lang
    done


    ./script.sh "other parameter" ru,en,fr,de,kk,pe
    Ответ написан
    Комментировать
  • Как в 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");

    Вместо вот этого всего
    Ответ написан
  • Почему не всегда правильно происходит вставка данных в MySQL?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Если я правильно понял, ваш вопрос состоит в том, что при вводе в форму значений name1 name2 name3 вы иногда получаете в БД запись с name1, name2, name2 name1.
    Мы не знаем, почему так происходит.
    Кроме этого, мы не знаем, с чего вы взяли, что в форму вводили именно name1 name2 name3.

    Самым очевидным объяснением (исходя из доступной нам информации) является то, что в форму тупо ввели именно эти значения: в первое поле формы name1, во второе - name2, а в третье - name2 и name1. Это простое и логически непротиворечивое объяснение. Если оно вам не подходит, то вы должны добавить в свой вопрос дополнительную информацию, которая делает это объяснение невозможным. Например привести логи, которые показывают, что в форму было введено совсем не это. Или по крайней мере добавить в вопрос полный код формы и скрипта-обработчика, а не какой-то огрызок.

    Кроме этого, как вам правильно заметили в комментариях, надо учиться работать с БД правильно. И никогда не подставлять переменные прямо в запрос, а передавать их через символы подстановки. Таким образом вы сразу отсеете большое количество вероятных проблем. Читайте как правильно использовать mysqli
    Ответ написан
    Комментировать
  • Почему код некорректно работает с кириллицей?

    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.

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

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    массив в БД э то таблица.
    вложенный массив - это связанная таблица
    по таблице на пользователя никогда не создают
    делается одна таблица, в которой у записи есть id пользователя
    по этому id выбираются все строки, принадлежащие пользователю

    подробнее можно сказать только увидев предполагаемую структуру данных
    про приведенный в вопросе огрызок можно только сказать, что наверное это будет таблица messages с полями id, user_id, role, content
    Ответ написан
    Комментировать