Nette Documentation Preview

syntax
Servis Tanımları
****************

.[perex]
Yapılandırma, DI container'a tek tek servisleri nasıl oluşturacağını ve onları bağımlılıklarıyla nasıl bağlayacağını anlattığımız yerdir. Nette bunu yapmanın çok anlaşılır ve şık bir yolunu sunar.

NEON yapılandırma dosyasındaki `services` bölümü, kendi servislerimizi ve yapılandırmalarını tanımladığımız yerdir. `PDO` sınıfının bir örneğini temsil eden `database` adlı bir servisi tanımlayan basit bir örneğe bakalım:

```neon
services:
	database: PDO('sqlite::memory:')
```

Yukarıdaki yapılandırma, [DI container|container] içinde şu factory metodunu doğurur:

```php
public function createServiceDatabase(): PDO
{
	return new PDO('sqlite::memory:');
}
```

Servis adları, yapılandırma dosyasının başka yerlerinde `@servisAdı` biçimiyle onlara başvurmayı sağlar. Servise ad vermeye gerek yoksa yalnızca bir madde imi (`-`) kullanabiliriz:

```neon
services:
	- PDO('sqlite::memory:')
```

DI container'dan bir servis almak için, parametre olarak servis adını alan `getService()` metodunu ya da servis türünü alan `getByType()` metodunu kullanabiliriz:

```php
$database = $container->getService('database');
$database = $container->getByType(PDO::class);
```


Servis Oluşturma
================

Genellikle bir servisi yalnızca belirli bir sınıfı örnekleyerek oluştururuz. Örneğin:

```neon
services:
	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
```

Yapılandırmayı ek anahtarlarla genişletmemiz gerekirse, tanım birden çok satıra bölünebilir:

```neon
services:
	database:
		create: PDO('sqlite::memory:')
		setup: ...
```

`create` anahtarının `factory` adında bir takma adı vardır; iki biçim de yaygın olarak kullanılır. Yine de `create` kullanmanızı öneririz.

Yapıcının ya da factory metodunun argümanları, alternatif olarak `arguments` anahtarıyla da belirtilebilir:

```neon
services:
	database:
		create: PDO
		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]
```

Servisler yalnızca sınıf örneklemesiyle oluşturulmak zorunda değildir; statik metotların ya da başka servislerin metotlarının çağrılmasının sonucu da olabilirler:

```neon
services:
	database: DatabaseFactory::create()
	router: @routerFactory::create()
```

Basitlik için `->` yerine `::` kullanıldığına dikkat edin, bkz. [#İfade Dili]. Şu factory metotları üretilecek:

```php
public function createServiceDatabase(): PDO
{
	return DatabaseFactory::create();
}

public function createServiceRouter(): RouteList
{
	return $this->getService('routerFactory')->create();
}
```

DI container'ın, oluşturulan servisin türünü bilmesi gerekir. Servisi, dönüş türü belirtilmemiş bir metotla oluşturuyorsak, bu türü yapılandırmada açıkça bildirmeliyiz:

```neon
services:
	database:
		create: DatabaseFactory::create()
		type: PDO
```


Argümanlar
==========

Argümanları yapıcılara ve metotlara, PHP'nin kendisinde yapıldığına çok benzer biçimde aktarırız:

```neon
services:
	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)
```

Daha iyi okunurluk için argümanları ayrı satırlarda sıralayabiliriz. Bu durumda virgül kullanmak isteğe bağlı olur:

```neon
services:
	database: PDO(
		'mysql:host=127.0.0.1;dbname=test'
		root
		secret
	)
```

Argümanları adlandırabilir ve böylece sıralarıyla uğraşmaktan kurtulabilirsiniz:

```neon
services:
	database: PDO(
		username: root
		password: secret
		dsn: 'mysql:host=127.0.0.1;dbname=test'
	)
```

Belirli argümanları atlayıp varsayılan değerlerini kullanmak ya da [autowiring|autowiring] ile bir servisin enjekte edilmesini istiyorsanız, alt çizgi (`_`) kullanın:

```neon
services:
	foo: Foo(_, %appDir%)
```

Argümanlar servisleri, parametreleri ve daha fazlasını içerebilir, bkz. [#İfade Dili].


Setup
=====

`setup` bölümünde, servis oluşturulurken çağrılması gereken metotları tanımlarız.

```neon
services:
	database:
		create: PDO(%dsn%, %user%, %password%)
		setup:
			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
```

Bu PHP'de şöyle görünürdü:

```php
public function createServiceDatabase(): PDO
{
	$service = new PDO('...', '...', '...');
	$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
	return $service;
}
```

Metot çağrılarının yanı sıra özelliklere değer de atanabilir. Dizilere öğe eklemek de desteklenir; bu, NEON söz dizimiyle çakışmayı önlemek için dizi erişiminin tırnak içine alınmasını gerektirir:

```neon
services:
	foo:
		create: Foo
		setup:
			- $value = 123
			- '$onClick[]' = [@bar, clickHandler]
```

Bu, PHP kodunda şöyle görünürdü:

```php
public function createServiceFoo(): Foo
{
	$service = new Foo;
	$service->value = 123;
	$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
	return $service;
}
```

Ancak setup içinde statik metotları ya da başka servislerin metotlarını da çağırabilirsiniz. Geçerli servisin kendisini argüman olarak aktarmanız gerekiyorsa, ona `@self` ile başvurun:

```neon
services:
	foo:
		create: Foo
		setup:
			- My\Helpers::initializeFoo(@self)
			- @anotherService::setFoo(@self)
```

Basitlik için `->` yerine `::` kullanıldığına dikkat edin, bkz. [#İfade Dili]. Şöyle bir factory metodu üretilecek:

```php
public function createServiceFoo(): Foo
{
	$service = new Foo;
	My\Helpers::initializeFoo($service);
	$this->getService('anotherService')->setFoo($service);
	return $service;
}
```


İfade Dili
==========

Nette DI son derece zengin bir ifade dili sunar; bu dille neredeyse her şeyi tanımlayabiliriz. Yapılandırma dosyalarında [parametreleri |configuration#Parametreler] kullanabiliriz:

```neon
# parametre
%wwwDir%

# bir anahtarın altındaki parametrenin değeri
%mailer.user%

# dize içinde parametre
'%wwwDir%/images'
```

Ayrıca nesne oluşturabilir, metot ve fonksiyon çağırabiliriz:

```neon
# nesne oluştur
DateTime()

# statik metot çağır
Collator::create(%locale%)

# PHP fonksiyonu çağır
::getenv(DB_USER)
```

Servislere ya adlarıyla ya da türleriyle başvurabiliriz:

```neon
# ada göre servis
@database

# türe göre servis
@Nette\Database\Connection
```

First-class callable söz dizimini kullanın: .{data-version:3.2.0}

```neon
# callback oluşturur, [@user, logout] ile eşdeğerdir
@user::logout(...)
```

Sabitleri kullanın:

```neon
# sınıf sabiti
FilesystemIterator::SKIP_DOTS

# genel sabiti PHP'nin constant() fonksiyonuyla al
::constant(\PHP_VERSION)
```

Bir servisin public özelliklerine ve sabitlerine `@service::member` ile erişin. Adın bir özelliğe mi yoksa bir sabite mi çözüleceğine ilk harfi karar verir: küçük harfle başlaması public bir özellik, büyük harfle başlaması bir sabit demektir:

```neon
# bir servisin public özelliği (küçük harfle başlar)
@settings::apiUrl

# bir servisin sınıf sabiti (büyük harfle başlar)
@settings::Version
```

Metot çağrıları, tıpkı PHP'deki gibi zincirlenebilir. Basitlik için `->` yerine `::` kullanılır:

```neon
DateTime()::format('Y-m-d')
# PHP: (new DateTime())->format('Y-m-d')

@http.request::getUrl()::getHost()
# PHP: $this->getService('http.request')->getUrl()->getHost()
```

Bu ifadeleri her yerde kullanabilirsiniz: [servis oluştururken |#Servis Oluşturma], [argümanlarda |#Argümanlar], [setup |#Setup] bölümünde ya da [parametrelerde |configuration#Parametreler]:

```neon
parameters:
	ipAddress: @http.request::getRemoteAddress()

services:
	database:
		create: DatabaseFactory::create( @anotherService::getDsn() )
		setup:
			- initialize( ::getenv('DB_USER') )
```


Özel Fonksiyonlar
-----------------

Yapılandırma dosyalarında şu özel fonksiyonları kullanabilirsiniz:

- `not()` bir değeri tersine çevirir
- `bool()`, `int()`, `float()`, `string()` belirtilen türe kayıpsız dönüştürme .{data-version:3.0.5}
- `typed()` belirtilen türdeki tüm servislerden oluşan bir dizi oluşturur
- `tagged()` verilen etikete sahip tüm servislerden oluşan bir dizi oluşturur

```neon
services:
	- Foo(
		id: int(::getenv('ProjectId'))
		productionMode: not(%debugMode%)
	)
```

`(int)` gibi standart PHP dönüşümlerinin aksine, kayıpsız dönüştürme sayısal olmayan değerlerde istisna fırlatır.

`typed()` fonksiyonu, belirtilen türdeki (sınıf ya da arayüz) tüm servislerden oluşan bir dizi oluşturur. Autowiring'i kapatılmış servisleri dışarıda bırakır. Virgülle ayırarak birden çok tür de belirtilebilir.

```neon
services:
	- BarsDependent( typed(Bar) )
```

Belirli bir türdeki servislerden oluşan bir dizi, [autowiring |autowiring#Servis Koleksiyonu] ile argüman olarak otomatik de aktarılabilir.

`tagged()` fonksiyonu ise belirli bir etikete sahip tüm servislerden oluşan bir dizi oluşturur. Burada da virgülle ayırarak birden çok etiket belirtebilirsiniz.

```neon
services:
	- LoggersDependent( tagged(logger) )
```


Autowiring
==========

`autowired` anahtarı, belirli bir servisin autowiring davranışını etkilemenizi sağlar. Ayrıntılar için [autowiring bölümüne|autowiring] bakın.

```neon
services:
	foo:
		create: Foo
		autowired: false     # foo servisi autowiring'den çıkarılır
```


Tembel Servisler .{data-version:3.2.4}
======================================

Tembel yükleme, bir servisin oluşturulmasını gerçekten gerekene dek erteleyen bir tekniktir. Genel yapılandırmada tüm servisler için [tembel oluşturmayı |configuration#Tembel Servisler] tek seferde açabilirsiniz. Tek tek servislerde bu davranışı geçersiz kılabilirsiniz:

```neon
services:
	foo:
		create: Foo
		lazy: false
```

Bir servis tembel olarak tanımlandığında, onu DI container'dan istediğimizde özel bir proxy nesnesi alırız. Bu proxy, gerçek servisle aynı görünür ve aynı davranır, ama asıl başlatma (yapıcının ve setup çağrılarının çalıştırılması) yalnızca metotlarından ya da özelliklerinden birine ilk erişimde gerçekleşir.

Servis daha sonra oluşturulduğundan, yapılandırmasındaki hataların da daha sonra ortaya çıkacağını unutmayın. Örneğin yanlış veritabanı kimlik bilgileri, uygulama başlarken değil, ilk sorguda kendini gösterir.

Tembel oluşturma, döngüsel bağımlılıkları da, yani A servisinin B'yi, B'nin de aynı anda A'yı gerektirdiği durumu hafifletir. Bu olmadan container `Circular reference detected` hatasını bildirir. Tembel proxy'yle A servisi yalnızca B servisinin bir proxy'sini alır; o da gerçekten kullanıldığında, yani A zaten varken kendini başlatır. Yine de döngüsel bağımlılık kusurlu bir tasarımın işaretidir ve ondan kurtulmak daha iyidir.

.[note]
Tembel yükleme PHP 8.4 ya da daha yenisini gerektirir ve yalnızca doğrudan sınıf örneklenerek oluşturulan servislerde çalışır (örneğin `create: Foo`), factory metoduyla oluşturulanlarda çalışmaz. Sonunda PHP'nin iç sınıflarından birini genişleten sınıflarda da kullanılamaz. Tembel yükleme uygulanamadığında `lazy: true` bayrağı sessizce yok sayılır.


Etiketler
=========

Etiketler, servislere ek bilgi eklemeye yarar. Bir servise bir ya da daha çok etiket atayabilirsiniz:

```neon
services:
	foo:
		create: Foo
		tags:
			- cached
```

Etiketler değer de taşıyabilir:

```neon
services:
	foo:
		create: Foo
		tags:
			logger: monolog.logger.event
```

Belirli etiketlerle ilişkili tüm servisleri almak için `tagged()` fonksiyonunu kullanabilirsiniz:

```neon
services:
	- LoggersDependent( tagged(logger) )
```

DI container içinde, belirli bir etikete sahip tüm servislerin adlarını `findByTag()` metoduyla alabilirsiniz:

```php
$names = $container->findByTag('logger');
// $names, anahtarları servis adları, değerleri etiket değerleri olan bir dizidir
// örneğin ['foo' => 'monolog.logger.event', ...]
```


Inject Kipi
===========

`inject: true` bayrağı, [Inject |best-practices:inject-method-attribute#Inject Attribute'ları] attribute'una sahip public özellikler ve [inject*() |best-practices:inject-method-attribute#inject*() Metotları] metotları üzerinden bağımlılık enjeksiyonunu etkinleştirir.

```neon
services:
	articles:
		create: App\Model\Articles
		inject: true
```

Varsayılan olarak `inject` kipi yalnızca presenter'larda açıktır.


Servis Değişiklikleri
=====================

DI container, yerleşik ya da [kullanıcı extension'larıyla|extensions] eklenmiş pek çok servis tutar. Bu var olan servislerin tanımlarını doğrudan yapılandırmada değiştirebilirsiniz. Örneğin varsayılanı `Nette\Application\Application` olan `application.application` servisinin sınıfını başka bir sınıfla değiştirebilirsiniz:

```neon
services:
	application.application:
		create: MyApplication
		alteration: true
```

`alteration` bayrağı, var olan bir servisi yalnızca değiştirdiğimizi gösterir. Aynı zamanda bir güvence görevi görür: değiştirilen servis yoksa derleme istisnayla başarısız olur.

Setup'ı da tamamlayabiliriz:

```neon
services:
	application.application:
		create: MyApplication
		alteration: true
		setup:
			- '$onStartup[]' = [@resource, init]
```

Bir servisi iç adıyla belirtmek zorunda değilsiniz; onun yerine türüyle başvurabilirsiniz. Önceki örnek şöyle de yazılabilir:

```neon
services:
	@Nette\Application\Application:
		create: MyApplication
```

Bir servisi değiştirirken özgün argümanları, setup öğelerini ya da etiketleri `reset` anahtarıyla kaldırmak isteyebiliriz:

```neon
services:
	application.application:
		create: MyApplication
		alteration: true
		reset:
			arguments: true
			setup: true
			tags: true
```

Bir extension tarafından eklenen bir servisi kaldırmak isterseniz bunu şöyle yapabilirsiniz:

```neon
services:
	cache.journal: false
```

Servis Tanımları

Yapılandırma, DI container'a tek tek servisleri nasıl oluşturacağını ve onları bağımlılıklarıyla nasıl bağlayacağını anlattığımız yerdir. Nette bunu yapmanın çok anlaşılır ve şık bir yolunu sunar.

NEON yapılandırma dosyasındaki services bölümü, kendi servislerimizi ve yapılandırmalarını tanımladığımız yerdir. PDO sınıfının bir örneğini temsil eden database adlı bir servisi tanımlayan basit bir örneğe bakalım:

services:
	database: PDO('sqlite::memory:')

Yukarıdaki yapılandırma, DI container içinde şu factory metodunu doğurur:

public function createServiceDatabase(): PDO
{
	return new PDO('sqlite::memory:');
}

Servis adları, yapılandırma dosyasının başka yerlerinde @servisAdı biçimiyle onlara başvurmayı sağlar. Servise ad vermeye gerek yoksa yalnızca bir madde imi (-) kullanabiliriz:

services:
	- PDO('sqlite::memory:')

DI container'dan bir servis almak için, parametre olarak servis adını alan getService() metodunu ya da servis türünü alan getByType() metodunu kullanabiliriz:

$database = $container->getService('database');
$database = $container->getByType(PDO::class);

Servis Oluşturma

Genellikle bir servisi yalnızca belirli bir sınıfı örnekleyerek oluştururuz. Örneğin:

services:
	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)

Yapılandırmayı ek anahtarlarla genişletmemiz gerekirse, tanım birden çok satıra bölünebilir:

services:
	database:
		create: PDO('sqlite::memory:')
		setup: ...

create anahtarının factory adında bir takma adı vardır; iki biçim de yaygın olarak kullanılır. Yine de create kullanmanızı öneririz.

Yapıcının ya da factory metodunun argümanları, alternatif olarak arguments anahtarıyla da belirtilebilir:

services:
	database:
		create: PDO
		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]

Servisler yalnızca sınıf örneklemesiyle oluşturulmak zorunda değildir; statik metotların ya da başka servislerin metotlarının çağrılmasının sonucu da olabilirler:

services:
	database: DatabaseFactory::create()
	router: @routerFactory::create()

Basitlik için -> yerine :: kullanıldığına dikkat edin, bkz. İfade Dili. Şu factory metotları üretilecek:

public function createServiceDatabase(): PDO
{
	return DatabaseFactory::create();
}

public function createServiceRouter(): RouteList
{
	return $this->getService('routerFactory')->create();
}

DI container'ın, oluşturulan servisin türünü bilmesi gerekir. Servisi, dönüş türü belirtilmemiş bir metotla oluşturuyorsak, bu türü yapılandırmada açıkça bildirmeliyiz:

services:
	database:
		create: DatabaseFactory::create()
		type: PDO

Argümanlar

Argümanları yapıcılara ve metotlara, PHP'nin kendisinde yapıldığına çok benzer biçimde aktarırız:

services:
	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)

Daha iyi okunurluk için argümanları ayrı satırlarda sıralayabiliriz. Bu durumda virgül kullanmak isteğe bağlı olur:

services:
	database: PDO(
		'mysql:host=127.0.0.1;dbname=test'
		root
		secret
	)

Argümanları adlandırabilir ve böylece sıralarıyla uğraşmaktan kurtulabilirsiniz:

services:
	database: PDO(
		username: root
		password: secret
		dsn: 'mysql:host=127.0.0.1;dbname=test'
	)

Belirli argümanları atlayıp varsayılan değerlerini kullanmak ya da autowiring ile bir servisin enjekte edilmesini istiyorsanız, alt çizgi (_) kullanın:

services:
	foo: Foo(_, %appDir%)

Argümanlar servisleri, parametreleri ve daha fazlasını içerebilir, bkz. İfade Dili.

Setup

setup bölümünde, servis oluşturulurken çağrılması gereken metotları tanımlarız.

services:
	database:
		create: PDO(%dsn%, %user%, %password%)
		setup:
			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)

Bu PHP'de şöyle görünürdü:

public function createServiceDatabase(): PDO
{
	$service = new PDO('...', '...', '...');
	$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
	return $service;
}

Metot çağrılarının yanı sıra özelliklere değer de atanabilir. Dizilere öğe eklemek de desteklenir; bu, NEON söz dizimiyle çakışmayı önlemek için dizi erişiminin tırnak içine alınmasını gerektirir:

services:
	foo:
		create: Foo
		setup:
			- $value = 123
			- '$onClick[]' = [@bar, clickHandler]

Bu, PHP kodunda şöyle görünürdü:

public function createServiceFoo(): Foo
{
	$service = new Foo;
	$service->value = 123;
	$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
	return $service;
}

Ancak setup içinde statik metotları ya da başka servislerin metotlarını da çağırabilirsiniz. Geçerli servisin kendisini argüman olarak aktarmanız gerekiyorsa, ona @self ile başvurun:

services:
	foo:
		create: Foo
		setup:
			- My\Helpers::initializeFoo(@self)
			- @anotherService::setFoo(@self)

Basitlik için -> yerine :: kullanıldığına dikkat edin, bkz. İfade Dili. Şöyle bir factory metodu üretilecek:

public function createServiceFoo(): Foo
{
	$service = new Foo;
	My\Helpers::initializeFoo($service);
	$this->getService('anotherService')->setFoo($service);
	return $service;
}

İfade Dili

Nette DI son derece zengin bir ifade dili sunar; bu dille neredeyse her şeyi tanımlayabiliriz. Yapılandırma dosyalarında parametreleri kullanabiliriz:

# parametre
%wwwDir%

# bir anahtarın altındaki parametrenin değeri
%mailer.user%

# dize içinde parametre
'%wwwDir%/images'

Ayrıca nesne oluşturabilir, metot ve fonksiyon çağırabiliriz:

# nesne oluştur
DateTime()

# statik metot çağır
Collator::create(%locale%)

# PHP fonksiyonu çağır
::getenv(DB_USER)

Servislere ya adlarıyla ya da türleriyle başvurabiliriz:

# ada göre servis
@database

# türe göre servis
@Nette\Database\Connection

First-class callable söz dizimini kullanın:

# callback oluşturur, [@user, logout] ile eşdeğerdir
@user::logout(...)

Sabitleri kullanın:

# sınıf sabiti
FilesystemIterator::SKIP_DOTS

# genel sabiti PHP'nin constant() fonksiyonuyla al
::constant(\PHP_VERSION)

Bir servisin public özelliklerine ve sabitlerine @service::member ile erişin. Adın bir özelliğe mi yoksa bir sabite mi çözüleceğine ilk harfi karar verir: küçük harfle başlaması public bir özellik, büyük harfle başlaması bir sabit demektir:

# bir servisin public özelliği (küçük harfle başlar)
@settings::apiUrl

# bir servisin sınıf sabiti (büyük harfle başlar)
@settings::Version

Metot çağrıları, tıpkı PHP'deki gibi zincirlenebilir. Basitlik için -> yerine :: kullanılır:

DateTime()::format('Y-m-d')
# PHP: (new DateTime())->format('Y-m-d')

@http.request::getUrl()::getHost()
# PHP: $this->getService('http.request')->getUrl()->getHost()

Bu ifadeleri her yerde kullanabilirsiniz: servis oluştururken, argümanlarda, setup bölümünde ya da parametrelerde:

parameters:
	ipAddress: @http.request::getRemoteAddress()

services:
	database:
		create: DatabaseFactory::create( @anotherService::getDsn() )
		setup:
			- initialize( ::getenv('DB_USER') )

Özel Fonksiyonlar

Yapılandırma dosyalarında şu özel fonksiyonları kullanabilirsiniz:

  • not() bir değeri tersine çevirir
  • bool(), int(), float(), string() belirtilen türe kayıpsız dönüştürme
  • typed() belirtilen türdeki tüm servislerden oluşan bir dizi oluşturur
  • tagged() verilen etikete sahip tüm servislerden oluşan bir dizi oluşturur
services:
	- Foo(
		id: int(::getenv('ProjectId'))
		productionMode: not(%debugMode%)
	)

(int) gibi standart PHP dönüşümlerinin aksine, kayıpsız dönüştürme sayısal olmayan değerlerde istisna fırlatır.

typed() fonksiyonu, belirtilen türdeki (sınıf ya da arayüz) tüm servislerden oluşan bir dizi oluşturur. Autowiring'i kapatılmış servisleri dışarıda bırakır. Virgülle ayırarak birden çok tür de belirtilebilir.

services:
	- BarsDependent( typed(Bar) )

Belirli bir türdeki servislerden oluşan bir dizi, autowiring ile argüman olarak otomatik de aktarılabilir.

tagged() fonksiyonu ise belirli bir etikete sahip tüm servislerden oluşan bir dizi oluşturur. Burada da virgülle ayırarak birden çok etiket belirtebilirsiniz.

services:
	- LoggersDependent( tagged(logger) )

Autowiring

autowired anahtarı, belirli bir servisin autowiring davranışını etkilemenizi sağlar. Ayrıntılar için autowiring bölümüne bakın.

services:
	foo:
		create: Foo
		autowired: false     # foo servisi autowiring'den çıkarılır

Tembel Servisler

Tembel yükleme, bir servisin oluşturulmasını gerçekten gerekene dek erteleyen bir tekniktir. Genel yapılandırmada tüm servisler için tembel oluşturmayı tek seferde açabilirsiniz. Tek tek servislerde bu davranışı geçersiz kılabilirsiniz:

services:
	foo:
		create: Foo
		lazy: false

Bir servis tembel olarak tanımlandığında, onu DI container'dan istediğimizde özel bir proxy nesnesi alırız. Bu proxy, gerçek servisle aynı görünür ve aynı davranır, ama asıl başlatma (yapıcının ve setup çağrılarının çalıştırılması) yalnızca metotlarından ya da özelliklerinden birine ilk erişimde gerçekleşir.

Servis daha sonra oluşturulduğundan, yapılandırmasındaki hataların da daha sonra ortaya çıkacağını unutmayın. Örneğin yanlış veritabanı kimlik bilgileri, uygulama başlarken değil, ilk sorguda kendini gösterir.

Tembel oluşturma, döngüsel bağımlılıkları da, yani A servisinin B'yi, B'nin de aynı anda A'yı gerektirdiği durumu hafifletir. Bu olmadan container Circular reference detected hatasını bildirir. Tembel proxy'yle A servisi yalnızca B servisinin bir proxy'sini alır; o da gerçekten kullanıldığında, yani A zaten varken kendini başlatır. Yine de döngüsel bağımlılık kusurlu bir tasarımın işaretidir ve ondan kurtulmak daha iyidir.

Tembel yükleme PHP 8.4 ya da daha yenisini gerektirir ve yalnızca doğrudan sınıf örneklenerek oluşturulan servislerde çalışır (örneğin create: Foo), factory metoduyla oluşturulanlarda çalışmaz. Sonunda PHP'nin iç sınıflarından birini genişleten sınıflarda da kullanılamaz. Tembel yükleme uygulanamadığında lazy: true bayrağı sessizce yok sayılır.

Etiketler

Etiketler, servislere ek bilgi eklemeye yarar. Bir servise bir ya da daha çok etiket atayabilirsiniz:

services:
	foo:
		create: Foo
		tags:
			- cached

Etiketler değer de taşıyabilir:

services:
	foo:
		create: Foo
		tags:
			logger: monolog.logger.event

Belirli etiketlerle ilişkili tüm servisleri almak için tagged() fonksiyonunu kullanabilirsiniz:

services:
	- LoggersDependent( tagged(logger) )

DI container içinde, belirli bir etikete sahip tüm servislerin adlarını findByTag() metoduyla alabilirsiniz:

$names = $container->findByTag('logger');
// $names, anahtarları servis adları, değerleri etiket değerleri olan bir dizidir
// örneğin ['foo' => 'monolog.logger.event', ...]

Inject Kipi

inject: true bayrağı, Inject attribute'una sahip public özellikler ve inject*() metotları üzerinden bağımlılık enjeksiyonunu etkinleştirir.

services:
	articles:
		create: App\Model\Articles
		inject: true

Varsayılan olarak inject kipi yalnızca presenter'larda açıktır.

Servis Değişiklikleri

DI container, yerleşik ya da kullanıcı extension'larıyla eklenmiş pek çok servis tutar. Bu var olan servislerin tanımlarını doğrudan yapılandırmada değiştirebilirsiniz. Örneğin varsayılanı Nette\Application\Application olan application.application servisinin sınıfını başka bir sınıfla değiştirebilirsiniz:

services:
	application.application:
		create: MyApplication
		alteration: true

alteration bayrağı, var olan bir servisi yalnızca değiştirdiğimizi gösterir. Aynı zamanda bir güvence görevi görür: değiştirilen servis yoksa derleme istisnayla başarısız olur.

Setup'ı da tamamlayabiliriz:

services:
	application.application:
		create: MyApplication
		alteration: true
		setup:
			- '$onStartup[]' = [@resource, init]

Bir servisi iç adıyla belirtmek zorunda değilsiniz; onun yerine türüyle başvurabilirsiniz. Önceki örnek şöyle de yazılabilir:

services:
	@Nette\Application\Application:
		create: MyApplication

Bir servisi değiştirirken özgün argümanları, setup öğelerini ya da etiketleri reset anahtarıyla kaldırmak isteyebiliriz:

services:
	application.application:
		create: MyApplication
		alteration: true
		reset:
			arguments: true
			setup: true
			tags: true

Bir extension tarafından eklenen bir servisi kaldırmak isterseniz bunu şöyle yapabilirsiniz:

services:
	cache.journal: false