Редактируем статьи в блоге на PHP

Сегодня мы создадим еще один компонент нашего блога – систему редактирования статей.

В одном из прошлых уроков мы уже добавляли роутинг для редактирования статей:

src/routes.php

'~^articles/(\d+)/edit$~' => [\MyProject\Controllers\ArticlesController::class, 'edit'],

Он останется прежним. Переходим к экшену. Сейчас он выглядит вот так:

src/MyProject/Controllers/ArticlesController.php

public function edit(int $articleId)
{
    $article = Article::getById($articleId);

    if ($article === null) {
        throw new NotFoundException();
    }

    $article->setName('Новое название статьи');
    $article->setText('Новый текст статьи');

    $article->save();
}

Нам требуется его переписать, чтобы статья обновлялась данными из POST-запроса. Делаем:

public function edit(int $articleId)
{
    $article = Article::getById($articleId);

    if ($article === null) {
        throw new NotFoundException();
    }

    if ($this->user === null) {
        throw new UnauthorizedException();
    }

    if (!empty($_POST)) {
        try {
            $article->updateFromArray($_POST);
        } catch (InvalidArgumentException $e) {
            $this->view->renderHtml('articles/edit.php', ['error' => $e->getMessage(), 'article' => $article]);
            return;
        }

        header('Location: /articles/' . $article->getId(), true, 302);
        exit();
    }

    $this->view->renderHtml('articles/edit.php', ['article' => $article]);
}

Теперь давайте добавим соответсвующий шаблон.

templates/articles/edit.php

<?php
/**
 * @var \MyProject\Models\Articles\Article $article
 */
include __DIR__ . '/../header.php';
?>
    <h1>Редактирование статьи</h1>
    <?php if(!empty($error)): ?>
        <div style="color: red;"><?= $error ?></div>
    <?php endif; ?>
    <form action="/articles/<?= $article->getId() ?>/edit" method="post">
        <label for="name">Название статьи</label><br>
        <input type="text" name="name" id="name" value="<?= $_POST['name'] ?? $article->getName() ?>" size="50"><br>
        <br>
        <label for="text">Текст статьи</label><br>
        <textarea name="text" id="text" rows="10" cols="80"><?= $_POST['text'] ?? $article->getText() ?></textarea><br>
        <br>
        <input type="submit" value="Обновить">
    </form>
<?php include __DIR__ . '/../footer.php'; ?>

А теперь добавим соответствующий метод в модели:

src/MyProject/Models/Articles/Article.php

public function updateFromArray(array $fields): Article
{
    if (empty($fields['name'])) {
        throw new InvalidArgumentException('Не передано название статьи');
    }

    if (empty($fields['text'])) {
        throw new InvalidArgumentException('Не передан текст статьи');
    }

    $this->setName($fields['name']);
    $this->setText($fields['text']);

    $this->save();

    return $this;
}

Заходим теперь на страничку редактирования статьи:
http://myproject.loc/articles/14/edit

Редактирование статьи

Вводим какой-нибудь новый текст и заголовок.
Изменяем статью

Нажимаем на кнопку обновления и вуаля – статья обновлена.
Обновленная статья

Текущая версия кода на гитхабе.

loader
Домашнее задание
  1. При попытке обновления статьи НЕ админом – бросайте исключение ForbiddenException, как в прошлом уроке.
  2. Добавьте ссылку на странице показа статьи с текстом «Редактировать», которая будет вести на страницу редактирования этой статьи.
  3. Сделайте так, чтобы эта ссылка показывалась только если пользователь залогинен и он админ.
Комментарии
Этот урок набрал набрал достаточно большое количество комментариев и дальнейшее его комментирование отключено. Если вы хотели убедиться в правильности выполнения ДЗ или у вас возник вопрос по уроку, посмотрите ранее добавленные комментарии, кликнув по кнопке ниже. Скорее всего вы найдете там то, что искали. Если это не помогло - задайте вопрос в чате в телеграме - https://t.me/php_zone
Логические задачи с собеседований