Page d'accueil du blog

Créons maintenant la page d'accueil affichant les derniers articles.

Avant de commencer, il est nécessaire de connaître au moins les bases du patron de conception Modèle-Vue-Présenteur (similaire à MVC ((Modèle-Vue-Contrôleur))) :

  • Modèle – couche travaillant avec les données. Elle est complètement séparée du reste de l'application. Elle communique uniquement avec le presenter.
  • Vue – couche front-end. Elle affiche les données demandées à l'aide de templates et les présente à l'utilisateur.
  • Présenteur (ou Contrôleur) – couche de liaison. Le Presenter relie le Modèle et la Vue. Il traite les requêtes, interroge le Modèle pour obtenir des données et les renvoie à la Vue.

Dans le cas d'applications simples, comme notre blog, toute la couche modèle sera constituée uniquement de requêtes vers la base de données – pour cela, nous n'avons pas besoin de code supplémentaire pour le moment. Pour commencer, nous créerons donc uniquement les presenters et les templates. Dans Nette, chaque presenter a ses propres templates, nous les créerons donc en même temps.

Création de la base de données avec Adminer

Pour stocker les données, nous utiliserons une base de données MySQL, car c'est la plus répandue parmi les programmeurs d'applications web. Cependant, si vous ne souhaitez pas l'utiliser, n'hésitez pas à choisir une base de données de votre choix.

Préparons maintenant la structure de la base de données où seront stockés les articles de notre blog. Commençons très simplement – nous créerons une seule table pour les articles.

Pour créer la base de données, nous pouvons télécharger Adminer, ou un autre de vos outils préférés pour la gestion des bases de données.

Ouvrons Adminer et créons une nouvelle base de données nommée quickstart.

Créons une nouvelle table nommée posts avec ces colonnes :

  • id int, cochez autoincrement (AI)
  • title varchar, longueur 255
  • content text
  • created_at timestamp

La structure résultante devrait ressembler à ceci :

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;

Il est vraiment important d'utiliser le stockage InnoDB. Nous verrons bientôt pourquoi. Pour l'instant, sélectionnez-le simplement et cliquez sur enregistrer.

Avant de créer la possibilité d'ajouter des articles à la base de données via l'application, ajoutez manuellement quelques exemples d'articles sur le blog.

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);

Connexion à la base de données

Maintenant que la base de données est créée et que nous y avons stocké quelques articles, il est temps de les afficher sur notre belle nouvelle page.

Tout d'abord, nous devons indiquer à l'application quelle base de données utiliser. La connexion à la base de données est configurée dans le fichier config/common.neon à l'aide du DSN ((Data Source Name)) et des informations d'identification. Cela devrait ressembler à quelque chose comme ceci :

database:
	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
	user: *insérez ici le nom d'utilisateur*
	password: *insérez ici le mot de passe de la base de données*

Lors de la modification de ce fichier, faites attention à l'indentation des lignes. Le format NEON accepte à la fois l'indentation par espaces et l'indentation par tabulations, mais pas les deux en même temps. Le fichier de configuration par défaut dans Web Project utilise des tabulations.

Passage de la connexion à la base de données

Le presenter HomePresenter, qui s'occupera de l'affichage des articles, a besoin d'une connexion à la base de données. Pour l'obtenir, nous utiliserons un constructeur qui ressemblera à ceci :

<?php
namespace App\Presentation\Home;

use Nette;

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

	// ...
}

Chargement des articles depuis la base de données

Maintenant, chargeons les articles de la base de données et envoyons-les au template, qui les affichera ensuite sous forme de code HTML. Pour cela, une méthode dite render est prévue :

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

Le presenter contient maintenant une méthode de rendu renderDefault(), qui transmet les données de la base de données au template (Vue). Les templates sont situés dans app/Presentation/{PresenterName}/{viewName}.latte, donc dans ce cas, le template est situé dans app/Presentation/Home/default.latte. Dans le template, la variable $posts sera désormais disponible, contenant les articles récupérés de la base de données.

Template

Pour l'ensemble du site web, nous disposons d'un template principal (appelé layout, contenant l'en-tête, les styles, le pied de page,…) et de templates spécifiques pour chaque vue (par exemple, pour afficher les articles du blog), qui peuvent remplacer certaines parties du template principal.

Par défaut, le template de layout est situé dans app/Presentation/@layout.latte et contient :

...
{include content}
...

L'écriture {include content} insère dans le template principal un bloc nommé content. Nous le définirons dans les templates des vues individuelles. Dans notre cas, nous modifions le fichier Home/default.latte comme suit :

{block content}
	Hello World
{/block}

Nous avons ainsi défini le bloc content, qui sera inséré dans le layout principal. Si nous actualisons à nouveau le navigateur, nous verrons une page avec le texte “Hello World” (dans le code source également avec l'en-tête et le pied de page HTML définis dans @layout.latte).

Affichons les articles du blog – modifions le template comme suit :

{block content}
	<h1>Mon blog</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}

Si nous actualisons le navigateur, nous verrons la liste de tous les articles. L'affichage n'est pas encore très joli, ni coloré, nous pouvons donc ajouter quelques styles CSS au fichier www/css/style.css et le lier dans le layout :

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

La balise {foreach} itère sur tous les articles que nous avons transmis au template dans la variable $posts, et pour chacun, affiche le morceau de HTML donné. Elle se comporte exactement comme le code PHP.

L'écriture |date: est appelée un filtre. Les filtres sont destinés à formater la sortie. Ce filtre particulier convertit la date (par exemple 2013-04-12) en une forme plus lisible (April 12, 2013). Le filtre |truncate coupe la chaîne à la longueur maximale spécifiée et, si la chaîne est raccourcie, ajoute des points de suspension à la fin. Comme il s'agit d'un aperçu, il n'est pas logique d'afficher tout le contenu de l'article. D'autres filtres par défaut peuvent être trouvés dans la documentation ou nous pouvons créer les nôtres si nécessaire.

Encore une chose. Nous pouvons raccourcir et simplifier le code précédent. Nous y parvenons en remplaçant les balises Latte par des n:attributs :

{block content}
	<h1>Mon blog</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}

L'attribut n:foreach enveloppe le bloc div avec un foreach (fonctionne exactement de la même manière que le code précédent).

Résumé

Nous avons maintenant une base de données MySQL très simple avec quelques articles. L'application se connecte à cette base de données et affiche une simple liste de ces articles dans le template.