За последние 24 часа нас посетили 17773 программиста и 1672 робота. Сейчас ищут 959 программистов ...

Форма авторизации, не могу проверить хешированный пароль в базе данных

Тема в разделе "PHP и базы данных", создана пользователем evkon, 22 ноя 2016.

  1. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    Нет, не уходи, вернись, расскажи, при чем тут масштабирование, с каких пор mysqli стало домашним решением, и почему оно должно выдавать непредвиденные глюки?

    PDO. Это расширение заметно отличается от mysql/mysqli, поскольку оно было разработано для поддержки систем управления реляционными базами данных (RDBMS) вообще, а не конкретно MySQL. По этой причине PDO далек от совершенства и работа с ним ожидает от пользователя большого количества предположений, что иногда выливается в странное поведение расширения. Что имеется в виду?

    PDO взаимодействует с SQL-парсером, который эмулирует подготовленные выражения, если RDBMS их не поддерживает. Проблема в том, что поведение этого уровня отличается от поведения RDBMS. В случае с MySQL, уровень эмуляции PDO активен по умолчанию, когда вы готовите запрос. Но он никогда не достигнет уровня подготовленного выражения. По сути, код PDO отпарсит и соберёт ваш запрос без взаимодействия с MySQL на эту тему. Это странное поведение. Поэтому отключите этот уровень эмуляции как можно скорее:

    Код (Text):
    1. /* Отключаем подготовленные выражения в PDO */
    2. $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0);
    3.  
    4. /* То же самое, обратите внимание что мы передаем действительно 0, а не 1 */
    5. $pdo->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0);
    Если уровень эмуляции включён, PDO позаботится о сборке запроса и отправит традиционный запрос к RDBMS. Но, ввиду множества недостатков, это может стать причиной странного поведения. Поскольку PDO ничего не знает о столбцах таблицы, его уровень эмуляции заключит в кавычки каждый параметр, даже числового типа. Это приводит к подобным ошибкам:


    Код (Text):
    1. $stmt = $pdo->prepare("SELECT user_id FROM users LIMIT :limit");
    2. $stmt->bindValue('limit', 10);
    3. $stmt->execute();
    4.  
    5. $result = $stmt->fetch();
    6. var_dump($result);
    7.  
    8. /*
    9. PHP Fatal error:  Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax;
    10. check the manual that corresponds to your MySQL server version for the right syntax to use near ''10''
    11. */
    Как видите, PDO заключил в кавычки параметр limit, хотя этого делать было не нужно. Попробуем отключить уровень эмуляции, оставив только уровень RDBMS (в данном случае MySQL):
    Код (Text):
    1.  
    2. $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); /* Disable prepared statement emulation layer */
    3. $stmt = $pdo->prepare("SELECT user_id FROM users LIMIT :limit"); /* A true prepare() will be sent to the RDBMS, it has to support it */
    4. $stmt->bindValue('limit', 10);
    5. $stmt->execute();
    6.  
    7. $result = $stmt->fetch();
    8. var_dump($result);
    9. /*
    10. array(4) {
    11.   ["user_id"]=>
    12.   string(7) "18"
    13.   [0]=>
    14.   string(7) "18"
    15. }
    16. */
    Теперь всё в порядке. Если же вам всё же нужен работающий уровень эмуляции, то нужно указать PDO, что не надо трогать числовые параметры:

    Код (Text):
    1. /* Tells the PDO prepared statement emulation layer that this column is of type integer (SQL type) */
    2. $stmt->bindValue('limit', 10, PDO::PARAM_INT);
    Но на этом ещё не всё. Несмотря на то, что мы явным образом отключили уровень эмуляции подготовленных выражений в PDO, он всё ещё немного активен. У него инициирован парсинг параметров. Есть два вида синтаксиса параметров: анонимные параметры, представленные как «?» в вашем запросе на заполнение, и именованные параметры, вроде «:myparam». Не каждая RDBMS поддерживает оба синтаксиса, причём MySQL не поддерживает именованные, только анонимные. Однако наш предыдущий запрос завершён без проблем. Всё дело в том, что анализатор запросов PDO всё ещё активен, даже с отключённым уровнем эмуляции. Он вмешался и заменил каждый именованный параметр на анонимный, потому что перед этим спросил RDBMS (в данном случае MySQL), поддерживает ли тот именованный синтаксис. Поскольку MySQL не поддерживает, то PDO и заменил все «:myparamname» на «?».

    Про проблемы масштабирования, которые решает PDO, пожалуйста, расскажи отдельно. А еще ткни носом, где было сказано, что-то в сторону фреймворков. Пожааааалуйста. А то развел демагогию.
     
    #26 Fell-x27, 24 ноя 2016
    Последнее редактирование: 24 ноя 2016
    denis01 нравится это.