ブログのトップページ

次に、最新の記事を表示するトップページを作成しましょう。

始める前に、少なくとも Model-View-Presenter 設計パターン(MVC に似ています)の基本を知っておく必要があります。

  • Model – データを扱う層。アプリケーションの残りの部分から完全に分離されています。Presenterとのみ通信します。
  • View – フロントエンド層。テンプレートを使用して要求されたデータをレンダリングし、ユーザーに表示します。
  • Presenter(または Controller) – 接続層。Presenter は Model と View を接続します。リクエストを処理し、Model にデータを問い合わせ、それを View に返します。

私たちのブログのような単純なアプリケーションの場合、モデル層全体はデータベースへのクエリのみで構成されます – これには今のところ特別なコードは必要ありません。したがって、最初は Presenter とテンプレートのみを作成します。Nette では、各 Presenter には独自のテンプレートがあるため、同時に作成します。

Adminer を使用したデータベースの作成

データの保存には MySQL データベースを使用します。これは、Web アプリケーション開発者の間で最も普及しているためです。ただし、使用したくない場合は、自由に選択したデータベースを選択してください。

次に、ブログの記事を保存するデータベース構造を準備します。非常に単純なものから始めます – 記事用のテーブルを 1 つだけ作成します。

データベースを作成するには、Adminer または他の好きなデータベース管理ツールをダウンロードできます。

Adminer を開き、quickstart という名前の新しいデータベースを作成します。

posts という名前の新しいテーブルを次のカラムで作成します。

  • id int、オートインクリメント (AI) にチェック
  • title varchar、長さ 255
  • content text
  • created_at timestamp

結果の構造は次のようになります。

CREATE TABLE `posts` (
	`id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
	`title` varchar(255) NOT NULL,
	`content` text NOT NULL,
	`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB CHARSET=utf8;

InnoDB ストレージを使用することは本当に重要です。その理由はすぐにわかります。今のところ、単にそれを選択して保存をクリックしてください。

アプリケーションを使用してデータベースに記事を追加する機能を作成する前に、ブログにいくつかのサンプル記事を手動で追加してください。

INSERT INTO `posts` (`id`, `title`, `content`, `created_at`) VALUES
(1,	'Article One',	'Lorem ipusm dolor one',	CURRENT_TIMESTAMP),
(2,	'Article Two',	'Lorem ipsum dolor two',	CURRENT_TIMESTAMP),
(3,	'Article Three',	'Lorem ipsum dolor three',	CURRENT_TIMESTAMP);

データベースへの接続

データベースが作成され、いくつかの記事が保存されたので、それらを美しい新しいページに表示するのに適切な時期です。

まず、アプリケーションに使用するデータベースを伝える必要があります。データベースへの接続は、DSN とログイン資格情報を使用して config/common.neon ファイルで設定します。次のようになります。

database:
	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
	user: *ここにユーザー名を入力*
	password: *ここにデータベースのパスワードを入力*

このファイルを編集するときは、行のインデントに注意してください。NEON 形式は、スペースによるインデントとタブによるインデントの両方を受け入れますが、両方を同時に使用することはできません。Web Project のデフォルト設定ファイルはタブを使用します。

データベース接続の受け渡し

記事のリスト表示を担当する HomePresenter は、データベースへの接続が必要です。それを取得するために、次のようなコンストラクタを使用します。

<?php
namespace App\Presentation\Home;

use Nette;

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

	// ...
}

データベースからの記事の読み込み

次に、データベースから記事を読み込み、テンプレートに送信します。テンプレートはその後、HTML コードとしてレンダリングします。これには、いわゆる render メソッドが使用されます。

public function renderDefault(): void
{
	$this->template->posts = $this->database
		->table('posts')
		->order('created_at DESC')
		->limit(5);
}

Presenter には、データベースからテンプレート(View)にデータを渡す 1 つのレンダリングメソッド renderDefault() が含まれるようになりました。テンプレートは app/Presentation/{PresenterName}/{viewName}.latte に配置されているため、この場合、テンプレートは app/Presentation/Home/default.latte に配置されます。テンプレートでは、データベースから取得した記事を含む変数 $posts が利用可能になります。

テンプレート

Web サイト全体には、メインテンプレート(layout と呼ばれ、ヘッダー、スタイル、フッターなどを含む)と、各ビュー(View)用の特定のテンプレート(例:ブログ記事の表示用)があり、これらはメインテンプレートの一部を上書きできます。

デフォルトでは、レイアウトテンプレートは app/Presentation/@layout.latte に配置され、次の内容が含まれます。

...
{include content}
...

{include content} という記述は、content という名前のブロックをメインテンプレートに挿入します。これは、個々のビュー(View)のテンプレートで定義します。私たちの場合、Home/default.latte ファイルを次のように変更します。

{block content}
	Hello World
{/block}

これにより、メインレイアウトに挿入される content ブロック を定義しました。ブラウザを再度更新すると、「Hello World」というテキストが表示されたページが表示されます(ソースコードには @layout.latte で定義された HTML ヘッダーとフッターも含まれます)。

ブログ記事を表示しましょう – テンプレートを次のように変更します。

{block content}
	<h1>私のブログ</h1>

	{foreach $posts as $post}
	<div class="post">
		<div class="date">{$post->created_at|date:'F j, Y'}</div>

		<h2>{$post->title}</h2>

		<div>{$post->content|truncate:256}</div>
	</div>
	{/foreach}
{/block}

ブラウザを更新すると、すべての記事のリストが表示されます。リストはまだあまり見栄えが良くなく、色もありません。そのため、www/css/style.css ファイルにいくつかの CSS スタイル を追加し、レイアウトでリンクすることができます。

	...
	<link rel="stylesheet" href="{$basePath}/css/style.css">
</head>
...

{foreach} タグは、変数 $posts でテンプレートに渡したすべての記事を反復処理し、それぞれに対して指定された HTML の一部をレンダリングします。これは PHP コードとまったく同じように動作します。

|date: という記述をフィルタと呼びます。フィルタは出力のフォーマットに使用されます。この特定のフィルタは、日付(例:2013-04-12)をより読みやすい形式(April 12, 2013)に変換します。|truncate フィルタは、文字列を指定された最大長に切り詰め、文字列が短縮された場合は末尾に 3 つのドットを追加します。これはプレビューであるため、記事の全文を表示する意味はありません。その他のデフォルトフィルタは ドキュメント にあり、必要に応じて独自のフィルタを作成することもできます。

もう 1 つ。前のコードを短縮して簡略化できます。これは、*Latte タグ* を n:属性 に置き換えることで実現できます。

{block content}
	<h1>私のブログ</h1>

	<div n:foreach="$posts as $post" class="post">
		<div class="date">{$post->created_at|date:'F j, Y'}</div>

		<h2>{$post->title}</h2>

		<div>{$post->content|truncate:256}</div>
	</div>
{/block}

n:foreach 属性は、div ブロックを foreach でラップします(前のコードとまったく同じように機能します)。

まとめ

これで、いくつかの記事を含む非常に単純な MySQL データベースができました。アプリケーションはこのデータベースに接続し、これらの記事の単純なリストをテンプレートに出力します。