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çintagged()
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