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

Serebos

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

Функция здесь мешает использовать подготовленные выражения по назначению.
Не говоря о том что в ней по-хорошему должно быть всего две строчки
Поэтому лучше от нее отказаться
Код соединения с БД берем здесь

PHP:
$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) {
...
    $stmt->execute();
}
количество (и порядок) знаков вопроса, а также количество букв "s" должно соответсовать количеству переменных.
относительно s такое вот нашел:
The argument may be one of four types:
i - integer
d - double
s - string
b - BLOB
"
Это имеет отношение к этой части кода?
Вопрос также возникает: зачем автор курса запихнул INSERT в функцию, и это, для меня, как новичка, только усложнило задачу, согласно ваших слов о несовместимости некоторых вещей в пределах этого базового кода!?
 

Фанат

oncle terrible
Команда форума
Авторы курсов в массе своей неграмотные школьники, которые посмотрев какой-нибудь курс, тут же решают сделать свой.
Результат немного предсказуем.
 

Serebos

Новичок
ну я же его уже написал
Спасибо, Фанат. Мне показалось, что это часть кода, к которому мне еще предстоит проделать кучу трансформаций в том, с чего я начал! С контекста я понимаю, что мне нужно просто замену в код внести. Хорошо, как быть с экранированием спец символов?
 

Фанат

oncle terrible
Команда форума
все уже экранируется.
никакая "куча" транформаций не требуется.
Надо полключить файл, на который я дал ссылку
написать две строчки до цикла
и одну строчку вместо вызова функции - внутри цикла.
Это прямо такие сложные трансформации?
 

Serebos

Новичок
все уже экранируется.
никакая "куча" транформаций не требуется.
Надо полключить файл, на который я дал ссылку
написать две строчки до цикла
и одну строчку вместо вызова функции - внутри цикла.
Это прямо такие сложные трансформации?
алгоритм простой: состоит из единичных однозначных действий! Сложность возникает в понимании того, в чем же отличия сущности представления "моего" кода и вашего. Какую нагрузку несет function? Если это ошибка и нелепость, тогда вопросов нет!
 

Serebos

Новичок
алгоритм простой: состоит из единичных однозначных действий! Сложность возникает в понимании того, в чем же отличия сущности представления "моего" кода и вашего. Какую нагрузку несет function? Если это ошибка и нелепость, тогда вопросов нет!
еще раз спасибо, за перевод разговора от теоретической демагогии к реальному коду!
 

Фанат

oncle terrible
Команда форума
отличие простое - я понимаю что делаю, а автор курсов - нет
 

Serebos

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

nllabs

Новичок
На здоровье!

Да, Фанат прав. Приведу код для работы с БД, выдернутый из одного из моих проектов. Собирал из разных файлов, старался избежать ошибок.

PHP:
try {
    $db = new \PDO('mysql:host=localhost;dbname=test;charset=utf8', 'username', 'password',
        [
            \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
            \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
        ]);
} catch (\PDOException $e) {
    //die('PDO connection error: ' . $e->getMessage());
    throw new \Exception('PDO connection error: ' . $e->getMessage());
}



// select
$sth = $db->prepare('SELECT * FROM `feeds` WHERE `user` = :user ORDER BY `pubDate` DESC LIMIT 20');
$sth->execute([
    'user' => 'someuser',
]);

foreach ($sth->fetchAll() as $f) {
    //$rss->addItem($f['title'], $f['description'], $f['link'], $f['category'], new DateTime($f['pubDate']));
}



// insert
$sth = $db->prepare('INSERT INTO feeds(title, description, link, category, pubDate) VALUES(:title, :description, :link, :category, :pubDate)');
$sth->execute([
    'title'               => 'SomeTitle',
    'description'    => 'SomeDescription',
    'link'               => 'https://example.ru/link',
    'category'        => 'SomeCategory',
    'pubDate'        => 'SomeDate',
]);
P.S. заменил die на throw по совету Фаната.
 
Последнее редактирование:

Фанат

oncle terrible
Команда форума
Ну тут практически только одна ошибка,
die('PDO connection error: ' . $e->getMessage());
а в остальном нормально
 

Serebos

Новичок
всем огромное спасибо за помощь! Буду анализировать все написанное по этому вопросу. Надеюсь, вопрос исчерпал свое дальнейшее обсуждение!
 

Фанат

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

Фанат

oncle terrible
Команда форума
P.S. заменил die на throw по совету Фаната.
Чтобы пояснить
В слуае ошибки die выведет ее на экран.
Это нормально для этапа разработки но совершенно неприемлемо для боевого сайта
А throw породит стандартное исключение, которое будет обработано так же как все остальные ошибки.

Вообще, это получается масло масляное - поймать исключение чтобы тут же снова бросить. И в большинстве случаев это действительно бессмысленно. Имеется в виду писать try catch чтобы вывести ошибку.
Вот ты например совешенно правильно не пишешь try catch вокруг запросов. ПДО совершенно самостоятельно кинет исключение в случае ошибки, и ты будешь о ней проинформирован

Но в данном случае это оправдано поскольку исклбчение содержит стек вызовов в котором присутствует пароль к БД.
А бросая новое исключение с текстом сообщения об ошибке мы как раз избавляемся от стека вызовов
 
Последнее редактирование:

Serebos

Новичок
Я не думаю.
Наверняка при реализации возникнут ошибки, с которыми самостоятельно справиться не получится
По крайней мере, я знаю, куда мне обратиться с вопросами! Я сделаю еще раз - не получиться, я снова переделаю.... и так до самой цели! СПАСИБО.
 

nllabs

Новичок
Тот код - из парсера, который запускается на компьютере клиента, который является единственным пользователем скрипта.
Понятное дело, что на боевом сервере в случае ошибки, нельзя выводить какие-либо подробности. Достаточно вывести "Произошла ошибка" с кодом 500.

А как злоумышленник может достать пароль из стека вызовов ?
 

Фанат

oncle terrible
Команда форума
Тот код - из парсера, который запускается на компьютере клиента, который является единственным пользователем скрипта.
Это неважно, где код и что он делает. Это просто глупо писать разный код для разных условий.
Понятное дело, что на боевом сервере в случае ошибки, нельзя выводить какие-либо подробности. Достаточно вывести "Произошла ошибка" с кодом 500.
Правильно. Главное не выводить это внутри catch
А как злоумышленник может достать пароль из стека вызовов ?
Это сложнй вопрос.
Я доло время рекомендовал вообще не ловить исключение при коннекте.
Но меня убедили, что люди разные, и ситуации разные.
У кого-то на боевом сервере включен вывод ошибок на экран
У кого-то раделены права и пароль нельзя увидеть в коде, но можно - в логе ошибок. И так далее. лучше пересраховаться.
 

nllabs

Новичок
Правильно. Главное не выводить это внутри catch
Я тут некоторое время думал и проверял кое-что.
Для того, чтобы утек пароль через stack trace, нужно выполнить два условия:
1) Спровоцировать stack trace.
2) Настроить вывод stack trace так, чтобы видны были передаваемые параметры. Не знаю, возможно ли такое вообще.

Если даже вывести сообщение внутри catch - то это не вызовет трассировки стека и его вывод.
А если админ на боевом сервере настроил PHP так, чтобы были видны передаваемые параметры при выводе stack trace - то трассировка пишется в лог, а не выводится на экран.

Не вижу я сценария, как можно увидеть пароль через stack trace.

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

Спасибо за интересное обсуждение.
 
Последнее редактирование:

Фанат

oncle terrible
Команда форума
2) Настроить вывод stack trace так, чтобы видны были передаваемые параметры. Не знаю, возможно ли такое вообще.
Ню-ню.
А теперь попробуй настроить сервер так, чтобы параметры НЕ были видны.
Я с интересом понаблюдаю
 
Последнее редактирование:
Сверху