Задать вопрос
Профиль пользователя заблокирован сроком с 10 апреля 2022 г. и навсегда по причине: систематические нарушения правил сервиса
  • Переход на 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 комментария
  • Как в PHP вывести маленькое дробное число без изменения количества знаков после запятой и перевода в формат "e"?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    > Есть какой-то еще способ заставить PHP просто вывести дробное число без изменения его внешнего вида?

    Нет

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

    Если важен "исходный внешний вид", то следует работать с числами, как со строками, и тогда они будут всегда выводиться, как есть.
    Ответ написан
    Комментировать
  • Хранить в БД или PHP?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Разумеется, только в БД.

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

    Или, если сформулировать короче, то данные должны лежать в базе, а в РНР файлах - только код.
    Ответ написан
    5 комментариев
  • Могут ли украсть сессию php?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Как всегда, в теле вопроса написано совсем не то, что в заголовке.

    Отвечаем на оба вопроса

    Могут ли украсть сессию php?
    при нормальных настройках сайта (httponly cookies, SSL) - практически нереально. Только трояном с компа. Но если есть доступ к компу, то с сессиями уже заморачиваться как-то мелко.
    Хотя я не очень уверен насчет расширений браузера/тулбаров. Думаю, что они доступ к кукам имеют свободный.

    Может ли другой человек узнав ID сессии и приписав его в свой php скрипт получить доступ к данным сессии моего сайта?
    Разумеется, может.

    Только не описанным способом, конечно. Идентификация происходит через cookies. Соответственно, узнав ID, надо просто отправить нужный session_id со своего сервера или браузера.
    Ответ написан
    1 комментарий
  • Как узнать сколько было извлечено записей из базы данных.?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Это абсолютно бессмысленная операция, которая никогда не бывает нужна.

    Если вдруг показалось, что нужно получить количество строк, которые вернул запрос, то значит проблемы с логикой. Это как раз тот случай, который мы наблюдаем сейчас. Откуда тут взялись 2 запроса к базе данных? Они существуют только в вашем воображении. В вашем коде используется только один запрос. И никакое количество строк тут не нужно, ваш код прекрасно работает без него. Разве что убрать из него SQL инъекцию и бессмысленные телодвижения

    $stmt = $_connect_->prepare("SELECT * FROM users WHERE login=?");
    $stmt->execute([$_SESSION['login']]);
    $user = $stmt->fetch();
    
    if($user){
        echo 'есть записи';
        echo 'Имя пользователя'.$user['login'];
    }else
        echo 'нет записей';
    }
    Ответ написан
    Комментировать