Задать вопрос
Профиль пользователя заблокирован сроком с 10 апреля 2022 г. и навсегда по причине: систематические нарушения правил сервиса
Ответы пользователя по тегу PHP
  • PDO данные для подключения из стороннего файла?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Чтобы передать в функцию параметр, надо - сюрприз! - заранее сказать ей об этом.

    То есть если ты собираешься передать в функцию какое-то значение, которое потом будет использовано внутри, его надо описать при определении функции:
    function foo($bar) {
        echo $bar;
    }

    А если этого не сделать, то функция не будет знать, откуда у нее вдруг должна взяться переменная $bar.

    Соответственно, чтобы твой код заработал, надо сказать конструктору, что в нем будет переменная $config
    public function __construct(Config $config)
    И вызывать эту функцию в соответствии с данным определением. Это значит, что при определении функции указан 1 параметр, то при вызове надо писать тоже 1 параметр, а не 10.
    То есть вместо
    $db = new db($config->host, $config->user, $config->pass, $config->base, $config->charset);

    должно быть
    $db = new db($config);
    Ответ написан
    Комментировать
  • Php не видит и не подключает существующие файлы, почему?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    По какой-то загадочной причине пользователи похапе en masse не читают подробное объяснение ошибки, предоставленное интерпретатором РНР, предпочитая гадание на кофейной гуще.

    Казалось бы, объяснение прямо под носом: ищем файл в папке local
    /home/bitrix/www/local/modules/custom.module/lib/exception.php

    в то время как в реальности файлы приложения лежат в папке bitrix
    /home/bitrix/www/bitrix/modules/main/lib/loader.php

    То есть можно предположить банально неверную конфигурацию приложения.
    Ответ написан
  • Как отобразить комментарий под статьёй, под которой его написали, через PDO PHP?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    $stmt = $db->prepare('SELECT * FROM comments WHERE article_id = ?');
    $stmt->execute([$_GET['post_id']]);
    $comments = $stmt->fetchAll(PDO::FETCH_OBJ)


    И дальше уже выводишь из массива $comments в разметке. Самый простой пример: phpfaq.ru/tpl
    Ответ написан
  • Есть ли принципиальная разница между данными двумя подготовленными запросами запросами?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    В первом варианте меньше лишней писанины, а так никакой.

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

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Если я правильно понял функционал

    class AppException extends Exception {}
    
    class Test{
      public function create(array $data){
        if(empty($data['message'])){
          throw new AppException('Сообщение не может быть пустым');
        }
      }
    }
    
    $test = new Test();
    
    try{
      $test->create(array('message' => 'v'));
      // redirect
    }catch(AppException $e){
      echo $e->getMessage();
    }


    Идея в том, что при использовании исключений, никаких ручных проверок делать не надо. Если исключения не было - значит всё нормально. А если было, то код попросту не будет исполнен.
    Ответ написан
    1 комментарий
  • PDO делает несколько подключений к бд?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Нет, не должно быть.
    При дефолтных настройках такого не бывает.
    Возможно, это фишка некоего "openserver".
    Я думаю, переживать в любом случае не надо, поскольку на домашнем коммпике все равно сколько соединений - одно или два, а на нормальном хостинге у нормального админа никаких лишних соединений нет.
    Ответ написан
    Комментировать
  • Отследить ошибку Mysql PDO PHP?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    > То есть мне просто нужно узнать, запрос прошел или нет.

    Не нужно.
    Если есть какая-то определенная причина, по которой запрос может не пройти, то надо проверять конкретно эту причину.
    Во всех остальных случаях вместо "обычного return false" система должна порождать ошибку.
    Ответ написан
    Комментировать
  • MySQL. В чем разница функций?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Разница очень простая.

    Функция mysqli_real_scape_string не предназначена для защиты против возможных sql-инъекций. И применять ее в таком качестве - прямой путь заполучить инъекцию.
    В то время как одно из назначений функции mysqli_stmt_bind_param - это предотвращение sql-инъекций, поэтому применять её для этой цели можно и нужно.
    Ответ написан
    Комментировать
  • Как лучше всего сделать авторизацию на сайте?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    В сессии хранится минимально id юзера.
    В куке уникальное значение, uuid например (разумеется каждый раз генерируется заново) + он же кладется в базу для проверки.
    Ответ написан
    1 комментарий
  • Как получить и массив товаров и количество?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    PDO не пишет за тебя SQL. Он может выполнить только тот запрос, который ты сам смог написать. Поэтому фраза "PDO умеет как-то работать без LIMITа" не имеет смысла.

    Так что сами запросы оставляй как есть.
    Переделывать под ПДО имеет смысл всегда, если у тебя сейчас стандартный говнокод вида "у пети 2 яблока, а у васи 5": while mysql_fetch_array и вот это вот все.

    Если тебе будут впаривать SQL_CALC_FOUND_ROWS - не ведись, это заведомо медленнее, чем count(*) и все равно 2 запроса.
    Ответ написан
    Комментировать
  • PHP PDO Ошибка соединения с БД: SQLSTATE[HY000]: General error: could not call class constructor?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Следует отметить, что у этого класса очень много других проблем.

    1. Статическая функция для коннекта это картннный буратино, который никакой полезной функции не выполняет, а выполняет только вредную, каждый раз заново соединяясь с базой дынных. Надо хотя бы проверять, еслть ли уже соединение, и возвращать его.
    2. prepare с пустым execute - это картннный буратино, который никакой полезной функции не выполняет, а выполняет только вредную, пропуская все инъекции на свете. В prepare надо передавать запрос с плейсхолдерами, а execute массив с переменными для замены.
    3. echo "Ошибка соединения с БД: " - это это картннный буратино, который никакой полезной функции не выполняет, а выполняет только вредную. Пользователь из сообщения об ошибке ничего не поймет, а программист о ней ничего не узнает. Для вывода ошибок try должен быть один, глобальный, и выводить их в зависимости от окружения - на домашнем компике можно вываливать прямо на экран, а на боевом сервере только логировать.
    4. Пользователь - это не база данных. Поэтому наследовать классу БД он не должен. и уж тем более нет ни малейшего смысла наследовать класс со статическими методами. Объект для работы с БД надо передавать в конструктор и присваивать переменной класса. Либо если это тупой синглтон, то ничего вообще не передавать, а просто вызывать его методы где надо, хотя это неправильно.

    Подробне читать здесь (можно через гуглопереводчик)
    https://phpdelusions.net/pdo/common_mistakes
    https://phpdelusions.net/articles/error_reporting
    Ответ написан
    Комментировать
  • Как наладить корректную работу скрипта регистрации?

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

    Вот как на самом деле должен выглядеть твой код:

    if (empty($errors)) {
     
        $stmt = $db->prepare("SELECT count(*) FROM users WHERE email = ? OR login = ?");
        $stmt->execute([$email, $login]);
        $count = $stmt->fetchColumn();
     
        // Если найдены, значит логин/эмайл заняты, не регистрируенм, а выводим ошибку
        if ($count > 0) {
               exit("email или login занят!");    
        } else {
               $sql = "INSERT INTO users (login, email, password) VALUES (?,?,?)";
               $db->prepare($sql)->execute([$login, $email, $password]);
     
               echo '<div class="okreged">Вы успешно зарегистрированы! <a href = "/test/index.php">Перейти на главную</a></div>';
        }
     }
    Ответ написан
  • Почему in_array не работает в utf-8?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    > У меня оба файла исключительно в utf-8.

    Кодировка файла не имеет вообще никакого отношения к отправляемым данным.
    Имеет значение только кодировка, заданная в НТТР заголовках.

    > На сервере принудительно выставлено utf-8 через htaccess

    Никого никогда не интересует, что где выставлено. Важно не то, что "выставлено", а то, что фактически отдается в реальности.
    Смотреть надо не в htaccess а в консоль разработчика в браузере, в какой кодировке отдает форму сервер.
    В этой же самой кодировке данные будут отправлены на сервер обратно.

    > В чем может быть загвоздка?

    Никто не знает. Гадание на кофейной гуще не входит в профессиональные обязанности программиста.
    Если одна строка не равна другой - значит надо вывести обе эти строки, включая непечатные символы, и смотреть в чем разница. Для вывода можно использовать например функцию bin2hex.
    Ответ написан
  • Mssql_connect / PDO('sqlsrv'). Как сделать команду на UPDATE?

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

    $db = new PDO("sqlsrv:Server=".self::$host.";Database=".self::$database, self::$user, self::$password);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $db->prepare('UPDATE Pmark SET Finish=? WHERE ID=?')->execute([$date, $id]);
    $arResult['success'] = true;
    Ответ написан
    Комментировать
  • Что я делаю не так при добавлении записи через PDO?

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

    Наверное, убрать код, который выводит?
    Просто убери то что у тебя называется "исключения": try и catch
    Ответ написан
    Комментировать
  • INSERT PDO как?

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

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

    Если запись в БД не добавляется, то значит произошла ошибка.
    Если произошла ошибка, то надо прочесть ее текст и затем исправить.
    Чтобы увидеть текст ошибки, надо либо смотреть лог веб-сервера, либо включить вывод ошибок на экран и повторить вставку.
    чтобы понять, в чем проблема, надо прочесть и понять то, что говорится в сообщении об ошибке. Так же можно использовать переводчик гугля и сам гугль, если все равно непонятно, в чем заключается ошибка или как ее исправить.

    Разные варианты настроек вывода ошибок можно посмотреть здесь.
    Ответ написан
    1 комментарий
  • Что почитать по составлению безопасных sql запросов?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Базовые принципы на то и базовые, что не меняются со временем. Я бы только переформулировал немного по-другому,
    • Данные подставляем в запрос только через плейсхолдеры
    • Все остальное - только после проверки через белые списки

    И еще бы добавил что эти правила должны соблюдаться безусловно, в 100% процентов случаев, без рассуждений типа "вот эти данные у нас безопасны, их можно не защищать".

    Если же говорить о тенденциях, то с чистым SQL сейчас никто практически не работает. 95% запросов выполняются через ORM. Т.е. вместо
    $stmt = $pdo->prepare("SELECT * FROM user where id = ?");
    $stmt->execute([$id]);
    $user = $stmt->fetch();

    пишем просто
    $user = User::find($id);
    при этом защита уже вшита у ORM внутри и думать о ней не надо

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

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    public static function getComments(){
        return DB::getConnection()->query('SELECT * FROM comments')->fetchAll(PDO::FETCH_UNIQUE);
    }
    Ответ написан
    Комментировать
  • Как использовать bind_param в цикле?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Самым простым решением будет переместить заполнение $aStmt в конструктор.

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

    Плюс сам код можно значительно упростить.
    foreach($this->aStmt AS $name => $param){
        $this->aStmt[$name]['stmt'] = $this->oDB->prepare($param['query']);
        $this->aStmt[$name]['stmt']->bind_param($param['paramType']), ...$param['params']);
    }
    Ответ написан
    Комментировать
  • Почему не работает запрос на php + PDO?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Накосячено здесь везде. В каждой строчке. Но самая ерунда написана в комментариях.

    > я всегда делаю, чтобы сначала работало, а потом делаю защиту и "секьюрность".

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

    Файл соединения:
    <?php 
    $serverName = "localhost";
    $userName = "root";
    $password = "";
    $dataBase = "matrix";
    $pdo = new PDO ("mysql:host=$serverName; dbname=$dataBase", $userName, $password);
    $pdo->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );


    "Движок" берем отсюда, https://phpdelusions.net/pdo_examples/password_hash

    $stmt = $pdo->prepare("SELECT login, password, otdel FROM `user_s` WHERE login=?");
    $stmt->execute([$_POST['login']]);
    $user = $stmt->fetch();
    
    if ($user && password_verify($_POST['password'], $user['password']))
    {
        echo "valid!";
    } else {
        echo "invalid";
    }


    Не забыв предварительно хэшировать все пароли перед записью в БД через password_hash.

    А ответ на вопрос, почему у тебя не работает сейчас, можешь прочесть в документации по exec(). Там написано.
    Ответ написан
    1 комментарий