Nette Documentation Preview

syntax
Page d'accueil du blog
**********************

.[perex]
Créons la page d'accueil affichant vos articles récents.


Avant de commencer, vous devez connaître au moins les bases du modèle de conception Modèle-Vue-Présentateur (similaire à MVC((Model-View-Controller))) :

- **Modèle** - couche de manipulation des données. Elle est complètement séparée du reste de l'application. Elle ne communique qu'avec les présentateurs.

- **View** - une couche de définition frontale. Elle rend les données demandées à l'utilisateur en utilisant des modèles.

- **Presenter** (ou Controller) - une couche de connexion. Le présentateur relie le modèle et la vue. Il traite les demandes, demande des données au modèle et les transmet ensuite à la vue en cours.


Dans le cas d'une application très simple comme notre blog, la couche Modèle sera en fait constituée uniquement de requêtes à la base de données elle-même - nous n'avons pas besoin de code PHP supplémentaire pour cela. Nous avons seulement besoin de créer les couches Presenter et View. Dans Nette, chaque Presenter a ses propres Views, donc nous allons continuer avec les deux simultanément.


Création de la base de données avec Adminer .[#toc-creating-the-database-with-adminer]
======================================================================================

Pour stocker les données, nous utiliserons la base de données MySQL car c'est le choix le plus courant parmi les développeurs web. Mais si vous ne l'aimez pas, n'hésitez pas à utiliser une base de données de votre choix.

Préparons la base de données qui stockera nos articles de blog. Nous pouvons commencer très simplement - avec une seule table pour les articles.

Pour créer la base de données, nous pouvons télécharger [Adminer |https://www.adminer.org], ou vous pouvez utiliser un autre outil de gestion de base de données.


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

Créez une nouvelle table nommée `posts` et ajoutez ces colonnes :
- `id` int, cliquez sur autoincrement (AI)
- `title` varchar, longueur 255
- `content` text
- `created_at` timestamp

Cela devrait ressembler à ceci :

[* adminer-posts.webp *]

```sql
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;
```

.[caution]
Il est très important d'utiliser la table de stockage **InnoDB**. Vous en verrez la raison plus tard. Pour l'instant, choisissez simplement cela et soumettez. Vous pouvez cliquer sur Enregistrer maintenant.

Essayez d'ajouter quelques exemples d'articles de blog avant de mettre en œuvre la possibilité d'ajouter de nouveaux articles directement à partir de notre application.

```sql
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 .[#toc-connecting-to-the-database]
=================================================================

Maintenant, quand la base de données est créée et que nous avons des articles dedans, c'est le bon moment pour les afficher sur notre nouvelle page brillante.

Tout d'abord, nous devons indiquer à notre application quelle base de données utiliser. La configuration de la connexion à la base de données est stockée dans `config/common.neon`. Définissez la connexion DSN((Data Source Name)) et vos informations d'identification. Cela devrait ressembler à ceci :

```neon .{file:config/common.neon}
database:
	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
	user: *enter user name*
	password: *enter password here*
```

.[note]
Faites attention à l'indentation lorsque vous modifiez ce fichier. Le [format NEON |neon:format] accepte les espaces et les tabulations, mais pas les deux ensemble ! Le fichier de configuration du projet Web utilise les tabulations par défaut.


Injection de la connexion à la base de données .[#toc-injecting-the-database-connection]
========================================================================================

Le présentateur `HomePresenter`, qui va lister les articles, a besoin d'une connexion à la base de données. Pour la recevoir, écrivez un constructeur comme celui-ci :

```php .{file:app/UI/Home/HomePresenter.php}
<?php
namespace App\UI\Home;

use Nette;

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

	// ...
}
```


Chargement des messages depuis la base de données .[#toc-loading-posts-from-the-database]
=========================================================================================

Maintenant, récupérons les messages de la base de données et transmettons-les au modèle, qui rendra ensuite le code HTML. C'est à cela que sert la méthode dite *render* :

```php .{file:app/UI/Home/HomePresenter.php}
public function renderDefault(): void
{
	$this->template->posts = $this->database
		->table('posts')
		->order('created_at DESC')
		->limit(5);
}
```

Le présentateur a maintenant une méthode de rendu `renderDefault()` qui transmet les données à une vue appelée `default`. Les modèles de présentateur peuvent être trouvés dans `app/UI/{PresenterName}/{viewName}.latte`, donc dans ce cas le modèle sera situé dans `app/UI/Home/default.latte`. Dans le modèle, une variable nommée `$posts` est maintenant disponible, qui contient les messages de la base de données.


Modèle .[#toc-template]
=======================

Il existe un modèle générique pour l'ensemble de la page (appelé *layout*, avec l'en-tête, les feuilles de style, le pied de page, ...), puis des modèles spécifiques pour chaque vue (par exemple, pour afficher la liste des articles du blog), qui peuvent remplacer certaines parties du modèle layout.

Par défaut, le modèle de mise en page est situé dans `templates/@layout.latte`, qui contient :

```latte .{file:app/UI/@layout.latte}
...
{include content}
...
```

`{include content}` insère un bloc nommé `content` dans le modèle principal. Vous pouvez le définir dans les modèles de chaque vue. Dans ce cas, nous allons éditer le fichier `Home/default.latte` comme ceci :

```latte .{file:app/UI/Home/default.latte}
{block content}
	Hello World
{/block}
```

Il définit le [bloc |latte:tags#block]*contenu*, qui sera inséré dans la mise en page. Si vous rafraîchissez le navigateur, vous verrez 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 - nous allons modifier le modèle comme suit :

```latte .{file:app/UI/Home/default.latte}
{block content}
	<h1>My blog</h1>

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

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

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

Si vous rafraîchissez votre navigateur, vous verrez la liste de vos articles de blog. La liste n'est pas très fantaisiste ou colorée, alors n'hésitez pas à ajouter quelques [CSS brillants |https://github.com/nette-examples/quickstart/blob/v4.0/www/css/style.css] à `www/css/style.css` et à les lier dans une mise en page :

```latte .{file:app/UI/@layout.latte}
	...
	<link rel="stylesheet" href="{$basePath}/css/style.css">
</head>
...
```

La balise `{foreach}` parcourt tous les messages transmis au modèle dans la variable `$posts` et affiche un morceau de code HTML pour chaque message. Tout comme le ferait un code PHP.

L'élément `|date` est appelé un filtre. Les filtres sont utilisés pour formater la sortie. Ce filtre particulier convertit une date (par exemple `2013-04-12`) en sa forme la plus lisible (`12. 4. 2013`). Le filtre `|truncate` tronque la chaîne de caractères à la longueur maximale spécifiée, et ajoute une ellipse à la fin si la chaîne est tronquée. Comme il s'agit d'un aperçu, il est inutile d'afficher le contenu complet de l'article. D'autres filtres par défaut [peuvent être trouvés dans la documentation |latte:filters] ou vous pouvez créer les vôtres si nécessaire.

Une dernière chose. Nous pouvons rendre le code un peu plus court et donc plus simple. Nous pouvons remplacer les *balises lattes* par des *n:attributs* comme ceci :

```latte .{file:app/UI/Home/default.latte}
{block content}
	<h1>My 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}</div>
	</div>
{/block}
```

Le site `n:foreach`, enveloppe simplement la *div* avec un bloc *foreach* (il fait exactement la même chose que le bloc de code précédent).


Résumé .[#toc-summary]
======================

Nous avons une base de données MySQL très simple contenant quelques articles de blog. L'application se connecte à la base de données et affiche une simple liste des articles.

{{priority: -1}}
{{sitename: Nette Quickstart}}

Page d'accueil du blog

Créons la page d'accueil affichant vos articles récents.

Avant de commencer, vous devez connaître au moins les bases du modèle de conception Modèle-Vue-Présentateur (similaire à MVC) :

  • Modèle – couche de manipulation des données. Elle est complètement séparée du reste de l'application. Elle ne communique qu'avec les présentateurs.
  • View – une couche de définition frontale. Elle rend les données demandées à l'utilisateur en utilisant des modèles.
  • Presenter (ou Controller) – une couche de connexion. Le présentateur relie le modèle et la vue. Il traite les demandes, demande des données au modèle et les transmet ensuite à la vue en cours.

Dans le cas d'une application très simple comme notre blog, la couche Modèle sera en fait constituée uniquement de requêtes à la base de données elle-même – nous n'avons pas besoin de code PHP supplémentaire pour cela. Nous avons seulement besoin de créer les couches Presenter et View. Dans Nette, chaque Presenter a ses propres Views, donc nous allons continuer avec les deux simultanément.

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

Pour stocker les données, nous utiliserons la base de données MySQL car c'est le choix le plus courant parmi les développeurs web. Mais si vous ne l'aimez pas, n'hésitez pas à utiliser une base de données de votre choix.

Préparons la base de données qui stockera nos articles de blog. Nous pouvons commencer très simplement – avec une seule table pour les articles.

Pour créer la base de données, nous pouvons télécharger Adminer, ou vous pouvez utiliser un autre outil de gestion de base de données.

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

Créez une nouvelle table nommée posts et ajoutez ces colonnes :

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

Cela 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 très important d'utiliser la table de stockage InnoDB. Vous en verrez la raison plus tard. Pour l'instant, choisissez simplement cela et soumettez. Vous pouvez cliquer sur Enregistrer maintenant.

Essayez d'ajouter quelques exemples d'articles de blog avant de mettre en œuvre la possibilité d'ajouter de nouveaux articles directement à partir de notre application.

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, quand la base de données est créée et que nous avons des articles dedans, c'est le bon moment pour les afficher sur notre nouvelle page brillante.

Tout d'abord, nous devons indiquer à notre application quelle base de données utiliser. La configuration de la connexion à la base de données est stockée dans config/common.neon. Définissez la connexion DSN et vos informations d'identification. Cela devrait ressembler à ceci :

database:
	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
	user: *enter user name*
	password: *enter password here*

Faites attention à l'indentation lorsque vous modifiez ce fichier. Le format NEON accepte les espaces et les tabulations, mais pas les deux ensemble ! Le fichier de configuration du projet Web utilise les tabulations par défaut.

Injection de la connexion à la base de données

Le présentateur HomePresenter, qui va lister les articles, a besoin d'une connexion à la base de données. Pour la recevoir, écrivez un constructeur comme celui-ci :

<?php
namespace App\UI\Home;

use Nette;

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

	// ...
}

Chargement des messages depuis la base de données

Maintenant, récupérons les messages de la base de données et transmettons-les au modèle, qui rendra ensuite le code HTML. C'est à cela que sert la méthode dite render :

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

Le présentateur a maintenant une méthode de rendu renderDefault() qui transmet les données à une vue appelée default. Les modèles de présentateur peuvent être trouvés dans app/UI/{PresenterName}/{viewName}.latte, donc dans ce cas le modèle sera situé dans app/UI/Home/default.latte. Dans le modèle, une variable nommée $posts est maintenant disponible, qui contient les messages de la base de données.

Modèle

Il existe un modèle générique pour l'ensemble de la page (appelé layout, avec l'en-tête, les feuilles de style, le pied de page, …), puis des modèles spécifiques pour chaque vue (par exemple, pour afficher la liste des articles du blog), qui peuvent remplacer certaines parties du modèle layout.

Par défaut, le modèle de mise en page est situé dans templates/@layout.latte, qui contient :

...
{include content}
...

{include content} insère un bloc nommé content dans le modèle principal. Vous pouvez le définir dans les modèles de chaque vue. Dans ce cas, nous allons éditer le fichier Home/default.latte comme ceci :

{block content}
	Hello World
{/block}

Il définit le bloccontenu, qui sera inséré dans la mise en page. Si vous rafraîchissez le navigateur, vous verrez 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 – nous allons modifier le modèle comme suit :

{block content}
	<h1>My blog</h1>

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

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

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

Si vous rafraîchissez votre navigateur, vous verrez la liste de vos articles de blog. La liste n'est pas très fantaisiste ou colorée, alors n'hésitez pas à ajouter quelques CSS brillants à www/css/style.css et à les lier dans une mise en page :

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

La balise {foreach} parcourt tous les messages transmis au modèle dans la variable $posts et affiche un morceau de code HTML pour chaque message. Tout comme le ferait un code PHP.

L'élément |date est appelé un filtre. Les filtres sont utilisés pour formater la sortie. Ce filtre particulier convertit une date (par exemple 2013-04-12) en sa forme la plus lisible (12. 4. 2013). Le filtre |truncate tronque la chaîne de caractères à la longueur maximale spécifiée, et ajoute une ellipse à la fin si la chaîne est tronquée. Comme il s'agit d'un aperçu, il est inutile d'afficher le contenu complet de l'article. D'autres filtres par défaut peuvent être trouvés dans la documentation ou vous pouvez créer les vôtres si nécessaire.

Une dernière chose. Nous pouvons rendre le code un peu plus court et donc plus simple. Nous pouvons remplacer les balises lattes par des n:attributs comme ceci :

{block content}
	<h1>My 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}</div>
	</div>
{/block}

Le site n:foreach, enveloppe simplement la div avec un bloc foreach (il fait exactement la même chose que le bloc de code précédent).

Résumé

Nous avons une base de données MySQL très simple contenant quelques articles de blog. L'application se connecte à la base de données et affiche une simple liste des articles.