Hizmet Tanımları

Yapılandırma, DI konteynerine tek tek hizmetlerin nasıl bir araya getirileceği ve diğer bağımlılıklarla nasıl bağlanacağı konusunda talimat verdiğimiz yerdir. Nette bunu başarmak için çok açık ve zarif bir yol sunar.

NEON yapılandırma dosyasındaki services bölümü, özel hizmetlerimizi ve yapılandırmalarını tanımladığımız yerdir. PDO sınıfının bir örneğini temsil eden database adlı bir hizmetin tanımlanmasına ilişkin basit bir örneğe bakalım:

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

Bu yapılandırma DI konteynerinde aşağıdaki fabrika yöntemiyle sonuçlanır:

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

Hizmet adları, @serviceName biçimini kullanarak yapılandırma dosyasının diğer bölümlerinde bunlara başvurmamızı sağlar. Hizmeti adlandırmaya gerek yoksa, sadece bir madde işareti kullanabiliriz:

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

DI konteynerinden bir hizmeti almak için, parametre olarak hizmet adıyla birlikte getService() yöntemini veya hizmet türüyle birlikte getByType() yöntemini kullanabiliriz:

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

Hizmet Oluşturma

En yaygın olarak, sadece belirli bir sınıfı örnekleyerek bir hizmet 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 fazla satıra genişletilebilir:

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

create anahtarının bir takma adı vardır factory, her iki sürüm de pratikte yaygındır. Ancak biz create adresini kullanmanızı öneririz.

Kurucu argümanları veya oluşturma yöntemi alternatif olarak arguments anahtarına yazılabilir:

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

Hizmetler sadece bir sınıfın basit bir şekilde örneklenmesiyle oluşturulmak zorunda değildir; statik yöntemlerin veya diğer hizmetlerin yöntemlerinin çağrılmasıyla da ortaya çıkabilirler:

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

Basitlik için -> yerine :: kullandığımızı unutmayın, ifade araçlarına bakın. Bu fabrika yöntemleri oluşturulur:

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

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

DI konteynerinin oluşturulan hizmetin türünü bilmesi gerekir. Belirtilen bir dönüş türüne sahip olmayan bir yöntem kullanarak bir hizmet oluşturursak, yapılandırmada bu türden açıkça bahsetmeliyiz:

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

Argümanlar

Normal PHP'ye çok benzer bir şekilde kuruculara ve yöntemlere argümanlar aktarırız:

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

Daha iyi okunabilirlik için, argümanları ayrı satırlarda listeleyebiliriz. Bu formatta virgül kullanımı isteğe bağlıdır:

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

Argümanlara isim de verebilirsiniz, böylece sıraları konusunda endişelenmenize gerek kalmaz:

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

Belirli bağımsız değişkenleri atlamak ve varsayılan değerlerini kullanmak veya otomatik bağlantı yoluyla bir hizmet eklemek istiyorsanız, bir alt çizgi kullanın:

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

Bağımsız değişkenler hizmetler, parametreler ve çok daha fazlası olabilir, ifade araçlarına bakın.

Kurulum

setup bölümünde, hizmet oluşturulurken çağrılması gereken yöntemleri tanımlıyoruz.

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

PHP'de bu şöyle görünecektir:

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

Yöntem çağrılarına ek olarak, özelliklere değer de aktarabilirsiniz. Bir diziye eleman eklemek de desteklenir, ancak NEON sözdizimiyle çakışmasını önlemek için bunu tırnak içine almanız gerekir:

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

PHP'de bu şu anlama gelir:

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

Kurulumda, statik yöntemleri veya diğer hizmetlerin yöntemlerini de çağırabilirsiniz. Geçerli hizmeti argüman olarak geçirmeniz gerekiyorsa, @self adresini kullanın:

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

Basitlik için -> yerine :: kullandığımızı unutmayın, ifade araçlarına bakın. Bu, aşağıdaki fabrika yöntemini oluşturur:

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

İfade Araçları

Nette DI bize son derece zengin ifade yetenekleri sunarak neredeyse her şeyi ifade etmemize olanak tanır. Yapılandırma dosyalarında parametreler kullanabiliriz:

# parametresi
%wwwDir%

# bir parametre anahtarı altındaki değer
%mailer.user%

# bir dize içindeki parametre
'%wwwDir%/images'

Ayrıca nesneler oluşturabilir, yöntemler ve fonksiyonlar çağırabiliriz:

# bir nesne oluşturun
DateTime()

# statik bir yöntem çağırma
Collator::create(%locale%)

# bir PHP işlevini çağırır
::getenv(DB_USER)

Hizmetlere ya adlarıyla ya da türlerine göre atıfta bulunun:

# isme göre hizmet
@database

# türe göre hi̇zmet
@Nette\Database\Connection

Birinci sınıf çağrılabilir sözdizimi kullanın:

# creating a callback, equivalent to [@user, logout]
@user::logout(...)

Sabitleri kullanın:

# sınıf sabiti
FilesystemIterator::SKIP_DOTS

# constant() PHP işlevi tarafından elde edilen küresel sabit
::constant(PHP_VERSION)

Metot çağrıları PHP'de olduğu gibi zincirleme yapılabilir. Basitlik için -> yerine :: kullanacağız:

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

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

Bu ifadeler hizmetler oluşturulurken herhangi bir yerde, argümanlarda, kurulum bölümünde veya parametrelerde kullanılabilir:

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

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

Özel Fonksiyonlar

Yapılandırma dosyaları içinde bu özel işlevleri kullanabilirsiniz:

  • Değer olumsuzlama için not()
  • Kayıpsız tip dökümü için bool(), int(), float()string()
  • typed() belirtilen türdeki tüm hizmetlerin bir dizisini oluşturmak için
  • tagged() belirli bir etikete sahip tüm hizmetlerin bir dizisini oluşturmak için
services:
	- Foo(
		id: int(::getenv('ProjectId'))
		productionMode: not(%debugMode%)
	)

PHP'deki (int) gibi geleneksel tip atamayla karşılaştırıldığında, kayıpsız tip atama sayısal olmayan değerler için bir istisna oluşturur.

typed() işlevi, belirli bir türdeki (sınıf veya arayüz) tüm hizmetlerin bir dizisini oluşturur. Otomatik kablolaması kapalı olan hizmetleri hariç tutar. Virgülle ayrılarak birden fazla tür belirtilebilir.

services:
	- BarsDependent( typed(Bar) )

Otomatik kablolamayı kullanarak belirli bir türdeki bir dizi hizmeti otomatik olarak argüman olarak da iletebilirsiniz.

tagged() işlevi, belirtilen etikete sahip tüm hizmetlerin bir dizisini oluşturur. Birden fazla etiket virgülle ayrılarak listelenebilir.

services:
	- LoggersDependent( tagged(logger) )

Otomatik Kablolama

autowired tuşu, belirli bir hizmet için otomatik kablolama davranışını değiştirmenize olanak tanır. Daha fazla ayrıntı için otomatik kablolama bölümüne bakın.

services:
	foo:
		create: Foo
		autowired: false     # foo hizmeti otomatik kablolamanın dışında tutulur

Etiketler

Etiketler hizmetlere ek bilgi eklemek için kullanılır. Bir hizmete bir veya daha fazla etiket atayabilirsiniz:

services:
	foo:
		create: Foo
		tags:
			- cached

Etiketler değer de taşıyabilir:

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

Belirli etiketlere sahip tüm hizmetleri almak için tagged() işlevini kullanabilirsiniz:

services:
	- LoggersDependent( tagged(logger) )

DI konteynerinde, findByTag() yöntemini kullanarak belirli bir etikete sahip tüm hizmetlerin adlarını elde edebilirsiniz:

$names = $container->findByTag('logger');
// $names, hizmet adını ve etiket değerini içeren bir dizidir
// örneğin ['foo' => 'monolog.logger.event', ...]

Enjeksiyon Modu

inject: true bayrağının kullanılması, bağımlılıkların inject ek açıklaması ve inject*() yöntemleri ile genel değişkenler aracılığıyla aktarılmasını etkinleştirir.

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

Varsayılan olarak, inject yalnızca sunum yapanlar için etkinleştirilir.

Hizmet Değişiklikleri

DI konteyneri, yerleşik veya kullanıcı uzantıları tarafından eklenen birçok hizmet içerir. Bu hizmetlerin tanımlarını doğrudan yapılandırma içinde değiştirebilirsiniz. Örneğin, geleneksel olarak Nette\Application\Application olan application.application hizmetinin sınıfını başka bir şeyle değiştirebilirsiniz:

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

alteration bayrağı bilgilendiricidir ve yalnızca mevcut bir hizmeti değiştirdiğimizi gösterir.

Kurulumu da tamamlayabiliriz:

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

Bir hizmetin üzerine yazarken, orijinal argümanları, kurulum öğelerini veya etiketleri kaldırmak isteyebilirsiniz, işte bu noktada reset kullanışlı hale gelir:

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

Bir uzantı tarafından eklenen bir hizmeti kaldırmak isterseniz, bunu şu şekilde yapabilirsiniz:

services:
	cache.journal: false
versiyon: 3.x