Bileşen Modeli

Nette'de önemli bir kavram bileşendir. Sayfalara görsel etkileşimli bileşenler ekleriz; formlar ve onların tüm elemanları da bileşendir. Tüm bu bileşenlerin kalıttığı iki temel sınıf nette/component-model paketinin parçasıdır ve bileşen ağacı hiyerarşisini oluşturmaktan sorumludur.

Component

Nette\ComponentModel\Component, tüm bileşenlerin ortak atasıdır. Bileşenin adını döndüren getName() metodunu ve anasını döndüren getParent() metodunu içerir. İkisi de setParent() metoduyla ayarlanabilir; ilk parametre ana, ikincisi ise bileşen adıdır.

lookup (?string $type, bool $throw=true): ?Component

Hiyerarşide yukarı doğru, istenen sınıf ya da arayüzden bir nesne arar. Örneğin $component->lookup(Nette\Application\UI\Presenter::class), bileşen bir presenter'a bağlıysa, birkaç düzey ötede olsa bile onu döndürür. Eşleşen bir nesne bulunamazsa istisna fırlatır; onun yerine null döndürmesi için ikinci argüman olarak false aktarın. $type olarak null aktarırsanız, metot ağaçtaki en üstteki bileşeni, yani anası olmayan kökü arar.

lookupPath (?string $type=null, bool $throw=true): ?string

Yol denen şeyi döndürür; bu, geçerli bileşen ile aranan bileşen arasındaki yoldaki tüm bileşenlerin adlarının birleştirilmesiyle oluşan bir dizedir. Yani örneğin $component->lookupPath(Nette\Application\UI\Presenter::class), bileşenin presenter'a göre benzersiz tanımlayıcısını döndürür. $type değeri null olduğunda (ya da atlandığında) yol, ağacın köküne dek ölçülür.

Container

Nette\ComponentModel\Container, ana bileşendir; yani çocuk içeren ve böylece ağaç yapısını oluşturan bileşen. Nesneleri kolayca eklemek, almak ve kaldırmak için metotları vardır. Örneğin formun ya da Control ile Presenter sınıflarının atasıdır. ArrayAccess trait'ini kullanan alt sınıflar (Control ve Presenter gibi) çocuklara dizi yazımıyla erişmeye de izin verir, örneğin $container['child'].

addComponent (Component $component, ?string $name, ?string $insertBefore=null)static

Container'a çocuk olarak bir bileşen ekler. $name değeri null ise bileşenin kendi adı kullanılır. İsteğe bağlı $insertBefore parametresi (var olan bir çocuğun adı) kullanılırsa, yeni bileşen tam ondan önce eklenir; aksi hâlde sona iliştirilir. Metot container'ın kendisini döndürür, dolayısıyla çağrılar zincirlenebilir.

removeComponent (Component $component)void

Bir çocuk bileşeni container'dan kaldırır.

getComponent (string $name): ?Component

Bir bileşen döndürür. Tanımlanmamış bir çocuğu almaya çalışmak createComponent($name) factory metodunu çağırır. createComponent($name) metodu, geçerli bileşende createComponent<bileşen adı> metodunu, bileşen adını parametre olarak aktararak çağırır. Oluşturulan bileşen sonra geçerli bileşene çocuk olarak eklenir. Bu metotlara bileşen factory'leri deriz ve onlar Container sınıfından kalıtan sınıflarda gerçekleştirilebilir.

getComponents(): IComponent[]

Doğrudan alt bileşenleri bir dizi olarak döndürür; anahtarlar bu bileşenlerin adlarını içerir. Alt ağacın tamamını özyinelemeli almak için, tip süzmesi gerekiyorsa array_filter() ile birleştirerek getComponentTree() kullanın. (Eski sürümlerden bilinen $deep ve $filterType parametreleri 4.0 sürümünde kaldırıldı.)

getComponentTree(): list<IComponent>

Tüm iç içe çocuk bileşenler dahil bileşen hiyerarşisinin tamamını indeksli bir dizi olarak alır. Arama derinlik öncelikli yapılır.

Ataları İzleme

Nette bileşen modeli ağaçla çok dinamik çalışmaya izin verir (bileşenleri kaldırabilir, taşıyabilir, ekleyebiliriz), dolayısıyla bir bileşen oluşturulduktan hemen sonra (yapıcıda) anasının, ananın anasının vb. bilindiğine güvenmek yanlış olurdu. Genellikle bileşen oluşturulurken ana hiç bilinmez.

Bir bileşen, bir presenter'ın ya da belirli bir tipteki başka bir atanın altına iliştirildiği anı nasıl öğrenebilir? Doğrudan anayı izlemek yetmez, çünkü bağlantı ağacın daha yukarısında, örneğin ananın anası iliştirildiğinde gerçekleşebilir. monitor($type, $attached, $detached) metodu tam da bunun içindir: bir bileşen, ağaçta üstünde $type sınıfından ya da arayüzünden bir ata belirdiğinde ya da oradan yittiğinde bildirim almak istediğini bildirir. Bir bileşen istediği kadar tipi izleyebilir; eşleşen bir ata bağlandığında $attached callback'i tetiklenir ve argüman olarak o atayı alır, $detached ise ata ayrıldığında tetiklenir. İzleme unmonitor($type) ile yeniden durdurulabilir.

Bildirimler ağaç yapısını izler. İliştirmede bir ata, alt bileşenlerinden önce bildirim alır (yukarıdan aşağıya), böylece bir ana önce paylaşılan durumu hazırlayabilir, hatta bir çocuğu kendi callback'i çalışmadan önce kaldırabilir. Ayırmada sıra terstir; önce alt bileşenler bildirim alır. Callback'ler ayrıca yinelenmeden arındırılır, dolayısıyla aynı callback aynı nesne için asla iki kez çağrılmaz. Bu davranışın ardındaki gerekçe için 4.0 sürümü hakkındaki blog yazısına bakın.

Daha iyi anlamak için bir örnek: Nette Forms'ta dosya yükleme form denetimini temsil eden UploadControl sınıfı, formun enctype niteliğini multipart/form-data yapmalıdır. Ancak nesnenin oluşturulduğu anda hiçbir forma iliştirilmemiş olabilir. Öyleyse form hangi noktada değiştirilmelidir? Çözüm basittir: yapıcıda izleme isteği yapılır:

class UploadControl extends Nette\Forms\Controls\BaseControl
{
	public function __construct($label)
	{
		$this->monitor(Nette\Forms\Form::class, function ($form): void {
			$form->setHtmlAttribute('enctype', 'multipart/form-data');
		});
		// ...
	}

	// ...
}

ve form kullanılabilir olur olmaz callback çağrılır.

Daha yeni bir sürüme yükseltiyorsanız yükseltme sayfasına bakın.

versiyon: 4.x