Nette Documentation Preview

syntax
Üretilen Fabrikalar
*******************

.[perex]
Nette DI, arayüze dayalı olarak otomatik olarak fabrika kodu oluşturabilir, bu da sizi kod yazmaktan kurtarır.

Fabrika, nesneleri oluşturan ve yapılandıran bir sınıftır. Bu nedenle bağımlılıklarını da onlara aktarır. Lütfen fabrikaları kullanmanın belirli bir yolunu tanımlayan ve bu konuyla ilgili olmayan *factory method* tasarım kalıbı ile karıştırmayın.

 [Giriş bölümünde |introduction#factory] böyle bir fabrikanın neye benzediğini göstermiştik:

```php
class ArticleFactory
{
	public function __construct(
		private Nette\Database\Connection $db,
	) {
	}

	public function create(): Article
	{
		return new Article($this->db);
	}
}
```

Nette DI otomatik olarak fabrika kodu üretebilir. Tek yapmanız gereken bir arayüz oluşturmaktır ve Nette DI bir uygulama üretecektir. Arayüz, `create` adında tam olarak bir yönteme sahip olmalı ve bir dönüş türü bildirmelidir:

```php
interface ArticleFactory
{
	function create(): Article;
}
```

Dolayısıyla `ArticleFactory` fabrikasının `Article` nesnelerini oluşturan bir `create` yöntemi vardır. Örneğin `Article` sınıfı aşağıdaki gibi görünebilir:

```php
class Article
{
	public function __construct(
		private Nette\Database\Connection $db,
	) {
	}
}
```

Fabrikayı yapılandırma dosyasına ekleyin:

```neon
services:
	- ArticleFactory
```

Nette DI ilgili fabrika uygulamasını oluşturacaktır.

Böylece, fabrikayı kullanan kodda, nesneyi arayüze göre talep ederiz ve Nette DI üretilen uygulamayı kullanır:

```php
class UserController
{
	public function __construct(
		private ArticleFactory $articleFactory,
	) {
	}

	public function foo()
	{
		// fabrikanın bir nesne oluşturmasına izin verin
		$article = $this->articleFactory->create();
	}
}
```


Parametrelendirilmiş Fabrika .[#toc-parameterized-factory]
==========================================================

`create` fabrika yöntemi, daha sonra kurucuya aktaracağı parametreleri kabul edebilir. Örneğin, `Article` sınıfına bir makale yazarı kimliği ekleyelim:

```php
class Article
{
	public function __construct(
		private Nette\Database\Connection $db,
		private int $authorId,
	) {
	}
}
```

Ayrıca fabrikaya parametre de ekleyeceğiz:

```php
interface ArticleFactory
{
	function create(int $authorId): Article;
}
```

Yapıcıdaki parametre ve fabrikadaki parametre aynı ada sahip olduğundan, Nette DI bunları otomatik olarak geçirecektir.


Gelişmiş Tanım .[#toc-advanced-definition]
==========================================

Tanım, `implement` tuşu kullanılarak çok satırlı olarak da yazılabilir:

```neon
services:
	articleFactory:
		implement: ArticleFactory
```

Bu uzun şekilde yazarken, normal hizmetlerde olduğu gibi `arguments` anahtarındaki kurucu için ek argümanlar ve `setup` kullanarak ek yapılandırma sağlamak mümkündür.

Örnek: `create()` yöntemi `$authorId` parametresini kabul etmeseydi, yapılandırmada `Article` yapıcısına aktarılacak sabit bir değer belirtebilirdik:

```neon
services:
	articleFactory:
		implement: ArticleFactory
		arguments:
			authorId: 123
```

Ya da tersine, eğer `create()` parametre kabul etseydi `$authorId` ancak bu parametre kurucunun bir parçası olmasaydı ve `Article::setAuthorId()` yöntemi tarafından aktarılsaydı, bu parametreye `setup` bölümünde atıfta bulunacaktık:

```neon
services:
	articleFactory:
		implement: ArticleFactory
		setup:
			- setAuthorId($authorId)
```


Accessor .[#toc-accessor]
=========================

Nette, fabrikaların yanı sıra erişimci adı verilen nesneler de üretebilir. Erişimci, DI konteynerinden belirli bir hizmeti döndüren `get()` yöntemine sahip bir nesnedir. Birden fazla `get()` çağrısı her zaman aynı örneği döndürecektir.

Accessor'lar bağımlılıklara tembel yükleme getirir. Hataları özel bir veritabanına kaydeden bir sınıfımız olsun. Eğer veritabanı bağlantısı sınıfın kurucusunda bir bağımlılık olarak aktarılsaydı, bağlantının her zaman oluşturulması gerekirdi, ancak sadece nadiren bir hata ortaya çıktığında kullanılacağından bağlantı çoğunlukla kullanılmadan kalırdı.
Bunun yerine, sınıf bir erişimci geçebilir ve `get()` yöntemi çağrıldığında, yalnızca o zaman veritabanı nesnesi oluşturulur:

Bir accessor nasıl oluşturulur? Sadece bir arayüz yazın ve Nette DI uygulamayı oluşturacaktır. Arayüz, `get` adında tam olarak bir yönteme sahip olmalı ve dönüş türünü bildirmelidir:

```php
interface PDOAccessor
{
	function get(): PDO;
}
```

Erişiciyi, erişicinin döndüreceği hizmetin tanımıyla birlikte yapılandırma dosyasına ekleyin:

```neon
services:
	- PDOAccessor
	- PDO(%dsn%, %user%, %password%)
```

Erişimci, `PDO` türünde bir hizmet döndürür ve yapılandırmada bu türden yalnızca bir hizmet olduğu için erişimci bunu döndürür. Bu türde birden fazla yapılandırılmış hizmet varsa, adını kullanarak hangisinin döndürüleceğini belirtebilirsiniz, örneğin `- PDOAccessor(@db1)`.


Multifactory/Accessor .[#toc-multifactory-accessor]
===================================================
Şimdiye kadar, fabrikalar ve erişimciler yalnızca tek bir nesne oluşturabiliyor veya döndürebiliyordu. Bir erişimci ile birleştirilmiş bir çoklu fabrika da oluşturulabilir. Böyle bir çoklu fabrika sınıfının arayüzü, aşağıdaki gibi adlandırılan birden fazla yöntemden oluşabilir `create<name>()` ve `get<name>()`Örneğin:

```php
interface MultiFactory
{
	function createArticle(): Article;
	function getDb(): PDO;
}
```

Birden fazla oluşturulmuş fabrika ve erişimci geçirmek yerine, yalnızca bir karmaşık çoklu fabrika geçirebilirsiniz.

Alternatif olarak, birden fazla yöntem yerine bir parametre ile `get()` adresini kullanabilirsiniz:

```php
interface MultiFactoryAlt
{
	function get($name): PDO;
}
```

Bu durumda, `MultiFactory::getArticle()`, `MultiFactoryAlt::get('article')` ile aynı şeyi yapar. Ancak, alternatif sözdiziminin birkaç dezavantajı vardır. Hangi `$name` değerlerinin desteklendiği açık değildir ve birden fazla farklı `$name` değeri kullanıldığında dönüş türü arayüzde belirtilemez.


Liste ile Tanımlama .[#toc-definition-with-a-list]
--------------------------------------------------
Bu yol, yapılandırmada birden fazla fabrika tanımlamak için kullanılabilir: .{data-version:3.2.0}

```neon
services:
	- MultiFactory(
		article: Article                      # defines createArticle()
		db: PDO(%dsn%, %user%, %password%)    # defines getDb()
	)
```

Veya fabrika tanımında, bir referans kullanarak mevcut hizmetlere atıfta bulunabiliriz:

```neon
services:
	article: Article
	- PDO(%dsn%, %user%, %password%)
	- MultiFactory(
		article: @article    # defines createArticle()
		db: @\PDO            # defines getDb()
	)
```


Etiketlerle Tanım .[#toc-definition-with-tags]
----------------------------------------------

Bir multifactory'nin nasıl tanımlanacağına dair bir başka seçenek de [etiket |services#Tags] kullanmaktır:

```neon
services:
	- App\Core\RouterFactory::createRouter
	- App\Model\DatabaseAccessor(
		db1: @database.db1.explorer
	)
```

Üretilen Fabrikalar

Nette DI, arayüze dayalı olarak otomatik olarak fabrika kodu oluşturabilir, bu da sizi kod yazmaktan kurtarır.

Fabrika, nesneleri oluşturan ve yapılandıran bir sınıftır. Bu nedenle bağımlılıklarını da onlara aktarır. Lütfen fabrikaları kullanmanın belirli bir yolunu tanımlayan ve bu konuyla ilgili olmayan factory method tasarım kalıbı ile karıştırmayın.

Giriş bölümünde böyle bir fabrikanın neye benzediğini göstermiştik:

class ArticleFactory
{
	public function __construct(
		private Nette\Database\Connection $db,
	) {
	}

	public function create(): Article
	{
		return new Article($this->db);
	}
}

Nette DI otomatik olarak fabrika kodu üretebilir. Tek yapmanız gereken bir arayüz oluşturmaktır ve Nette DI bir uygulama üretecektir. Arayüz, create adında tam olarak bir yönteme sahip olmalı ve bir dönüş türü bildirmelidir:

interface ArticleFactory
{
	function create(): Article;
}

Dolayısıyla ArticleFactory fabrikasının Article nesnelerini oluşturan bir create yöntemi vardır. Örneğin Article sınıfı aşağıdaki gibi görünebilir:

class Article
{
	public function __construct(
		private Nette\Database\Connection $db,
	) {
	}
}

Fabrikayı yapılandırma dosyasına ekleyin:

services:
	- ArticleFactory

Nette DI ilgili fabrika uygulamasını oluşturacaktır.

Böylece, fabrikayı kullanan kodda, nesneyi arayüze göre talep ederiz ve Nette DI üretilen uygulamayı kullanır:

class UserController
{
	public function __construct(
		private ArticleFactory $articleFactory,
	) {
	}

	public function foo()
	{
		// fabrikanın bir nesne oluşturmasına izin verin
		$article = $this->articleFactory->create();
	}
}

Parametrelendirilmiş Fabrika

create fabrika yöntemi, daha sonra kurucuya aktaracağı parametreleri kabul edebilir. Örneğin, Article sınıfına bir makale yazarı kimliği ekleyelim:

class Article
{
	public function __construct(
		private Nette\Database\Connection $db,
		private int $authorId,
	) {
	}
}

Ayrıca fabrikaya parametre de ekleyeceğiz:

interface ArticleFactory
{
	function create(int $authorId): Article;
}

Yapıcıdaki parametre ve fabrikadaki parametre aynı ada sahip olduğundan, Nette DI bunları otomatik olarak geçirecektir.

Gelişmiş Tanım

Tanım, implement tuşu kullanılarak çok satırlı olarak da yazılabilir:

services:
	articleFactory:
		implement: ArticleFactory

Bu uzun şekilde yazarken, normal hizmetlerde olduğu gibi arguments anahtarındaki kurucu için ek argümanlar ve setup kullanarak ek yapılandırma sağlamak mümkündür.

Örnek: create() yöntemi $authorId parametresini kabul etmeseydi, yapılandırmada Article yapıcısına aktarılacak sabit bir değer belirtebilirdik:

services:
	articleFactory:
		implement: ArticleFactory
		arguments:
			authorId: 123

Ya da tersine, eğer create() parametre kabul etseydi $authorId ancak bu parametre kurucunun bir parçası olmasaydı ve Article::setAuthorId() yöntemi tarafından aktarılsaydı, bu parametreye setup bölümünde atıfta bulunacaktık:

services:
	articleFactory:
		implement: ArticleFactory
		setup:
			- setAuthorId($authorId)

Accessor

Nette, fabrikaların yanı sıra erişimci adı verilen nesneler de üretebilir. Erişimci, DI konteynerinden belirli bir hizmeti döndüren get() yöntemine sahip bir nesnedir. Birden fazla get() çağrısı her zaman aynı örneği döndürecektir.

Accessor'lar bağımlılıklara tembel yükleme getirir. Hataları özel bir veritabanına kaydeden bir sınıfımız olsun. Eğer veritabanı bağlantısı sınıfın kurucusunda bir bağımlılık olarak aktarılsaydı, bağlantının her zaman oluşturulması gerekirdi, ancak sadece nadiren bir hata ortaya çıktığında kullanılacağından bağlantı çoğunlukla kullanılmadan kalırdı. Bunun yerine, sınıf bir erişimci geçebilir ve get() yöntemi çağrıldığında, yalnızca o zaman veritabanı nesnesi oluşturulur:

Bir accessor nasıl oluşturulur? Sadece bir arayüz yazın ve Nette DI uygulamayı oluşturacaktır. Arayüz, get adında tam olarak bir yönteme sahip olmalı ve dönüş türünü bildirmelidir:

interface PDOAccessor
{
	function get(): PDO;
}

Erişiciyi, erişicinin döndüreceği hizmetin tanımıyla birlikte yapılandırma dosyasına ekleyin:

services:
	- PDOAccessor
	- PDO(%dsn%, %user%, %password%)

Erişimci, PDO türünde bir hizmet döndürür ve yapılandırmada bu türden yalnızca bir hizmet olduğu için erişimci bunu döndürür. Bu türde birden fazla yapılandırılmış hizmet varsa, adını kullanarak hangisinin döndürüleceğini belirtebilirsiniz, örneğin - PDOAccessor(@db1).

Multifactory/Accessor

Şimdiye kadar, fabrikalar ve erişimciler yalnızca tek bir nesne oluşturabiliyor veya döndürebiliyordu. Bir erişimci ile birleştirilmiş bir çoklu fabrika da oluşturulabilir. Böyle bir çoklu fabrika sınıfının arayüzü, aşağıdaki gibi adlandırılan birden fazla yöntemden oluşabilir create<name>() ve get<name>()Örneğin:

interface MultiFactory
{
	function createArticle(): Article;
	function getDb(): PDO;
}

Birden fazla oluşturulmuş fabrika ve erişimci geçirmek yerine, yalnızca bir karmaşık çoklu fabrika geçirebilirsiniz.

Alternatif olarak, birden fazla yöntem yerine bir parametre ile get() adresini kullanabilirsiniz:

interface MultiFactoryAlt
{
	function get($name): PDO;
}

Bu durumda, MultiFactory::getArticle(), MultiFactoryAlt::get('article') ile aynı şeyi yapar. Ancak, alternatif sözdiziminin birkaç dezavantajı vardır. Hangi $name değerlerinin desteklendiği açık değildir ve birden fazla farklı $name değeri kullanıldığında dönüş türü arayüzde belirtilemez.

Liste ile Tanımlama

Bu yol, yapılandırmada birden fazla fabrika tanımlamak için kullanılabilir:

services:
	- MultiFactory(
		article: Article                      # defines createArticle()
		db: PDO(%dsn%, %user%, %password%)    # defines getDb()
	)

Veya fabrika tanımında, bir referans kullanarak mevcut hizmetlere atıfta bulunabiliriz:

services:
	article: Article
	- PDO(%dsn%, %user%, %password%)
	- MultiFactory(
		article: @article    # defines createArticle()
		db: @\PDO            # defines getDb()
	)

Etiketlerle Tanım

Bir multifactory'nin nasıl tanımlanacağına dair bir başka seçenek de etiket kullanmaktır:

services:
	- App\Core\RouterFactory::createRouter
	- App\Model\DatabaseAccessor(
		db1: @database.db1.explorer
	)