Model
Uygulama büyüdükçe, yakında farklı yerlerde, farklı presenter'larda, veritabanıyla benzer işlemler yapmamız gerektiğini fark edeceğiz. Örneğin, en son yayınlanan makaleleri almak. Uygulamayı, örneğin makalelere taslak olup olmadıklarını belirten bir bayrak ekleyerek geliştirirsek, o zaman uygulamada makalelerin veritabanından alındığı tüm yerleri gözden geçirmeli ve yalnızca taslak olmayan makalelerin seçilmesi için where koşulunu eklemeliyiz.
Bu noktada, veritabanıyla doğrudan çalışmak yetersiz hale gelir ve bize yayınlanmış makaleleri döndürecek yeni bir fonksiyonla yardım etmek daha akıllıca olacaktır. Ve daha sonra başka bir koşul eklediğimizde, örneğin gelecekteki bir tarihe sahip makalelerin gösterilmemesi gerektiğini, kodu yalnızca tek bir yerde düzenleriz.
Fonksiyonu örneğin PostFacade
sınıfına yerleştireceğiz ve getPublicArticles()
olarak
adlandıracağız.
app/Model/
dizininde, makalelerimizle ilgilenecek olan model sınıfımız
PostFacade
'i oluşturacağız:
<?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');
}
}
Sınıfta, yapıcı aracılığıyla veritabanı Explorer'ı aktarmasını isteyeceğiz. Böylece DI konteynerinin gücünden yararlanacağız.
HomePresenter
'a geçeceğiz, onu Nette\Database\Explorer
bağımlılığından kurtulacak ve yeni
sınıfımıza olan yeni bağımlılıkla değiştirecek şekilde düzenleyeceğiz.
<?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);
}
}
Use bölümünde App\Model\PostFacade
var, bu yüzden PHP kodundaki yazımı PostFacade
olarak
kısaltabiliriz. Bu nesneyi yapıcıda isteyeceğiz, $facade
özelliğine yazacağız ve renderDefault metodunda
kullanacağız.
Geriye kalan son adım, DI konteynerine bu nesneyi nasıl üreteceğini öğretmektir. Bu genellikle
config/services.neon
dosyasındaki services
bölümüne bir madde işareti ekleyerek, sınıfın tam
adını ve yapıcı parametrelerini belirterek yapılır. Böylece onu kaydederiz ve nesne daha sonra servis olarak
adlandırılır. Autowiring adlı sihir sayesinde, çoğu
zaman yapıcı parametrelerini belirtmemiz gerekmez, çünkü DI onları kendi başına tanır ve aktarır. Bu nedenle yalnızca
sınıfın adını belirtmek yeterli olacaktır:
...
services:
- App\Model\PostFacade
Ancak, bu satırı eklemeniz bile gerekmez. services.neon
başındaki search
bölümünde,
-Facade
veya -Factory
ile biten tüm sınıfların DI tarafından kendi kendine bulunacağı
tanımlanmıştır, bu da PostFacade
durumu için geçerlidir.
Özet
PostFacade
sınıfı, yapıcıda Nette\Database\Explorer
'ın aktarılmasını ister ve bu sınıf DI
konteynerinde kayıtlı olduğundan, konteyner bu örneği oluşturur ve aktarır. DI bizim için PostFacade
örneğini bu şekilde oluşturur ve onu isteyen HomePresenter sınıfının yapıcısına aktarır. Böyle bir matruşka. :)
Herkes sadece ne istediğini söyler ve neyin nerede ve nasıl yaratıldığıyla ilgilenmez. Oluşturma işini DI konteyneri
halleder.
Burada dependency injection ve yapılandırma hakkında daha fazla bilgi edinebilirsiniz.