Modelo
À medida que nossa aplicação cresce, logo descobrimos que precisamos realizar operações similares de banco de dados em vários locais e em vários apresentadores, por exemplo, adquirindo os mais novos artigos publicados. Se melhorarmos nossa aplicação adicionando uma bandeira aos artigos para indicar um estado de trabalho em andamento, devemos também passar por todos os locais em nossa aplicação e adicionar uma cláusula de localização para garantir que apenas os artigos acabados sejam selecionados.
Neste ponto, o trabalho direto com o banco de dados torna-se insuficiente e será mais inteligente nos ajudar com uma nova função que retorna artigos publicados. E quando adicionamos outra cláusula posteriormente (por exemplo, para não exibir artigos com uma data futura), editamos nosso código apenas em um lugar.
Colocaremos a função na classe PostFacade
e a chamaremos de getPublicArticles()
.
Vamos criar nossa classe modelo PostFacade
no diretório app/Model/
para cuidar de nossos
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 passamos no Explorer do banco de dados. Isto irá tirar proveito do poder do recipiente DI.
Mudaremos para HomePresenter
que editaremos para nos livrarmos da dependência em
Nette\Database\Explorer
, substituindo-a por uma nova dependência de nossa nova classe.
<?php
namespace App\UI\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 de uso, estamos usando App\Model\PostFacade
, assim podemos encurtar o código PHP para
PostFacade
. Solicitamos este objeto no construtor, escrevemo-lo na propriedade $facade
e o usamos no
método renderDefault.
O último passo restante é ensinar o recipiente DI a produzir este objeto. Isto geralmente é feito adicionando um ponto no
arquivo config/services.neon
na seção services
, dando o nome completo da classe e os parâmetros do
construtor. Isto o registra, por assim dizer, e o objeto é então chamado de **service***. Graças a alguma mágica chamada autowiring, normalmente não precisamos especificar os
parâmetros do construtor porque DI os reconhecerá e os passará automaticamente. Assim, seria suficiente apenas fornecer o nome
da classe:
...
services:
- App\Model\PostFacade
Entretanto, você também não precisa acrescentar esta linha. Na seção search
no início de
services.neon
está definido que todas as classes que terminem com -Facade
ou -Factory
serão pesquisadas automaticamente por DI, o que também é o caso de PostFacade
.
Sumário
A classe PostFacade
pede Nette\Database\Explorer
em um construtor e como esta classe está
registrada no container DI, o container cria esta instância e a passa. DI desta forma cria uma instância
PostFacade
para nós e a passa em uma construtora para a classe HomePresenter que a solicitou. Uma espécie de boneca
Matryoshka de código :) Todos os componentes só pedem o que precisam e não se importam onde e como ele é criado. A criação
é feita por um recipiente DI.
Aqui você pode ler mais sobre injeção de dependência, e sobre configuração.