Подготавливаемый запрос PHP

Фанат

oncle terrible
Команда форума
Если даже вывести сообщение внутри catch - то это не вызовет трассировки стека и его вывод.
А я и не писал что вызовет.
Выводить что-нибудь внутри catch - это просто глупо, без всякой связи с трассировкой :)
Пардон что четко не обозначил этот момент.
 

nllabs

Новичок
Ты же тот пример притянул за уши. Изначально условия были другие.

Кроме того ты сделал так, как сам советовал - и получил утечку данных.
Ты писал:
Правильно. Главное не выводить это внутри catch
А сам бросил исключение вместо вывода.
А бросая новое исключение с текстом сообщения об ошибке мы как раз избавляемся от стека вызовов
Не в этом случае :)

Вот так работает ?

А теперь попробуй сделать так, чтобы параметры были видны.
Хоть throw, хоть die.
 

Фанат

oncle terrible
Команда форума
А теперь попробуй сделать так, чтобы параметры были видны.
Мы говорим об одном и том же. просто вышла небольшая путаница.

В большинстве случаев ловить исключение (т.е. писать try..catch) вообще не нужно.
Вот как ты не ловишь вокруг запросов. И это правильно.

Однако, в случае с коннектом, при ошибке, если не ловить исключение, то параметры будут видны.

Поэтому я и порекомендовал тебе, в качестве исключения поймать исключение при коннекте и бросить заново только сообщение об ошибке, оставив трейс за бортом.
Что ты и сделал.

Я ж тебя не критиковал за те исправления, которые ты внес по моему совету :)
Я просто добавил объяснение - почему это важно.
 
Последнее редактирование:

nllabs

Новичок
Я это все понял, реально спасибо за это :)
Просто я ожидал демонстрацию вывода ошибки с паролем в случае моего кода. Раньше не видел ничего подобного, поэтому и продолжал диалог, думал, что чего-то не знаю или что-то упустил. Твой вариант, когда "все кишки полезут наружу" будет работать, если исключение выброшено и его некому поймать (выяснил экспериментальным путем). В реальных проектах такого не бывает. Поэтому я такого и не видел у себя.
Вот поэтому я и продолжал а не потому, что ты покритиковал или предложил внести исправления в мой код :)
 

Фанат

oncle terrible
Команда форума
если исключение выброшено и его некому поймать В реальных проектах такого не бывает.
Опять 25. Всё наоборот же
Если исключение выброшено и его некому поймать - это нормально. Так и должно быть.
Это нормально.
Это не то что "такого не бывает", а так должно быть в 99% случаев.
Так и надо писать. Не нужно пихать трай и кетч на каждый чих. Ни в реальном проекте, ни в виртуальном.

Случай соединения с БД - исключительный.
Поэтом с ним такая возня.

Если же говорить про "реальные" проекты, то в них обычно именно та каша которая была у тебя. Пишем код искренне полагая, что всегда будем единственным посетителем своего сайта. И в итоге на когда сайт выходит онлайн, ошибку без долгих разговоров вываливаем юзеру, а программист о ней без понятия.
Так что в случае с похапе говорить про "реальные проекты" вообще не стоит. Там внутри такой дым коромыслом, что волосы дыбом. И приводить в пример "реальные" проекты уж точно не стоит
 

nllabs

Новичок
Опять 25. Всё наоборот же
Если исключение выброшено и его некому поймать - это нормально. Так и должно быть.
Я неточно выразился, поэтому ты неправильно меня понял. Когда я говорил, что исключение некому поймать - то имел ввиду, что в клиентском коде нет try ... catch или обработчика исключений и исключение ловит обработчик по умолчанию, встроенный в PHP. Даже в самом простом проекте есть обработчик исключений (и не важно, это try ... catch, обернутое над всем кодом или callable, установленное с помощью set_exception_handler).
Другими словами - при возникновении исключения в трассировке стека будут показаны параметры только тогда, когда это исключение ловит обработчик, встроенный в PHP.
Во всех фреймворках есть обработчик исключений. Если кто-то пишет на чистом PHP, нужно быть большим разгильдяем, чтобы выбросить исключение и не обработать его, а полагаться на встроенный в PHP.
А только встроенный в PHP обработчик выводит конфиденциальные данные.
Если разработчик в своем обработчике исключений выводит конфиденциальные данные пользователю - то он ССЗБ.
Вот что я хотел сказать.
 

Фанат

oncle terrible
Команда форума
Ну в общем да.
Сойдемся на том, что в целом ловить не нужно, но в качестве защиты от дурака лучше поймать.
 

AnrDaemon

Продвинутый новичок
display_errors должна быть = Off на проде. Кто так не делает - ССЗБ.
 
Последнее редактирование:

Serebos

Новичок
Привет, Фанат и nllabs. Появилось время сегодня и занялся кодом. Ко всему предложенному, я решил сконцентрироваться на синтаксисе PDO (чтобы не было путаницы у меня с этими базовыми вещами). Что касается части PDO - по-моему все корректно записано, но вот в остальном не уверен.
Подскажите, где ошибки?

PHP:
$host = 'localhost';
$db   = 'kinomonster';
$user = 'root';
$pass = '';
$charset = 'utf8';

$options = [
    \PDO::ATTR_ERRMODE            => \PDO::ERRMODE_EXCEPTION,
    \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
];
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
try {
     $pdo = new \PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
    //die('PDO connection error: ' . $e->getMessage());
    throw new \Exception('PDO connection error: ' . $e->getMessage());
}

$stmt = $pdo->prepare("INSERT INTO movie VALUES(null, ?,?,?,?,?, Now(),?)";
$stmt->bind_param("ssssss", $name, $desc, $year, $rating, $poster,  $category_id);
 foreach ($xml as $movie_key => $movie) {
     $title = $movie->title_russian;
     $description = $movie->description;
     $year = $movie->year;

     foreach ($movie->poster->big->attributes() as $poster_key => $poster) {
         $post = $poster;
     }

     if($movie->imdb) {
         $rating = $movie->imdb->attributes()['rating'];
     } else {
         $rating = null;
     }

     $stmt->execute();

 }
PS: дописал шестую s в bind_param
 

Фанат

oncle terrible
Команда форума
к PDO приведенный код исполнения запроса не имеет ни малейшего отношения
не нужно менять коней на переправе
 

Фанат

oncle terrible
Команда форума
тогда уж убрать bind_param
и поменять
$stmt->execute([$name, $desc, $year, $rating, $poster, $category_id]);
 

AnrDaemon

Продвинутый новичок
$host = 'localhost'; $db = 'kinomonster'; $user = 'root'; $pass = ''; $charset = 'utf8';
Так лучше не делать. Задавайте DSN как один параметр конфигурации. Далеко не все БД имеют идентичные (да даже просто похожие!) структуры DSN.
$user = 'root'; $pass = '';
А вот так совершенно точно делать не стоит. Никогда не используйте суперпользователя для обычной работы с БД. (Я уже молчу про то, что при следующем обновлении муськи у вас это всё сломается, т.к. у рута не будет доступа к БД для работы, только для обслуживания.)

utf8mb4

А статью вы не читали. Идите перечитывайте. https://phpdelusions.net/pdo
 

Serebos

Новичок
Так лучше не делать. Задавайте DSN как один параметр конфигурации. Далеко не все БД имеют идентичные (да даже просто похожие!) структуры DSN.

А вот так совершенно точно делать не стоит. Никогда не используйте суперпользователя для обычной работы с БД. (Я уже молчу про то, что при следующем обновлении муськи у вас это всё сломается, т.к. у рута не будет доступа к БД для работы, только для обслуживания.)


utf8mb4


А статью вы не читали. Идите перечитывайте. https://phpdelusions.net/pdo
Материал я этот смотрел, но также я пытался объединить все вчерашние рекомендации...
 

Serebos

Новичок
сейчас попытаюсь применить эту конструкцию для своего случая

PHP:
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email AND status=:status');

$stmt->execute(['email' => $email, 'status' => $status]);
$user = $stmt->fetch();
К стати, спасибо всем, кто принимает участие в этом обсуждении!
 

Serebos

Новичок
к сожалению сырой пример без цикла... возвращаюсь обратно к рекомендации Фаната и вчерашнему коду...
 

Serebos

Новичок
Переписал, и вновь с ошибками.
Подскажите, пожалуйста, что здесь не так?
PHP:
$host = 'localhost';
$db   = 'kinomonster';
$user = 'root';
$pass = '';
$charset = 'utf8mb4';

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
    $mysqli = new mysqli($host, $user, $pass, $db);
    $mysqli->set_charset($charset);
} catch (\mysqli_sql_exception $e) {
     throw new \mysqli_sql_exception($e->getMessage(), $e->getCode());
}
unset($host, $db, $user, $pass, $charset); // we don't need them anymore

$stmt = $mysqli->prepare("INSERT INTO movie VALUES(null, ?,?,?,?,?, Now(),?)";
$stmt->bind_param("sssss", $name, $desc, $year, $rating, $poster,  $category_id);
foreach ($xml as $movie_key => $movie) {
    
     $title = $movie->title_russian;
     $description = $movie->description;
     $year = $movie->year;

     foreach ($movie->poster->big->attributes() as $poster_key => $poster) {
         $post = $poster;
     }

     if($movie->imdb) {
         $rating = $movie->imdb->attributes()['rating'];
     } else {
         $rating = null;
     }

     $stmt->execute();

 }
СПАСИБО.
 

AnrDaemon

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

Ваш код рабочий, просто надо выкинуть найух bind_param и поправить вызов execute().
 

Serebos

Новичок
При всём уважении, есть желание ответить - "а надо было читать".
В статье очень доходчиво излагаются не только приёмы использования, но и причины использования именно этих приёмов.

Ваш код рабочий, просто надо выкинуть найух bind_param и поправить вызов execute().
хорошо, спасибо! я переведу все дословно и еще раз взгляну на статью. Как раз и новые слова узнаю.
 
Сверху