Перейти к содержимому


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


Сообщений в теме: 45

#1 tarabukinivan

    Продвинутый пользователь

  • Клиенты WebForMySelf
  • PipPipPip
  • 62 сообщений
Репутация: 0

Отправлено 08 Сентябрь 2018 - 15:09

Добрый вечер Андрей!
На уроке вы создали метод 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? И проверяют выполнен ли запрос?

#2 matroskin8

    Администратор

  • Администраторы
  • 12 415 сообщений
Репутация: 2 124

Отправлено 09 Сентябрь 2018 - 05:50

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

Просмотр сообщения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, поскольку запрос ведь изменил одну строку. Поэтому, повторюсь, данные в таком случае нужно валидировать.

#3 tarabukinivan

    Продвинутый пользователь

  • Клиенты WebForMySelf
  • PipPipPip
  • 62 сообщений
Репутация: 0

Отправлено 09 Сентябрь 2018 - 08:54

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

#4 tarabukinivan

    Продвинутый пользователь

  • Клиенты WebForMySelf
  • PipPipPip
  • 62 сообщений
Репутация: 0

Отправлено 09 Сентябрь 2018 - 14:55

У меня есть такой метод
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


#5 matroskin8

    Администратор

  • Администраторы
  • 12 415 сообщений
Репутация: 2 124

Отправлено 10 Сентябрь 2018 - 13:17

Просмотр сообщения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(); // будет возвращено кол-во измененных запросом рядов
}


#6 tarabukinivan

    Продвинутый пользователь

  • Клиенты WebForMySelf
  • PipPipPip
  • 62 сообщений
Репутация: 0

Отправлено 11 Сентябрь 2018 - 00:58

Спасибо Андрей!

#7 tarabukinivan

    Продвинутый пользователь

  • Клиенты WebForMySelf
  • PipPipPip
  • 62 сообщений
Репутация: 0

Отправлено 11 Сентябрь 2018 - 01:05

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

#8 matroskin8

    Администратор

  • Администраторы
  • 12 415 сообщений
Репутация: 2 124

Отправлено 11 Сентябрь 2018 - 07:10

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

Просмотр сообщения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 попросту удаляет все теги из строки. Как-то так :)

#9 tarabukinivan

    Продвинутый пользователь

  • Клиенты WebForMySelf
  • PipPipPip
  • 62 сообщений
Репутация: 0

Отправлено 12 Сентябрь 2018 - 06:56

Просмотр сообщения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 попросту удаляет все теги из строки. Как-то так :)
Спасибо Андрей за исчерпывающий ответ!

#10 matroskin8

    Администратор

  • Администраторы
  • 12 415 сообщений
Репутация: 2 124

Отправлено 12 Сентябрь 2018 - 18:43

Пожалуйста!

#11 Sasha_1988

    Продвинутый пользователь

  • Клиенты WebForMySelf
  • PipPipPip
  • 269 сообщений
Репутация: 20

Отправлено 29 Сентябрь 2018 - 13:36

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

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

#12 matroskin8

    Администратор

  • Администраторы
  • 12 415 сообщений
Репутация: 2 124

Отправлено 30 Сентябрь 2018 - 07:46

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

#13 Sasha_1988

    Продвинутый пользователь

  • Клиенты WebForMySelf
  • PipPipPip
  • 269 сообщений
Репутация: 20

Отправлено 30 Сентябрь 2018 - 09:19

<?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. Но в любом случае все корректно срабатывает, хотя мне кажется это не логично.

#14 Genesis

    Пользователь

  • Пользователи
  • PipPip
  • 14 сообщений
Репутация: 0

Отправлено 30 Сентябрь 2019 - 09:26

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

#15 Genesis

    Пользователь

  • Пользователи
  • PipPip
  • 14 сообщений
Репутация: 0

Отправлено 30 Сентябрь 2019 - 15:52

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

#16 matroskin8

    Администратор

  • Администраторы
  • 12 415 сообщений
Репутация: 2 124

Отправлено 30 Сентябрь 2019 - 18:26

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

#17 Genesis

    Пользователь

  • Пользователи
  • PipPip
  • 14 сообщений
Репутация: 0

Отправлено 10 Октябрь 2019 - 17:33

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

#18 matroskin8

    Администратор

  • Администраторы
  • 12 415 сообщений
Репутация: 2 124

Отправлено 11 Октябрь 2019 - 07:28

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

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

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

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

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

#19 Genesis

    Пользователь

  • Пользователи
  • PipPip
  • 14 сообщений
Репутация: 0

Отправлено 12 Октябрь 2019 - 12:34

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

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

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



#20 matroskin8

    Администратор

  • Администраторы
  • 12 415 сообщений
Репутация: 2 124

Отправлено 12 Октябрь 2019 - 13:39

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





Количество пользователей, читающих эту тему: 1

0 пользователей, 1 гостей, 0 анонимных