Профиль пользователя заблокирован сроком с 10 апреля 2022 г. и навсегда по причине: систематические нарушения правил сервиса
  • Как преобразовать в другой тип значения массива в цикле?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    База данных не настолько тупая, как многие думают.
    Данные в нужном формате можно получить сразу из запроса. Для даты можно использовать date_format(date, '%d.%m%Y') в запросе.
    А вот вот цену я бы настоятельно не рекомендовал преобразовывать в какой-бы то ни было другой формат. Могут быть неприятности.
    Ответ написан
    Комментировать
  • Как реализовать постраничную навигацию с LEFT JOIN?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Постраничная навигация с LEFT JOIN ничем не отличается от навигации с любым другим запросом.

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

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Я вам писал уже, как правильно соединяться с mysqli. Если бы не читаете ответы, которые вам пишут, то не надо засорять сайт своими вопросами.

    Я попробую ещё раз: как правильно соединяться с mysqli

    После того, как вы измените код на правильный, база данных сама сообщит вам, что не так в вашем запросе. Останется только прочитать и исправить.

    Для справки. close никакого отношения к проблеме не имеет. Можно использовать, можно не использовать. Фактически, в большинстве случаев close писать нет смысла.
    И засорять код многочисленными $stmt, $stmt1, $stmt100500 тоже не имеет смысла. Если все данные из $stmt получены, то правильно будет повторно использовать переменную с таким же именем для следующего запроса.
    Ответ написан
    Комментировать
  • Почему PDO::execute не заменяет псевдопеременные в запросе?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Потому что не выключен режим эмуляции.

    Только фактически всё наоборот: при включенном режиме эмуляции PDO как раз таки подставляет данные в запрос, и в LIMIT будет ошибка. А при выключенном данные в запрос не подставляются, и следовательно никакой ошибки не будет.

    Судя по тому, что в вопросе нет сообщения об ошибке, при соединении вообще не указывается ни один нужный параметр. Как правильно соединяться с PDO
    При указанных настройках запрос с лимитом будет работать.

    Идея с функцией query() отличная, только она не должна возвращать fetchAll(). Это все равно что добровольно отказаться от половины функциональности PDO!
    Функция должна возвращать стейтмент. Тогда ее можно будет использовать для любых запросов ,и получать данные в любых из дюжины форматов, поддерживаемых PDO, а не только в виде тупого массива.

    Соответственно, функция должна делать return $query; а код будет таким
    $sql = 'SELECT * FROM vocabulary ORDER BY word_date DESC LIMIT :startLimit , :countLimit';
    $params = ['startLimit' => $_POST['slimit'], 'countLimit' => $_POST['limit']];
    $lines = $db->query($sql, $params)->fetchAll();
    var_dump($lines);
    Ответ написан
    Комментировать
  • Переход на mysqli, как по новым стандартам?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    По новым стандартам самое главное - это использовать подготовленные выражения для выполнения запросов. В смысле не подставлять переменные напрямую в запрос, а передавать их отдельно.

    Для mysqli

    Как соединяться
    Как проверить пароль

    Для PDO

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

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    К сожалению, примеры в мануале были написаны в прошлом веке, не очень сведущими людьми, и с тех пор не менялись. К примеру, оператор if в приведенном коде бессмысленный и вредный.

    Ну и плюс к тому надо же еще немножечко самостоятельно рассуждать. Оператор while нужен только если надо вывести много строк. А если нужна одна, то и оператор while не нужен.

    В итоге весь код с учетом исполнения запроса код можно сократить до трех строк (запихивать всё в одну нет смысла - потом будет неудобно читать)
    $query = "SELECT Name, CountryCode FROM City ORDER by ID DESC LIMIT 50,1";
    $result = $mysqli->query($query);
    $row = $result->fetch_assoc();

    Освоившись с объектным синтаксисом, в дальнейшем последние две строчки можно объединять в одну
    $row = $mysqli->query($query)->fetch_assoc();
    Также хочу отметить, что код для соединения с базой данных в примерах также дается ужасный. Более правильный вариант будет такой
    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
    $mysqli = new mysqli("localhost", "my_user", "my_password", "world");
    $mysqli->set_charset("utf8mb4");

    А еще лучше соединяться, как написано здесь, чтобы с одной стороны иметь нормальные сообщения об ошибках, а с другой не вывалить случайно при ошибке все параметры соединения к БД в открытый доступ.
    Ответ написан
    2 комментария
  • Какой смысл так упрощать запросы?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Забавно, что никто так и не понял вопроса.

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

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

    И в итоге этот код скорее всего работает не так, как хотел автор. Если переписать на обычные условия, то получится такой код
    if (isset($product_info['meta_h1'])) {
        if ($product_info['meta_h1']) {
            $out = $product_info['meta_h1'];
        } else {
            $out = $product_info['name'];
        }
    } else {
        $out = '';
    }

    Логики я здесь не вижу.
    Более осмысленным вариантом для меня было бы, "если $product_info['meta_h1'] не существует или пуста, то выводить $product_info['name']". То есть, все свелось бы к простому единственному тернарному оператору
    !empty($product_info['meta_h1']) ? $product_info['meta_h1'] : $product_info['name'];

    На вопрос же "зачем" ответ простой: от лени и головотяпства. Есть такой период в жизни каждого пользователя похапе, когда кажется, что чем короче ты напишешь, тем круче выглядит твой код... а потом, когда начинаешь читать свое произведение, из глаз начинает идти кровь.
    Ответ написан
    1 комментарий
  • PASSWORD_hash как проверить, верно ли условие?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Это очень плохой код. Только не в части password_verify, а в части выполнения SQL запроса.
    Потому что здесь можно залогиниться под кем угодно, без всякого пароля. Через SQL инъекцию.

    Ну и плюс этот код будет выдавать ошибку, если пользователь с таким логином не найден.

    Вот как правильно проверять пароль с помощью mysqli:
    $stmt = $db->prepare("SELECT * FROM user WHERE login = ?");
    $stmt->bind_param("s", $login);
    $stmt->execute();
    $user = $stmt->get_result()->fetch_assoc();
    
    if ($user && password_verify($password, $user['password']))
    {
        echo "valid!";
    } else {
        echo "invalid";
    }

    Здесь мы, во-первых, используем подготовленные выражения, а во-вторых, сначала проверяем, найден ли юзер с таким логином
    Ответ написан
    Комментировать
  • Что изменить в коде, чтобы перестали спамить боты через форму обратной связи?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Поставить каптчу.

    Это единственный вариант который будет работать по принципу "я тут что-то нашел, и воткнул себе на сайт но понятия не имею что это такое и как работает".
    Ответ написан
    1 комментарий
  • Как положить нужные ключи в массив?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Открываем тайные знания очередной жертве видеокурсов

    В SQL запросе можно запросить не все поля через SELECT * FROM, а только те, которые нужны.
    И тогда не придется извращаться, выбрасывая ненужное
    $sql = "SELECT two, three, four FROM table";
    $result = $mysqli->query($sql);
    $array2 = $result->fetch_row();

    Хотя, конечно, судя по именам переменных, там остальной код - такой же ад, и там всё надо менять
    Ответ написан
    4 комментария
  • Как построить таблицу из двумерного массива, где каждый вложенный массив это столбец?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Поскольку в современном РНР никто не пишет такую кашу из HTML и PHP, как в ответе 0xD34F, то сначала следует преобразовать массив к горизонтальному. Это можно сделать как угодно, я предпочитаю теплые ламповые циклы.
    $max = 0;
    foreach ($array as $title => $item) {
        $max = max($max, count($item));
    }
    $rows = [];
    for($i = 0; $i < $max; $i++) {
        foreach ($array as $item) {
            $rows[$i][] = $item[$i] ?? '';
        }
    };
    $titles = array_keys($array);

    И затем уже выводить $titles и $rows обычным циклом, используя любимый шаблонизатор.
    Ответ написан
    6 комментариев
  • PHP. Как изменить значение массива через форму на сайте?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Поскольку для пишущих ответы на Тостере это сложная задача, приведу полный код
    include "array.php";
    $array['определенное значение'] = значение из формы;
    $out = var_export($array, true);
    file_put_contents("array.php","<?php\n\$array = $out;");
    Ответ написан
    1 комментарий
  • Как добавить в конец записи MySQL?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Это неправильно.
    Надо завести отдельную таблицу user_read, в которой будет всего два поля - id пользователя и id новости.
    Соответственно, добавление "в конец" будет обычной операцией вставки.
    Ответ написан
    3 комментария
  • Зачем нужна IDE для PHP?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    На самом деле объяснение очень простое.

    Если под РНР понимать колупание в стиле прошлого века - отдельные файлы с include 'database_connect.php' и while($row = mysqli_fetch_array($result)), то IDE не нужна - достаточно любого редактора, позволяющего делать операцию копировать/вставить. Подойдет хоть Блокнот Виндоус.

    В современном же мире разработчик работает над проектом, зачастую основанном на фреймворке, лежащим в системе контроля версий и состоящим из множества файлов, большая часть которых содержит определения классов. В этом случае IDE становится необходимым инструментом, ускоряющим разработку в разы.
    Ответ написан
    Комментировать
  • Как узнать что записи в БД кончились?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    жаль что нельзя добавить else после while.


    Специально для жертв видеокурсов: РНР за 20 лет приобрел некоторые новые функции. Если учить пхп не только по видеокурсам, но открыть однажды для себя мануал, то там обнаружится такая функция, как mysqli_fetch_all(). И с ее помощью конструкция while($row = mysql_fetch_array($data)) из прошлого века, (к которой доблестные видеоблогеры осилили дописать буквочку i и решили что их код стал нереально современным) превратится в тыкву.

    Если хватит способностей проверить в JS на пустоту массив, то вместо "while" пишем просто
    echo json_encode(mysqli_fetch_all($data));
    если хочется обязательно null, то
    $rows = mysqli_fetch_all($data) ?: null;
    echo json_encode($rows);
    Ответ написан
    1 комментарий
  • Как вывести количество строк из БД?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Правильный ответ:

    $sql = "SELECT count(*) FROM `users` WHERE `login` = ? OR `email` = ?";
    $stmt = $pdo->prepare($sql);
    $stmt->execute([$login,$email]);
    $user = $stmt->fetchColumn();


    Что мы здесь имеем?
    • Во-первых, запрос, защищенный от кривых ручек пользователя похапе, и, как следствие, от неправильного синтаксиса
    • Во-вторых, запрос, защищенный от SQL инъекций.
    Ответ написан
  • Оптимизировать запрос MySQL. Как узнать сколько всего рядов когда использую limit?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Сам по себе еще один запрос - это не лишняя работа, а ерунда на постном масле.
    Вопрос не в том, сколько запросов выполняется, а что именно они делают.

    И в данном случае эти два запроса делают ужас, летящий на крыльях ночи. Я сейчас расскажу, что делает ваш код.
    Сначала этот код просит базу данных отправить в РНР все найденные запросом строки. Все. Без лимита. Чтобы РНР мог посчитать их и потом выбросить.
    После этого код еще раз просит базу отправить, только не все строки, а только часть. И теперь РНР уже не выбрасывает полученные строки, а честно выводит.
    Понятное дело, что смысла в этих замысловатых телодвижениях - ноль целых, ноль десятых.

    Как правильно получить общее количество найденных строк? Надо попросить базу посчитать их

    Ну и разумеется, использование prepare вместе с доморощенной и небезопасной функцией "clearStr" - это вообще за гранью добра и зла. Это примерно как хранить миллион в сейфе, но не запирать его на ключ, а подпирать дощечкой.

    $GLOBALS["mysqlcon"] - это отдельный ужас, но на фоне всего остального меркнет.

    Правильный код будет таким
    $sql = "SELECT count(*) FROM post WHERE MATCH (tags) AGAINST (? IN BOOLEAN MODE)";
    $STH = $GLOBALS["mysqlcon"]->prepare($sql);
    $STH->execute([$_GET['search']]);
    $totalPages=ceil($STH->fetchColumn()/$numPosts); //Узнаем сколько всего страниц существует
    
    $sql = "SELECT * FROM post WHERE MATCH (tags) AGAINST (? IN BOOLEAN MODE) LIMIT ?,?";
    $STH = $GLOBALS["mysqlcon"]->prepare($sql);
    $STH->execute([$_GET['search'],$start, $numPosts]);


    Поскольку все советуют синглтон, вот готовый пример: https://phpdelusions.net/pdo/pdo_wrapper#singleton
    С ним, кроме прочего, код будет короче

    $sql = "SELECT count(*) FROM post WHERE MATCH (tags) AGAINST (? IN BOOLEAN MODE)";
    $numRows = DB::run($sql, [$_GET['search']])->fetchColumn();
    $totalPages=ceil($numRows/$numPosts); //Узнаем сколько всего страниц существует
    
    $sql = "SELECT * FROM post WHERE MATCH (tags) AGAINST (? IN BOOLEAN MODE) LIMIT ?,?";
    $STH = DB::run($sql, [$_GET['search'],$start, $numPosts]);
    Ответ написан
    1 комментарий
  • Как правильно пользоваться подготовленными запросами в случает с ON DUPLICATE KEY UPDATE?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    В данном частном случае можно сделать так:
    ON DUPLICATE KEY UPDATE `z_str` = values(z_str), `z_id` = values(z_id), `name` = values(name), `url` = values(url)"


    А в общем случае - да, либо дублировать переменные, либо отключать режим эмуляции
    Ответ написан
  • PHP PDO предопределенная константа PARAM_STR?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    PDO никак не преобразовывает данные. Ни большие, ни маленькие. И предопределенная константа PARAM_STR тут тоже не при чем.
    Ответ написан
    2 комментария
  • PHP PDO почему идет преобразование текста в binary?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Никакого "преобразования" в "binary" при выполнении запроса не происходит.

    В сообщениях об ошибке / логах нестандартные символы кодируются для большей совместимости. К выполненному запросу этот формат не имеет отношения.
    Ответ написан
    3 комментария