Bootstrap

Bootstrap, ortamı başlatan, bağımlılık enjeksiyonu (DI) konteynerini oluşturan ve uygulamayı başlatan bir başlatma kodudur. Şunları ele alacağız:

  • NEON dosyaları kullanılarak nasıl yapılandırılır
  • üretim ve geliştirme modları nasıl ayırt edilir
  • DI konteyneri nasıl oluşturulur

Uygulamalar, ister web uygulamaları ister komut satırından çalıştırılan betikler olsun, çalışmalarına bir tür ortam başlatma ile başlarlar. Eski zamanlarda, bu genellikle ilk dosyanın dahil ettiği include.inc.php gibi bir dosyanın sorumluluğundaydı. Modern Nette uygulamalarında, bunun yerini uygulamanın bir parçası olarak app/Bootstrap.php dosyasında bulunan Bootstrap sınıfı almıştır. Örneğin şöyle görünebilir:

use Nette\Bootstrap\Configurator;

class Bootstrap
{
	private Configurator $configurator;
	private string $rootDir;

	public function __construct()
	{
		$this->rootDir = dirname(__DIR__);
		// Yapılandırıcı, uygulama ortamını ve servisleri ayarlamaktan sorumludur.
		$this->configurator = new Configurator;
		// Nette tarafından oluşturulan geçici dosyalar için dizini ayarlar (örn. derlenmiş şablonlar)
		$this->configurator->setTempDirectory($this->rootDir . '/temp');
	}

	public function bootWebApplication(): Nette\DI\Container
	{
		$this->initializeEnvironment();
		$this->setupContainer();
		return $this->configurator->createContainer();
	}

	private function initializeEnvironment(): void
	{
		// Nette akıllıdır ve geliştirme modu otomatik olarak açılır,
		// veya aşağıdaki satırın yorumunu kaldırarak belirli bir IP adresi için etkinleştirebilirsiniz:
		// $this->configurator->setDebugMode('secret@23.75.345.200');

		// Tracy'yi etkinleştirir: hata ayıklama için nihai "İsviçre çakısı".
		$this->configurator->enableTracy($this->rootDir . '/log');

		// RobotLoader: seçilen dizindeki tüm sınıfları otomatik olarak yükler
		$this->configurator->createRobotLoader()
			->addDirectory(__DIR__)
			->register();
	}

	private function setupContainer(): void
	{
		// Yapılandırma dosyalarını yükler
		$this->configurator->addConfig($this->rootDir . '/config/common.neon');
	}
}

index.php

Web uygulamaları durumunda ilk dosya, genel dizinde www/ bulunan index.php dosyasıdır. Bu dosya, Bootstrap sınıfından ortamı başlatmasını ve DI konteynerini oluşturmasını ister. Ardından, web uygulamasını başlatan Application servisini ondan alır:

$bootstrap = new App\Bootstrap;
// Ortamı başlat + DI konteynerini oluştur
$container = $bootstrap->bootWebApplication();
// DI konteyneri Nette\Application\Application nesnesini oluşturur
$application = $container->getByType(Nette\Application\Application::class);
// Nette uygulamasını başlat ve gelen isteği işle
$application->run();

Gördüğünüz gibi, ortamı ayarlamaya ve bağımlılık enjeksiyonu (DI) konteynerini oluşturmaya Nette\Bootstrap\Configurator sınıfı yardımcı olur, şimdi onu daha yakından tanıyacağız.

Geliştirme vs Üretim Modu

Nette, geliştirme veya üretim sunucusunda çalışıp çalışmadığına bağlı olarak farklı davranır:

🛠️ Geliştirme Modu (Development)
Yararlı bilgilerle (SQL sorguları, yürütme süresi, kullanılan bellek) Tracy hata ayıklama çubuğunu gösterir
Bir hata durumunda, fonksiyon çağrıları ve değişken içerikleriyle ayrıntılı bir hata sayfası gösterir
Latte şablonları değiştiğinde, yapılandırma dosyaları düzenlendiğinde vb. önbelleği otomatik olarak yeniler
🚀 Üretim Modu (Production)
Hata ayıklama bilgisi göstermez, tüm hataları günlüğe yazar
Bir hata durumunda, ErrorPresenter'ı veya genel “Server Error” sayfasını gösterir
Önbellek asla otomatik olarak yenilenmez!
Hız ve güvenlik için optimize edilmiştir

Mod seçimi otomatik algılama ile yapılır, bu nedenle genellikle herhangi bir şeyi yapılandırmaya veya manuel olarak değiştirmeye gerek yoktur:

  • geliştirme modu: localhost'ta (IP adresi 127.0.0.1 veya ::1) proxy mevcut değilse (yani HTTP başlığı yoksa)
  • üretim modu: her yerde

Geliştirme modunu diğer durumlarda da etkinleştirmek istersek, örneğin belirli bir IP adresinden erişen programcılar için, setDebugMode() kullanırız:

$this->configurator->setDebugMode('23.75.345.200'); // IP adresleri dizisi de belirtilebilir

Kesinlikle IP adresini bir çerezle birleştirmenizi öneririz. nette-debug çerezine gizli bir belirteç, örneğin secret1234 kaydederiz ve bu şekilde belirli bir IP adresinden erişen ve aynı zamanda çerezde belirtilen belirtece sahip olan programcılar için geliştirme modunu etkinleştiririz:

$this->configurator->setDebugMode('secret1234@23.75.345.200');

Geliştirme modunu tamamen kapatabiliriz, localhost için bile:

$this->configurator->setDebugMode(false);

Dikkat, true değeri geliştirme modunu zorla açar, bu üretim sunucusunda asla olmamalıdır.

Hata Ayıklama Aracı Tracy

Kolay hata ayıklama için harika Tracy aracını da etkinleştireceğiz. Geliştirme modunda hataları görselleştirir ve üretim modunda hataları belirtilen dizine günlüğe kaydeder:

$this->configurator->enableTracy($this->rootDir . '/log');

Geçici Dosyalar

Nette, DI konteyneri, RobotLoader, şablonlar vb. için önbellek kullanır. Bu nedenle, önbelleğin depolanacağı dizinin yolunu ayarlamak gerekir:

$this->configurator->setTempDirectory($this->rootDir . '/temp');

Linux veya macOS'ta, log/ ve temp/ dizinlerine yazma izinlerini ayarlayın.

RobotLoader

Genellikle RobotLoader kullanarak sınıfları otomatik olarak yüklemek isteyeceğiz, bu yüzden onu başlatmalı ve Bootstrap.php dosyasının bulunduğu dizinden (yani __DIR__) ve tüm alt dizinlerden sınıfları yüklemesine izin vermeliyiz:

$this->configurator->createRobotLoader()
	->addDirectory(__DIR__)
	->register();

Alternatif bir yaklaşım, PSR-4'e uyarak sınıfları yalnızca Composer aracılığıyla yüklemektir.

Zaman Dilimi

Yapılandırıcı aracılığıyla varsayılan zaman dilimini ayarlayabilirsiniz.

$this->configurator->setTimeZone('Europe/Prague');

DI Konteyner Yapılandırması

Başlatma sürecinin bir parçası, tüm uygulamanın kalbi olan nesneler için bir fabrika olan DI konteynerinin oluşturulmasıdır. Aslında bu, Nette tarafından oluşturulan ve önbellek dizinine kaydedilen bir PHP sınıfıdır. Fabrika, uygulamanın temel nesnelerini üretir ve yapılandırma dosyaları aracılığıyla ona nasıl oluşturulacağını ve ayarlanacağını bildiririz, böylece tüm uygulamanın davranışını etkileriz.

Yapılandırma dosyaları genellikle NEON formatında yazılır. Ayrı bir bölümde, nelerin yapılandırılabileceğini öğreneceksiniz.

Geliştirme modunda, kod veya yapılandırma dosyaları her değiştiğinde konteyner otomatik olarak güncellenir. Üretim modunda, yalnızca bir kez oluşturulur ve performansı en üst düzeye çıkarmak için değişiklikler kontrol edilmez.

Yapılandırma dosyalarını addConfig() kullanarak yükleriz:

$this->configurator->addConfig($this->rootDir . '/config/common.neon');

Daha fazla yapılandırma dosyası eklemek istiyorsak, addConfig() fonksiyonunu birden çok kez çağırabiliriz.

$configDir = $this->rootDir . '/config';
$this->configurator->addConfig($configDir . '/common.neon');
$this->configurator->addConfig($configDir . '/services.neon');
if (PHP_SAPI === 'cli') {
	$this->configurator->addConfig($configDir . '/cli.php');
}

cli.php adı bir yazım hatası değildir, yapılandırma bir dizi olarak döndüren bir PHP dosyasında da yazılabilir.

Ayrıca `includes` bölümünde |dependency-injection:configuration başka yapılandırma dosyaları da ekleyebiliriz.

Yapılandırma dosyalarında aynı anahtarlara sahip öğeler görünürse, bunlar üzerine yazılır veya diziler durumunda birleştirilir. Daha sonra eklenen dosya, öncekinden daha yüksek önceliğe sahiptir. includes bölümünün belirtildiği dosya, içine dahil edilen dosyalardan daha yüksek önceliğe sahiptir.

Statik Parametreler

Yapılandırma dosyalarında kullanılan parametreleri parameters bölümünde tanımlayabilir ve ayrıca addStaticParameters() metoduyla (diğer adı addParameters()) iletebilir (veya üzerine yazabiliriz). Önemli olan, farklı parametre değerlerinin ek DI konteynerlerinin, yani ek sınıfların oluşturulmasına neden olmasıdır.

$this->configurator->addStaticParameters([
	'projectId' => 23,
]);

projectId parametresine yapılandırmada normal %projectId% gösterimiyle başvurulabilir.

Dinamik Parametreler

Konteynere dinamik parametreler de ekleyebiliriz; bunların farklı değerleri, statik parametrelerin aksine, yeni DI konteynerlerinin oluşturulmasına neden olmaz.

$this->configurator->addDynamicParameters([
	'remoteIp' => $_SERVER['REMOTE_ADDR'],
]);

Bu şekilde, örneğin ortam değişkenlerini kolayca ekleyebiliriz, bunlara daha sonra yapılandırmada %env.variable% gösterimiyle başvurulabilir.

$this->configurator->addDynamicParameters([
	'env' => getenv(),
]);

Varsayılan Parametreler

Yapılandırma dosyalarında şu statik parametreleri kullanabilirsiniz:

  • %appDir%, Bootstrap.php dosyasını içeren dizine mutlak yoldur
  • %wwwDir%, giriş dosyası index.php dosyasını içeren dizine mutlak yoldur
  • %tempDir%, geçici dosyalar için dizine mutlak yoldur
  • %vendorDir%, Composer'ın kütüphaneleri kurduğu dizine mutlak yoldur
  • %rootDir%, projenin kök dizinine mutlak yoldur
  • %debugMode%, uygulamanın hata ayıklama modunda olup olmadığını belirtir
  • %consoleMode%, isteğin komut satırından gelip gelmediğini belirtir

İçe Aktarılan Servisler

Şimdi daha derine iniyoruz. DI konteynerinin amacı nesneleri üretmek olsa da, istisnai olarak mevcut bir nesneyi konteynere ekleme ihtiyacı doğabilir. Bunu, servisi imported: true bayrağıyla tanımlayarak yaparız.

services:
	myservice:
		type: App\Model\MyCustomService
		imported: true

Ve bootstrap'ta nesneyi konteynere ekleriz:

$this->configurator->addServices([
	'myservice' => new App\Model\MyCustomService('foobar'),
]);

Farklı Ortam

Bootstrap sınıfını ihtiyaçlarınıza göre değiştirmekten çekinmeyin. Web projelerini ayırt etmek için bootWebApplication() metoduna parametreler ekleyebilirsiniz. Veya birim testleri için ortamı başlatan bootTestEnvironment(), komut satırından çağrılan betikler için bootConsoleApplication() gibi başka metotlar ekleyebiliriz.

public function bootTestEnvironment(): Nette\DI\Container
{
	Tester\Environment::setup(); // Nette Tester'ı başlat
	$this->setupContainer();
	return $this->configurator->createContainer();
}

public function bootConsoleApplication(): Nette\DI\Container
{
	$this->configurator->setDebugMode(false);
	$this->initializeEnvironment();
	$this->setupContainer();
	return $this->configurator->createContainer();
}
versiyon: 4.0