Modelo
À medida que a aplicação cresce, logo descobriremos que em diferentes lugares, em diferentes presenters, precisamos realizar operações semelhantes com o banco de dados. Por exemplo, obter os artigos publicados mais recentemente. Se melhorarmos a aplicação, por exemplo, adicionando um sinalizador aos artigos para indicar se estão em rascunho, teremos que percorrer todos os lugares na aplicação onde os artigos são obtidos do banco de dados e adicionar uma condição where para selecionar apenas os artigos não rascunhados.
Nesse momento, o trabalho direto com o banco de dados se torna insuficiente e será mais conveniente usar uma nova função que nos retornará os artigos publicados. E quando adicionarmos outra condição posteriormente, por exemplo, que artigos com data futura não devem ser exibidos, modificaremos o código em apenas um lugar.
Colocaremos a função, por exemplo, na classe PostFacade
e a chamaremos de getPublicArticles()
.
No diretório app/Model/
, criaremos nossa classe de modelo PostFacade
, que cuidará dos artigos:
<?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');
}
}
Na classe, solicitaremos a passagem do Database Explorer através do construtor. Aproveitaremos assim o poder do contêiner de DI.
Mudaremos para o HomePresenter
, que modificaremos para nos livrarmos da dependência de
Nette\Database\Explorer
e a substituiremos pela nova dependência de nossa nova 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);
}
}
Na seção use, temos App\Model\PostFacade
, então podemos encurtar a escrita no código PHP para
PostFacade
. Solicitaremos este objeto no construtor, o escreveremos na propriedade $facade
e
o usaremos no método renderDefault.
Resta o último passo, que é ensinar o contêiner de DI a produzir este objeto. Isso geralmente é feito adicionando um
marcador ao arquivo config/services.neon
na seção services
, indicando o nome completo da classe e os
parâmetros do construtor. Assim, o registramos e o objeto é então chamado de serviço. Graças à mágica chamada autowiring, geralmente não precisamos especificar os
parâmetros do construtor, pois o DI os reconhece e os passa automaticamente. Bastaria, portanto, indicar apenas o nome da
classe:
...
services:
- App\Model\PostFacade
No entanto, você nem precisa adicionar esta linha. Na seção search
no início de services.neon
,
está definido que todas as classes terminadas com a palavra -Facade
ou -Factory
serão encontradas
automaticamente pelo DI, o que também é o caso de PostFacade
.
Resumo
A classe PostFacade
solicita a passagem de Nette\Database\Explorer
em seu construtor e, como esta
classe está registrada no contêiner de DI, o contêiner cria esta instância e a passa. O DI cria assim para nós a instância
de PostFacade
e a passa no construtor para a classe HomePresenter, que a solicitou. É como uma matriosca. :) Todos
apenas dizem o que querem e não se preocupam onde e como algo é criado. O contêiner de DI cuida da criação.
Aqui você pode ler mais sobre injeção de dependência e configuração.