Этот урок набрал набрал достаточно большое количество
комментариев и дальнейшее его комментирование отключено.
Если вы хотели убедиться в правильности выполнения ДЗ или у вас возник вопрос по уроку,
посмотрите ранее добавленные комментарии, кликнув по кнопке ниже. Скорее всего вы найдете там то, что искали.
Если это не помогло - задайте вопрос в чате в телеграме - https://t.me/php_zone
public function delete (int $id)
{
$article = Article::getById($id);
if ($article) {
$article->delete();
echo ' Статья удалена';
}
echo ' Статьи с таким id не существует';
}
Создайте роут для удаления статей - http://myproject.loc/articles/2/delete
При заходе на него получайте объект статьи по id и после этого удаляйте статью. Если статьи с таким id нет, то выдавайте соответствующее сообщение. Если же статья была, то выводите объект с помощью var_dump после удаления.
//notObject.php
<h1>Статья не существует, либо удалена</h1>
//ArticlesController.php
public function delete(int $articleId): void
{
$article = Article::getById($articleId);
if ($article === null) {
$this->view->renderHtml('errors/notObject.php', [], 404);
return;
}
$article->delete();
var_dump($article);
}
все таки есть некоторая каша в голове по поводу того почему нельзя везде делать статические или динамические только, как понять где статику ставить а где нет?
Статика применяется тогда, когда объектов нет. Например, для их создания. Но не только. В целом, если уже есть объект, то стоит использовать динамические методы.
public function delete(int $articleId): void //delete a record from Data Base
{
$article = Article::getById($articleId);
if ($article === null) {
$this->view->renderHtml('errors/404.php', [], 404);
return;
}
$article->delete();
var_dump($article);
}
route: '~^articles/(\d+)/delete$~' => [ArticlesController::class, 'delete']
После удаления:
object(MyProject\Models\Articles\Article)[4]
protected 'name' => string 'Новое название статьи' (length=40)
protected 'text' => string 'Новый текст статьи' (length=34)
protected 'authorId' => string '1' (length=1)
protected 'createdAt' => string '2019-07-29 18:43:05' (length=19)
protected 'id' => null
Если обновить страницу или прописать адрес с Id которого в базе нет - будет ошибка 404.
Привет, Артем. Я не очень понял зачем в src/MyProject/Models/ActiveRecordEntity.php в конце метода delete() обращать свойство id в null ($this->id = null)? Ведь все равно в результате работы этого метода строка с таким id будет удалена из базы данных, зачем дополнительно уничтожать id у объекта-то?
Объект должен отражать состояние строки в таблице. Если строки нет, то и id у объекта быть не должно. Если у этого объекта теперь вызвать метод save(), то создастся новая запись. Если же id объекта перед этим не очистить, то будет выполнен запрос в базу с типом UPDATE, из-за чего возникнет ошибка, так как записи с таким id нет.
public function delete(int $articleId): void
{
$article = Article::getById($articleId);
if ($article === null) {
$this->view->renderHtml('errors/NotFound.php', [], 404);
return;
}
$article->delete();
var_dump($article);
}
ActiveRecordEntity.php:
public function delete(): void
{
$db = Db::getInstance();
$db->query('DELETE FROM `' . static::getTableName() . '` WHERE id = :id;', [':id' => $this->id]);
$this->id = null;
}
Кстати, заметил один момент: при обращении по адресу /articles/несуществующий_id мы как положено отправляли 404 ошибку, но при обращении по адресу /articles/несуществующий_id/ уже был код 200 и выводилось сообщение из index.php:
if (!$isRouteFound) {
echo 'Страница не найдена!';
return;
}
В связи с эти я немного подправил наш главный статейный роут (добавил /? в конце):
public function delete(int $articleId): void
{
$article = Article::getById($articleId);
if ($article === null) {
echo 'Статьи с таким id не существует';
return;
}
$article->delete();
var_dump($article);
}
Не факт. Возможно в нем просто стоит выводить переменную, которую вы будете передавать из контроллера? А в ней уже будет написано, чего именно не хватает.
public function delete(int $articleId): void
{
$article = Article::getById($articleId);
if ($article) {
$article->delete();
echo "Статья успешно удалена.";
var_dump($article);
return;
}
echo "Такой статьи не существует!";
}
Приучайте себя в первую очередь обрабатывать негативные кейсы. Если сначала проверить что статьи нет и вернуть в этом случае ошибку, основной поток не будет находиться в блоке условия и код будет выглядеть проще.
public function delete(int $articleId): void
{
$article = Article::getById($articleId);
if ($article == null) {
echo 'Такой статьи не существует!';
return;
}
$article->delete();
echo 'Статья успешно удалена.';
var_dump($article);
}
Так?
У меня если честно, вообще в последних 5-6 уроках домашка вызывает ступор. Сам с ходу сделать не могу. Если подсмотреть готовые решение, тогда все становиться понятно и логично и могу у себя такое же сделать. Немного руки опускаются. Ведь в 30 лет перейти в IT сферу и так не просто, а мне еще и ООП туго идет
public function delete(int $articleId): void
{
$article = Article::getById($articleId);
if ($article == null) {
echo 'Статьи с таким ID не существует';
return;
}
$article->delete();
var_dump($article);
}
ActiveRecordEntity.php
public function delete(): void
{
$db = Db::getInstance();
$db->query(
'DELETE FROM `' . static::getTableName() . '` WHERE id = :id',
[':id' => $this->id]
);
$this->id = null;
}
.........
public function delete(): void
{
$db = Db::getInstance();
$db->query(
'DELETE FROM `' . static::getTableName() . '` WHERE id = :id',
[':id' => $this->id]
);
$this->id = null;
}
........
Не совсем поняно что происходит в этотм универсальном методе универсального класса. Особенно в части касаемо каким образом передается ид, и подставляется имя таблицы, которое каким то образом привязано к статик. Это и есть рефлексия?!
В файле ArticleController.php
....
public function delete(int $articleId): void
{
$article = Article::getById($articleId);
if ($article === null) {
$this->view->renderHtml('errors/404.php', [], 404);
return;
}
$article->delete();
var_dump($article);
$article->delete();
// Здесь редирект на главную статью например с тутлипом что страница удалена или на все статьи страницу
return;
}
....
Не совсем поняно что происходит в этотм универсальном методе универсального класса. Особенно в части касаемо каким образом передается ид, и подставляется имя таблицы, которое каким то образом привязано к статик. Это и есть рефлексия?!
Нет здесь рефлексии. Сущность, у которой вызывается метод, имеет и свойство id и метод getTableName. Вы же сами их добавляли ранее :)
Зачем-то save сначала делал чтобы сохранить изменения. Убедлся что запись в таблице статей с соответсвующим ид удаляется, что видно при обновлении страницы.
Но при этом создавалась новая запись. Отследил ошибку через var_dump.
Посмотрел ответы других учеников.
Позже думаю также добавить универсальный шаблон при отсутсвии удалаяемого/запрашиваемого объекта.
public function delete(int $articleId): void
{
$article = Article::getById($articleId);
if ($article) {
$article->delete();
echo 'Статья удалена!';
var_dump($article);
return;
}
echo 'Статья с таким id не существует';
}
файл ActiveRecordEntity.php
файл Route.php
файл ArticleController.php
Отлично!
ivashkevich, что "отлично", роут же неверный! такой паттерн должен быть!
И вторая ошибка, при удалении нужно сообщения выводить через if/else
а в описанном выше коде будут два срабатывания echo вне зависимости от результата!
Как вы проверяете домашку? ))
Создайте роут для удаления статей - http://myproject.loc/articles/2/delete
При заходе на него получайте объект статьи по id и после этого удаляйте статью. Если статьи с таким id нет, то выдавайте соответствующее сообщение. Если же статья была, то выводите объект с помощью var_dump после удаления.
Супер! Шаблон можно назвать NotFound, и передавать в него переменную error с конкретной ошибкой.
Спасибо, доделаю.
Это необязательно, но будет круто, если сделаешь!
ДЗ:
routes.php
ArticlesController.php
PageNot.php
Не надо в контроллерах HTML-тегов. Заведите отдельный шаблон для случая успешного удаления статьи.
Шаблон для отсутствующей страницы лучше назвать NotFound.
Вот так проверять:
плохо. Лучше сравнивать, что переменная !== null, или что значение является объектом какого-то класса (при помощи instanseof).
После удаление статьи, если добавить новую, то в БД id присваивается следующий номер после удаленной, а не по порядку. Хотя в поле id стоит auto_increment, так и должно быть?
http://s1.radikali.ru/uploads/2018/12/2/5857e823d14c9bfc9790ffb029fa2ef2-full.png
Да, база просто хранит последний использованный id отдельно, и шагает именно от него.
Вот решение д/з:
ArticlesController.php
Роут
delete.php
notFound.php
Лучше более явно проверять:
Понял, спасибо!
ArticleController.php
routes.php
Отлично!
А это для чего?
так ведь метод же нужно брать от созданного объекта?? иначе то ошибку выдает, или можно как то иначе?
аа, понял он статический и можно вот так Article::getById($articleId); )))
Нужно, а не можно) Статические методы для этого и нужны
все таки есть некоторая каша в голове по поводу того почему нельзя везде делать статические или динамические только, как понять где статику ставить а где нет?
Статика применяется тогда, когда объектов нет. Например, для их создания. Но не только. В целом, если уже есть объект, то стоит использовать динамические методы.
Отлично
routes.php
ArticlesController.php
NotFound.php
Что за del?) Называйте понятно
ArticleController.php
notfound.php
...
<h2>Извините, этой статьи не существует!!</h2>
...
Не используйте is_null. Или сравнивайте с null явно, или проверяйте через instanceof.
Хорошо )
routes.php:
ArticlesController:
Отлично
Привет, Артем. Я не очень понял зачем в src/MyProject/Models/ActiveRecordEntity.php в конце метода delete() обращать свойство id в null ($this->id = null)? Ведь все равно в результате работы этого метода строка с таким id будет удалена из базы данных, зачем дополнительно уничтожать id у объекта-то?
Объект должен отражать состояние строки в таблице. Если строки нет, то и id у объекта быть не должно. Если у этого объекта теперь вызвать метод save(), то создастся новая запись. Если же id объекта перед этим не очистить, то будет выполнен запрос в базу с типом UPDATE, из-за чего возникнет ошибка, так как записи с таким id нет.
Routes.php
ArticlesController.php
Ок. Только нужно поправить отступы.
когда мы удаляем строку в Бд, а потом добавляем новую строку то id идет не по порядку из-за того, что мы используем lastInsertId(), как это исправить?
Что значит не по порядку? Можно конкретный пример?
src/routes.php
src/MyProject/Models/ActiveRecordEntity.php
src/MyProject/Controllers/ArticlesController.php
Отлично
Спасибо за урок!)
routes.php:
ArticlesController.php:
ActiveRecordEntity.php:
Кстати, заметил один момент: при обращении по адресу /articles/несуществующий_id мы как положено отправляли 404 ошибку, но при обращении по адресу /articles/несуществующий_id/ уже был код 200 и выводилось сообщение из index.php:
В связи с эти я немного подправил наш главный статейный роут (добавил /? в конце):
Может быть это и не важно (а может и вообще неправильно), но решил на этом заострить внимание
Зачем слеш после id статьи? Не понял что вы хотите сделать и зачем.
Я замечал что на разных сайтах урл по разному заканчивается, где-то есть слеш, где-то нет.
Слеш в конце урл - это моё предположение, что такая ситуация может случиться, и её нужно как-то обработать. Если это незачем - поправьте меня)
Просто так такой ситуации произойти не может. Если только на такой адрес не поставят ссылку.
Понял, спасибо за разъяснение)
ArticlesController.php
Отлично
ArticlesController.php
ActiveRecordEntity.php
deleted.php
Отлично
Отлично!
Роут
ArticlesController
Отлично
routes.php:
ArticlesController.php:
notId.php:
Логичнее будет назвать шаблон notFound, и раз уж он только для статей, это тоже нужно отразить в его названии/пути.
Согласен, но наверное лучше сделать его общим для разных объектов:
MyProject/errors/notFound.php:
Не факт. Возможно в нем просто стоит выводить переменную, которую вы будете передавать из контроллера? А в ней уже будет написано, чего именно не хватает.
Действительно так лучше. 404.php:
ArticleController.php:
А с исключениями:
Отлично!
src/routes.php
src/MyProject/Controllers/ArticleController.php
templates/errors/NotFound.php
Отлично
ArticlesController
routes
Отлично
Исправил +
У нас же есть 404-исключение
src\routes.php
src\MyProject\Controllers\ArticlesController.php
src\MyProject\Models\ActiveRecordEntity.php
Отлично
Роут
Метод контроллера для удаления статьи
Тогда уж строгое неравенство !==. Мало ли к чему так null приведется.
routes.php
ArticlesController.php
Output:
Отлично
routes.php
Добавлено:
ArticleController.php
Добавлено:
Приучайте себя в первую очередь обрабатывать негативные кейсы. Если сначала проверить что статьи нет и вернуть в этом случае ошибку, основной поток не будет находиться в блоке условия и код будет выглядеть проще.
Так?
У меня если честно, вообще в последних 5-6 уроках домашка вызывает ступор. Сам с ходу сделать не могу. Если подсмотреть готовые решение, тогда все становиться понятно и логично и могу у себя такое же сделать. Немного руки опускаются. Ведь в 30 лет перейти в IT сферу и так не просто, а мне еще и ООП туго идет
Да, так.
Попробуйте уделять больше времени урокам в день, и заниматься каждый день хотя бы по часу. И не забывайте про алгоритмические задачки.
Строки пишутся в одинарных кавычках.
routes.php
ArticlesController.php
ActiveRecordEntity.php
Отлично!
ActiveRecordEntity
ArticlesController
Отлично
routes.php
ArticlesController.php
ActiveRecordEntity.php
Если попытаться удалить несуществующую статью, будет ошибка.
ArticleController.php
Ок. Лучше поставить return после отрисовки 404-шаблона, и блок else не понадобится тогда.
Проблема с форматированием. Делайте отступы и переносы как в уроках. Для этого в шторме можно нажать Ctrl+Alt+L
routes.php
ArticlesController.php
Отлично
routes.php
ArticlesController.php
А почему не через исключение 404 ошибка реализована?
наверное, что на данном этапе мы ещё не проходили исключения)))
Ох, сорян)
File routes.php
File ArticlesController.php
File ActiveRecordEntity.php
Отлично. Вообще, чтобы показать что объект не хранится в базе, достаточно удалить у него идентификатор.
routes.php
ArticlesController.php
ActiveRecordEntity.php
Отлично!
My URL
http://phpzone3/articles/13/delete
файл ActiveRecordEntity.php
Не совсем поняно что происходит в этотм универсальном методе универсального класса. Особенно в части касаемо каким образом передается ид, и подставляется имя таблицы, которое каким то образом привязано к статик. Это и есть рефлексия?!
В файле ArticleController.php
routing.php
Нет здесь рефлексии. Сущность, у которой вызывается метод, имеет и свойство id и метод getTableName. Вы же сами их добавляли ранее :)
Артём сделал удаление однако у меня не получается приравнять id к null. Пишет must be int, null used
ActiveRecordEntity
ArticlesController
А в каком месте ругается? Что на той строке написано? Использовать -1 не оч корректно.
ArticlesController.php
Зачем-то save сначала делал чтобы сохранить изменения. Убедлся что запись в таблице статей с соответсвующим ид удаляется, что видно при обновлении страницы.
Но при этом создавалась новая запись. Отследил ошибку через var_dump.
Посмотрел ответы других учеников.
Позже думаю также добавить универсальный шаблон при отсутсвии удалаяемого/запрашиваемого объекта.
Супер!
ArticlesController
Отлично