Nette Documentation Preview

syntax
Nette DI için Uzantı Oluşturma
******************************
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Nette DI için Uzantı Oluşturma

DI konteynerinin oluşturulması, yapılandırma dosyalarının yanı sıra uzantılar olarak adlandırılanlar tarafından da etkilenir. Bunları yapılandırma dosyasında extensions bölümünde etkinleştiririz.

Bu şekilde, BlogExtension sınıfı tarafından temsil edilen uzantıyı blog adı altında ekleriz:

extensions:
	blog: BlogExtension

Her derleyici uzantısı Nette\DI\CompilerExtension'dan kalıtım alır ve DI konteynerinin oluşturulması sırasında sırayla çağrılan aşağıdaki metotları uygulayabilir:

  1. getConfigSchema()
  2. loadConfiguration()
  3. beforeCompile()
  4. afterCompile()

getConfigSchema()

Bu metot ilk olarak çağrılır. Yapılandırma parametrelerinin doğrulanması için şemayı tanımlar.

Uzantıyı, uzantının eklendiği adla aynı olan bölümde, yani blog'da yapılandırırız:

# uzantı adıyla aynı
blog:
	postsPerPage: 10
	allowComments: false

Tipleri, izin verilen değerleri ve isteğe bağlı olarak varsayılan değerleri de dahil olmak üzere tüm yapılandırma seçeneklerini açıklayan bir şema oluştururuz:

use Nette\Schema\Expect;

class BlogExtension extends Nette\DI\CompilerExtension
{
	public function getConfigSchema(): Nette\Schema\Schema
	{
		return Expect::structure([
			'postsPerPage' => Expect::int(),
			'allowComments' => Expect::bool()->default(true),
		]);
	}
}

Dokümantasyonu Schema sayfasında bulabilirsiniz. Ayrıca, dynamic() kullanarak hangi seçeneklerin dinamik olabileceğini belirleyebilirsiniz, örn. Expect::int()->dynamic().

Yapılandırmaya, bir stdClass nesnesi olan $this->config değişkeni aracılığıyla erişiriz:

class BlogExtension extends Nette\DI\CompilerExtension
{
	public function loadConfiguration()
	{
		$num = $this->config->postPerPage;
		if ($this->config->allowComments) {
			// ...
		}
	}
}

loadConfiguration()

Konteynere servis eklemek için kullanılır. Bunun için Nette\DI\ContainerBuilder kullanılır:

class BlogExtension extends Nette\DI\CompilerExtension
{
	public function loadConfiguration()
	{
		$builder = $this->getContainerBuilder();
		$builder->addDefinition($this->prefix('articles'))
			->setFactory(App\Model\HomepageArticles::class, ['@connection']) // veya setCreator()
			->addSetup('setLogger', ['@logger']);
	}
}

Kural, uzantı tarafından eklenen servisleri adıyla ön eklemektir, böylece isim çakışmaları olmaz. Bunu prefix() metodu yapar, yani uzantı adı blog ise, servis blog.articles adını taşır.

Bir servisi yeniden adlandırmamız gerekirse, geriye dönük uyumluluğu korumak için orijinal adla bir takma ad (alias) oluşturabiliriz. Nette bunu benzer şekilde yapar, örn. önceki adı router altında da mevcut olan routing.router servisi için.

$builder->addAlias('router', 'routing.router');

Dosyadan Servis Yükleme

Servisleri yalnızca ContainerBuilder sınıfının API'sini kullanarak değil, aynı zamanda yapılandırma dosyasında services bölümünde kullanılan bilinen yazımla da oluşturabiliriz. @extension ön eki mevcut uzantıyı temsil eder.

services:
	articles:
		create: MyBlog\ArticlesModel(@connection)

	comments:
		create: MyBlog\CommentsModel(@connection, @extension.articles)

	articlesList:
		create: MyBlog\Components\ArticlesList(@extension.articles)

Servisleri yükleriz:

class BlogExtension extends Nette\DI\CompilerExtension
{
	public function loadConfiguration()
	{
		$builder = $this->getContainerBuilder();

		// uzantı için yapılandırma dosyasını yükleme
		$this->compiler->loadDefinitionsFromConfig(
			$this->loadFromFile(__DIR__ . '/blog.neon')['services'],
		);
	}
}

beforeCompile()

Metot, konteynerin loadConfiguration metotlarında bireysel uzantılar tarafından eklenen tüm servisleri ve ayrıca kullanıcı yapılandırma dosyalarını içerdiği anda çağrılır. Bu derleme aşamasında, servis tanımlarını düzenleyebilir veya aralarındaki bağlantıları tamamlayabiliriz. Konteynerdeki servisleri etiketlere göre aramak için findByTag() metodunu, sınıfa veya arayüze göre aramak için ise findByType() metodunu kullanabiliriz.

class BlogExtension extends Nette\DI\CompilerExtension
{
	public function beforeCompile()
	{
		$builder = $this->getContainerBuilder();

		foreach ($builder->findByTag('logaware') as $serviceName => $tagValue) {
			$builder->getDefinition($serviceName)->addSetup('setLogger');
		}
	}
}

afterCompile()

Bu aşamada, konteyner sınıfı zaten bir ClassType nesnesi şeklinde üretilmiştir, servisleri oluşturan tüm metotları içerir ve önbelleğe yazılmaya hazırdır. Sonuç kodunu bu noktada hala düzenleyebiliriz.

class BlogExtension extends Nette\DI\CompilerExtension
{
	public function afterCompile(Nette\PhpGenerator\ClassType $class)
	{
		$method = $class->getMethod('__construct');
		// ...
	}
}

$initialization

Configurator sınıfı, konteyner oluşturulduktan sonra $this->initialization nesnesine addBody() metodu kullanılarak yazılan başlatma kodunu çağırır.

Örneğin, başlatma koduyla oturumu nasıl başlatacağımızı veya run etiketine sahip servisleri nasıl çalıştıracağımızı gösteren bir örnek:

class BlogExtension extends Nette\DI\CompilerExtension
{
	public function loadConfiguration()
	{
		// oturumun otomatik başlatılması
		if ($this->config->session->autoStart) {
			$this->initialization->addBody('$this->getService("session")->start()');
		}

		// run etiketli servisler konteyner örneklendikten sonra oluşturulmalıdır
		$builder = $this->getContainerBuilder();
		foreach ($builder->findByTag('run') as $name => $foo) {
			$this->initialization->addBody('$this->getService(?);', [$name]);
		}
	}
}