記事の作成と編集

素晴らしい!超クールな新しいブログができました。人々はコメントで熱心に議論しており、私たちにはようやくさらにプログラミングする時間が少しできました。Adminer は素晴らしいツールですが、ブログに新しい記事を書くには完全に理想的ではありません。アプリケーションから直接新しい記事を追加するための簡単なフォームを作成するのに適切な時期のようです。始めましょう。

まず、ユーザーインターフェースのデザインから始めましょう。

  1. トップページに「新しい記事を書く」リンクを追加します。
  2. このリンクをクリックすると、タイトルと記事の内容を入力するテキストエリアのあるフォームが表示されます。
  3. 保存ボタンをクリックすると、記事がデータベースに保存されます。

後で、ログイン機能も追加し、ログインしたユーザーのみが記事を追加できるようにします。しかし、それは後で。すべてが機能するように、今すぐ書く必要があるコードは何ですか?

  1. 記事を追加するためのフォームを持つ新しい Presenter を作成します。
  2. フォームが正常に送信された後に実行され、新しい記事をデータベースに保存するコールバックを定義します。
  3. そのフォームが表示される新しいテンプレートを作成します。
  4. メインページのテンプレートにフォームへのリンクを追加します。

新しい Presenter

新しい Presenter を EditPresenter と名付け、app/Presentation/Edit/ に保存します。また、データベースに接続する必要があるため、ここでもデータベース接続を要求するコンストラクタを記述します。

<?php
namespace App\Presentation\Edit;

use Nette;
use Nette\Application\UI\Form;

final class EditPresenter extends Nette\Application\UI\Presenter
{
	public function __construct(
		private Nette\Database\Explorer $database,
	) {
	}
}

記事保存フォーム

コメント作成時にフォームとコンポーネントについてはすでに説明しました。まだ不明な点がある場合は、フォームとコンポーネントの作成 を確認してください。私たちはここで待っています ;)

次に、このメソッドを EditPresenter に追加します。

protected function createComponentPostForm(): Form
{
	$form = new Form;
	$form->addText('title', 'タイトル:')
		->setRequired();
	$form->addTextArea('content', '内容:')
		->setRequired();

	$form->addSubmit('send', '保存して公開');
	$form->onSuccess[] = $this->postFormSucceeded(...);

	return $form;
}

フォームから新しい記事を保存する

フォームからのデータを処理するメソッドを追加して続行します。

private function postFormSucceeded(array $data): void
{
	$post = $this->database
		->table('posts')
		->insert($data);

	$this->flashMessage("記事は正常に公開されました。", 'success');
	$this->redirect('Post:show', $post->id);
}

簡単な要約:このメソッドはフォームからデータを取得し、データベースに挿入し、記事が正常に保存されたことをユーザーに通知するメッセージを作成し、新しい記事のページにリダイレクトして、どのように見えるかをすぐに確認できるようにします。

新しい記事を作成するページ

次に、Edit/create.latte テンプレートを作成しましょう。

{block content}
<h1>新しい記事</h1>

{control postForm}

すべてが明確になっているはずです。最後の行は、これから作成するフォームをレンダリングします。

対応する renderCreate メソッドを作成することもできますが、必須ではありません。データベースからデータを取得してテンプレートに渡す必要はないため、そのメソッドは空になります。このような場合、メソッドはまったく存在する必要はありません。

記事作成へのリンク

おそらく、EditPresenter とその create アクションへのリンクを追加する方法はすでに知っているでしょう。試してみてください。

app/Presentation/Home/default.latte ファイルに以下を追加するだけです。

<a n:href="Edit:create">新しい記事を書く</a>

記事の編集

次に、記事を編集する機能も追加しましょう。非常に簡単です。すでに postForm フォームが完成しており、編集にも使用できます。

EditPresenter に新しいページ edit を追加します。

public function renderEdit(int $id): void
{
	$post = $this->database
		->table('posts')
		->get($id);

	if (!$post) {
		$this->error('Post not found');
	}

	$this->getComponent('postForm')
		->setDefaults($post->toArray());
}

そして、別のテンプレート Edit/edit.latte を作成します。

{block content}
<h1>記事を編集</h1>

{control postForm}

そして、postFormSucceeded メソッドを修正します。これにより、新しい記事を追加する(現在行っているように)だけでなく、既存の記事を編集することもできるようになります。

private function postFormSucceeded(array $data): void
{
	$id = $this->getParameter('id');

	if ($id) {
		$post = $this->database
			->table('posts')
			->get($id);
		$post->update($data);

	} else {
		$post = $this->database
			->table('posts')
			->insert($data);
	}

	$this->flashMessage('記事は正常に公開されました。', 'success');
	$this->redirect('Post:show', $post->id);
}

id パラメータが利用可能な場合、それは記事を編集することを意味します。その場合、要求された記事が実際に存在することを確認し、存在する場合はデータベースで更新します。id パラメータが利用できない場合、それは新しい記事を追加する必要があることを意味します。

しかし、その id パラメータはどこから来るのでしょうか?これは renderEdit メソッドに渡されたパラメータです。

これで、app/Presentation/Post/show.latte テンプレートにリンクを追加できます。

<a n:href="Edit:edit $post->id">記事を編集</a>

まとめ

ブログは現在機能しており、訪問者は積極的にコメントしており、公開に Adminer を使用する必要はもうありません。アプリケーションは完全に独立しており、誰でも新しい記事を追加できます。ちょっと待ってください、誰でも – そしてそれは本当にインターネットにアクセスできる誰でも – 新しい記事を追加できるというのは、おそらく完全に正しいことではありません。ログインしたユーザーのみが新しい記事を追加できるように、何らかのセキュリティが必要です。これについては次の章で見ていきます。