Modèle
Au fur et à mesure que l'application grandit, nous découvrirons bientôt que nous devons effectuer des opérations similaires avec la base de données à différents endroits, dans différents presenters. Par exemple, obtenir les derniers articles publiés. Si nous améliorons l'application, par exemple en ajoutant un indicateur aux articles pour savoir s'ils sont en cours de rédaction, nous devons également parcourir tous les endroits de l'application où les articles sont récupérés de la base de données et ajouter une condition where pour ne sélectionner que les articles non rédigés.
À ce moment-là, le travail direct avec la base de données devient insuffisant et il sera plus pratique de s'aider d'une nouvelle fonction qui nous renverra les articles publiés. Et si nous ajoutons plus tard une autre condition, par exemple que les articles avec une date future ne doivent pas être affichés, nous ne modifierons le code qu'à un seul endroit.
Nous placerons la fonction par exemple dans la classe PostFacade
et l'appellerons
getPublicArticles()
.
Dans le répertoire app/Model/
, nous créons notre classe de modèle PostFacade
, qui s'occupera des
articles :
<?php
namespace App\Model;
use Nette;
final class PostFacade
{
public function __construct(
private Nette\Database\Explorer $database,
) {
}
public function getPublicArticles()
{
return $this->database
->table('posts')
->where('created_at < ', new \DateTime)
->order('created_at DESC');
}
}
Dans la classe, nous nous faisons passer l'Explorer de base de données Nette\Database\Explorer via le constructeur. Nous utilisons ainsi la puissance du conteneur DI.
Nous passons à HomePresenter
, que nous modifions en nous débarrassant de la dépendance à
Nette\Database\Explorer
et en la remplaçant par une nouvelle dépendance à notre nouvelle classe.
<?php
namespace App\Presentation\Home;
use App\Model\PostFacade;
use Nette;
final class HomePresenter extends Nette\Application\UI\Presenter
{
public function __construct(
private PostFacade $facade,
) {
}
public function renderDefault(): void
{
$this->template->posts = $this->facade
->getPublicArticles()
->limit(5);
}
}
Dans la section use, nous avons App\Model\PostFacade
, nous pouvons donc raccourcir l'écriture dans le code PHP à
PostFacade
. Nous demandons cet objet dans le constructeur, l'écrivons dans la propriété $facade
et
l'utilisons dans la méthode renderDefault.
Il reste une dernière étape, apprendre au conteneur DI à fabriquer cet objet. Cela se fait généralement en ajoutant un
tiret dans le fichier config/services.neon
dans la section services
, en indiquant le nom complet de la
classe et les paramètres du constructeur. Nous l'enregistrons ainsi et l'objet est alors appelé service. Grâce à la
magie appelée autowiring, nous n'avons généralement pas
besoin d'indiquer les paramètres du constructeur, car DI les reconnaît et les transmet lui-même. Il suffirait donc d'indiquer
uniquement le nom de la classe :
...
services:
- App\Model\PostFacade
Cependant, vous n'avez même pas besoin d'ajouter cette ligne. Dans la section search
au début de
services.neon
, il est défini que toutes les classes se terminant par le mot -Facade
ou
-Factory
sont recherchées automatiquement par DI, ce qui est également le cas de PostFacade
.
Résumé
La classe PostFacade
demande dans son constructeur la transmission de Nette\Database\Explorer
et
comme cette classe est enregistrée dans le conteneur DI, le conteneur crée cette instance et la transmet. DI crée ainsi pour
nous l'instance de PostFacade
et la transmet dans le constructeur à la classe HomePresenter, qui l'a demandée. Une
sorte de matriochka. :) Tout le monde dit simplement ce qu'il veut et ne se soucie pas de savoir où et comment quoi que ce soit
est créé. Le conteneur DI s'occupe de la création.
Ici, vous pouvez en lire plus sur l'injection de dépendances et la configuration.