←  Вопросы по урокам сайта

Форум WebForMyself - Основы Самостоятельного Сайтостроения

»

курс по youtube "Создание фреймворка с...

 фотография tarabukinivan 08 Сен 2018

Добрый вечер Андрей!
На уроке вы создали метод execute:
public function execute($sql, $params = []){
  self::$countSql++;
  self::$queries[] = $sql;
  $stmt = $this->pdo->prepare($sql);
  return $stmt->execute($params);
}
На уроке вы говорите она должна возвратить true либо false в зависимости от выполнения запроса.
Используя его, я сделал вот такой метод для выполнения обновления таблицы:
public function findMySql($sql, $params = []){
  return $this->pdo->execute($sql, $params);
}

И с помощью него делаю вот такой запрос:
$this->findMySql("UPDATE users SET a_status='4' WHERE activation= ? ",[$acode]);

на таблице, поле `a_status` имеет тип ENUM ('0','1'). Так как поле не может принять значение '4', то на базу записывается пустота и метод возвращает true. Но по идее должна была возвратится false так, как '4' не записался. Как можно устранить данную проблему?

Как делают обновления таблицы через pdo? И проверяют выполнен ли запрос?
Ответить

 фотография matroskin8 09 Сен 2018

Здравствуйте.

Просмотр сообщенияtarabukinivan (08 Сентябрь 2018 - 15:09) писал:

на таблице, поле `a_status` имеет тип ENUM ('0','1'). Так как поле не может принять значение '4', то на базу записывается пустота и метод возвращает true. Но по идее должна была возвратится false так, как '4' не записался.
Почему должно вернуться false? Исходя из документации, false будет возвращено в случае ошибки. В Вашем случае, как я понимаю, речь идет не об ошибке, а о незапланированном поведении.

Просмотр сообщенияtarabukinivan (08 Сентябрь 2018 - 15:09) писал:

Как можно устранить данную проблему?
Используя механизм валидации. Задача SQL - это работа с данными в плане записи и получения, ну а Ваша задача - подготовить эти самые данные. Например, если Вы хотите сохранить email в соответствующее поле таблицы, то Вы ведь не требуете от sql-запроса валидации строки по формату email... нет, это мы делаем сами на стороне PHP. Также и здесь, нужно просто провалидировать это значение и привести его либо к "0" / "1", либо же вернуть ошибку и не трогать БД вообще в таком случае.

Просмотр сообщенияtarabukinivan (08 Сентябрь 2018 - 15:09) писал:

Как делают обновления таблицы через pdo? И проверяют выполнен ли запрос?
Так и делают. Только дополнительно используют метод rowCount(), который вернет количество строк, затронутых последним модифицирующим запросом (INSERT, UPDATE или DELETE). Вот только опять-таки, в Вашем случае, скорее всего, будет возвращено значение 1, поскольку запрос ведь изменил одну строку. Поэтому, повторюсь, данные в таком случае нужно валидировать.
Ответить

 фотография tarabukinivan 09 Сен 2018

Спасибо Андрей!
Ну это получается работа в php, валидируем и ставим только правильные данные, а можно ли с 100% уверенностью сказать, что данные успешно занесены?
1. Допустим во время изменения данных после выполнения update оборвался связь, то вылезет ли какая-либо ошибка?
2. Функция execute просто передает данные в mysql и возвращает true, либо ждёт ответа от mysql и только потом, если есть изменения возвращает true?
Ответить

 фотография tarabukinivan 09 Сен 2018

У меня есть такой метод
public function activate($data){
  $userdata = $this->findOne('users', "`activation` = ? AND a_status=0",[$data]);

  if($userdata){  
   $acode = $userdata['activation'];
   $res = $this->findMySql("UPDATE users SET a_status='1' WHERE activation= ? ",[$acode]);
	echo "res= $res";
   return true;
  }else{
   return false;
  }
}
Но для проверки отработки функции execute сделал так
public function activate($data){
  $userdata = $this->findOne('users', "`activation` = ?",[$data]);

  if($userdata){  
   $acode = $userdata['activation'];
   $res = $this->findMySql("UPDATE users SET a_status='0' WHERE activation= ? ",[$acode]);
	echo "res= $res";
   return true;
  }else{
   return false;
  }
}

И даже, если ничего в таблице не меняется, т.е. на a_status='0' заменяю на a_status='0', то в $res все равно получаю 1
Сообщение отредактировал tarabukinivan: 09 Сентябрь 2018 - 14:57
Ответить

 фотография matroskin8 10 Сен 2018

Просмотр сообщенияtarabukinivan (09 Сентябрь 2018 - 08:54) писал:

а можно ли с 100% уверенностью сказать, что данные успешно занесены?
Ну конечно же можно. Выше я писал о методе rowCount, который вернет Вам количество строк, измененных последним запросом. Если Вы планировали изменить запросом, к примеру, 2 строки и данный метод вернул 2 строки, тогда все прошло успешно.

Просмотр сообщенияtarabukinivan (09 Сентябрь 2018 - 08:54) писал:

1. Допустим во время изменения данных после выполнения update оборвался связь, то вылезет ли какая-либо ошибка?
В этом случае метод execute должен вернуть false, как я понимаю.

Просмотр сообщенияtarabukinivan (09 Сентябрь 2018 - 08:54) писал:

2. Функция execute просто передает данные в mysql и возвращает true, либо ждёт ответа от mysql и только потом, если есть изменения возвращает true?
Скорее, второе. В документации о таких тонкостях нет ни слова, но если там сказано, что true возвращается в случае успешного завершения запроса, тогда логично предположить, что запрос выполнился - ведь он завершен.

Просмотр сообщенияtarabukinivan (09 Сентябрь 2018 - 14:55) писал:

У меня есть такой метод
Но для проверки отработки функции execute сделал так
И даже, если ничего в таблице не меняется, т.е. на a_status='0' заменяю на a_status='0', то в $res все равно получаю 1
Судя по названию, этот метод мало подходит для операций UPDATE, скорее - для операций выборки все же. В любом случае, у Вас там вызов метода execute, выполняющего запрос. Выше я давал ссылку на документацию, где написано, что метод execute возвращает true, если запрос выполнился, и false, если произошла ошибка. Ваш запрос выполнился без ошибок, соответственно, было возвращено true, которое при выводе интерпретатор преобразовал к единице:
echo true; // на экране будет 1
Если нужно проверить, изменил ли что-то последний запрос в БД, тогда используйте метод rowCount, который я Вам и советовал выше. Для этого можно написать метод специально под операцию UPDATE - как-то так примерно:
public function update($sql, $params = []){
    $stmt = $this->pdo->prepare($sql);
    $stmt->execute($params);
    return $stmt->rowCount(); // будет возвращено кол-во измененных запросом рядов
}
Ответить

 фотография tarabukinivan 11 Сен 2018

Спасибо Андрей!
Ответить

 фотография tarabukinivan 11 Сен 2018

Еще вопрос по поводу подготовленных запросов типа:
INSERT INTO {$this->table} (login, name, email, activation, pass) VALUES(?,?,?,?,?)
Нужно ли обрабатывать входные данные login, name, email, activation, pass функциями mysql_real_escape_string, trim, htmlspecialchars, strip_tags или чем-то еще? Или PDO сам их обрабатывает?
Ответить

 фотография matroskin8 11 Сен 2018

Пожалуйста ;)

Просмотр сообщенияtarabukinivan (11 Сентябрь 2018 - 01:05) писал:

Еще вопрос по поводу подготовленных запросов типа:
Нужно ли обрабатывать входные данные login, name, email, activation, pass функциями mysql_real_escape_string, trim, htmlspecialchars, strip_tags или чем-то еще? Или PDO сам их обрабатывает?
Что касается функций для защиты от sql-инъекций типа функции mysql_real_escape_string - то не нужно. Подготовленные запросы будут автоматически обработаны PDO и защищены от sql-инъекций. Из документации:

Цитата

Параметры подготовленного запроса не требуется экранировать кавычками; драйвер это делает автоматически. Если в приложении используются исключительно подготовленные запросы, разработчик может быть уверен, что никаких SQL-инъекций случиться не может

Что же касается прочих функций (trim, htmlspecialchars, strip_tags), то их назначение не защита БД, т.е. БД от sql-инъекций эти функции не защитят. Их назначение несколько в ином и использовать их нужно, если в этом есть необходимость. Например, функция trim обрезает пробельные символы справа и слева строки. Функция может быть полезна при валидации. Например, если поле login не должно быть пустым и есть вероятность, что пользователь туда введет просто несколько пробелов. В этом случае trim обрежет все пробельные символы и строка не пройдет валидацию.
Функция htmlspecialchars преобразует специальные символы в HTML-сущности. Эта функция может быть полезна в том случае, если Вы хотите показать код на странице, но при этом данный код не должен выполняться. Также функция поможет защититься от XSS-атак и использовать ее рекомендуется при выводе пользовательских данных в браузер.
Ну а функция strip_tags попросту удаляет все теги из строки. Как-то так :)
Ответить

 фотография tarabukinivan 12 Сен 2018

Просмотр сообщенияmatroskin8 (11 Сентябрь 2018 - 07:10) писал:

Пожалуйста ;)


Что касается функций для защиты от sql-инъекций типа функции mysql_real_escape_string - то не нужно. Подготовленные запросы будут автоматически обработаны PDO и защищены от sql-инъекций. Из документации:


Что же касается прочих функций (trim, htmlspecialchars, strip_tags), то их назначение не защита БД, т.е. БД от sql-инъекций эти функции не защитят. Их назначение несколько в ином и использовать их нужно, если в этом есть необходимость. Например, функция trim обрезает пробельные символы справа и слева строки. Функция может быть полезна при валидации. Например, если поле login не должно быть пустым и есть вероятность, что пользователь туда введет просто несколько пробелов. В этом случае trim обрежет все пробельные символы и строка не пройдет валидацию.
Функция htmlspecialchars преобразует специальные символы в HTML-сущности. Эта функция может быть полезна в том случае, если Вы хотите показать код на странице, но при этом данный код не должен выполняться. Также функция поможет защититься от XSS-атак и использовать ее рекомендуется при выводе пользовательских данных в браузер.
Ну а функция strip_tags попросту удаляет все теги из строки. Как-то так :)
Спасибо Андрей за исчерпывающий ответ!
Ответить

 фотография matroskin8 12 Сен 2018

Пожалуйста!
Ответить

 фотография Sasha_1988 29 Сен 2018

Андрей, добрый день.
Смотрел ваш урок по обработки ошибок.
Встречал при создание обработчика фатальных ошибок:
while (ob_get_level()) {
    ob_end_clean();
}
вместо ob_end_clean();

Иначе может что-то вылезти, наверно
Ответить

 фотография matroskin8 30 Сен 2018

Добрый день.
Да, можно и так, если используется несколько уровней вложенности буферизации. Хотя и не использовал такой вариант, с проблемами пока не сталкивался, но читал о нем когда-то, вот даже статью нашел, которую читал.
Ответить

 фотография Sasha_1988 30 Сен 2018

<?php
class ErrorHandler{
public function __construct(){
  error_reporting(E_ALL);
  ob_start();
  register_shutdown_function([$this,'fatalHandler']);
}

public function fatalHandler(){
  //echo ob_get_level();
  ob_get_clean();
 
}
}
new ErrorHandler();
ob_start();
print 23423423;
require_once 'sdfsf.php';
print 3453453453;
$c = ob_get_clean();
?>
Кстати, провел эксперимент, думал в том месте где подключается несуществующий шаблон через require выкинет фатал в браузер, ведь получается ob_start открыт в констукторе ErrorHandler и перед подключением шаблона, соответственно во втором случае буфер не был закрыт,но код корректно отработал, т.е. в браузер ничего не попало. Причем если не делать в fatalHandler() ob_get_clean а вывести ob_get_level видно, что уровня 2. Но в любом случае все корректно срабатывает, хотя мне кажется это не логично.
Ответить

 фотография Genesis 30 Сен 2019

День добрый
Обращаюсь к автору курса PHP-Мастер от теории до собственной CMS интернет магазина
Изучаю ваш курс
Но у меня возникла проблема в части третьей курса урок №6 при написании админ панели
Проблема собственно состоит в чем в админ панели при нажатии на кнопку одобрить должен меняться статус заказа с нового на завершенный и должна меняться дата изменения заказа
Дата меняется а статус по какой то причине нет
Все проверил ошибок нет код правильный
Не могу разобраться в чем дело
Буду крайне признателен за помощь
Ответить

 фотография Genesis 30 Сен 2019

Доброго времени суток
Уже второй день бьюсь с проблемой изменения статуса заказа в админ панели с 0 на 1 и все четно
Вставлял даже исходные файлы в свой проект но результата особо не дало поэтому прошу помощи у вас
Проблема происходит только со статусом почему дата изменения заказа работает
В Open Server проверял логи ошибок ничего нету
Помогите пожалуйста разобраться
Хочу понять где я допустил ошибки и как это работает
Ответить

 фотография matroskin8 30 Сен 2019

Здравствуйте.
Смотрите, Вы выложили сотни строк кода (при этом неоформленного). По кускам кода ошибку не найти, поскольку такой код не запустить. Ошибки же ищут только на живом коде, т.е. на коде, который можно запустить, это называется отладка кода. Исключение может быть в том случае, если код небольшой, на несколько строк. В Вашем случае так не получится. Кроме того, я Вам уже подсказывал, что к каждому уроку есть исходники, с которыми можно сравнить Ваш код или заменить Ваши файлы. Вы пробовали это сделать?
Ответить

 фотография Genesis 10 Окт 2019

Добрый вечер
В продолжении вашего курса хочу попробовать подключить к админ панели входящую почту с gmail ящика!
Не подскажете с чего начать поиск, где посмотреть что почитать?
И еще такой вопрос не хотел поднимать прошлую свою ошибку о которой я писал но я сам разобрался и хотел бы у вас спросить
В вашем курсе статус заказа строка ENUM со значениями 1 2 3 и вот проблема собственно заключалась в ней
Ошибку выдавала что слишком длинная строка или что то в этом роде
Но что самое интересное при замене с ENUM на VARCHAR все работает идеально
Если есть возможность можете насчет этого что то подсказать
Ответить

 фотография matroskin8 11 Окт 2019

Здравствуйте.

Просмотр сообщенияGenesis (10 Октябрь 2019 - 17:33) писал:

В продолжении вашего курса хочу попробовать подключить к админ панели входящую почту с gmail ящика!
Не подскажете с чего начать поиск, где посмотреть что почитать?
Можно посмотреть этот урок. Это что касается отправки писем с сайта. Если же нужно именно получать письма с почтового ящика на сайте, то здесь не подскажу. С такой задачей никогда не сталкивался, но, полагаю, стоит начать с запроса в Google gmail api get emails.

Просмотр сообщенияGenesis (10 Октябрь 2019 - 17:33) писал:

Ошибку выдавала что слишком длинная строка или что то в этом роде
Но что самое интересное при замене с ENUM на VARCHAR все работает идеально
Если есть возможность можете насчет этого что то подсказать
Чтобы что-то подсказать, нужно увидеть ошибку как минимум... без этого остается только гадать. Очевидно, в поле с типом ENUM Вы пытались записать слишком большой объем данных для этого поля, поэтому сервер их и не записывал. Вместо VARCHAR можно поменять тип поля на TINYINT, если в этом поле планируется хранить небольшие числа.
Ответить

 фотография Genesis 12 Окт 2019

Вот сама ошибка

Она возникает когда строка указана как ENUM

Прикрепленные файлы

Ответить

 фотография matroskin8 12 Окт 2019

Я имел в виду, увидеть у себя :) В этом случае можно провести процесс отладки кода и понять причину ошибки.
Ответить