Şablonlar

Nette Latte şablon sistemini kullanır. Latte, PHP için en güvenli şablon sistemi ve aynı zamanda en sezgisel sistem olduğu için kullanılır. Yeni bir şey öğrenmenize gerek yok, sadece PHP ve birkaç Latte etiketi bilmeniz yeterli.

Sayfanın düzen şablonu + eylem şablonundan tamamlanması olağandır. Bir düzen şablonu böyle görünebilir, {block} bloklarına ve {include} etiketine dikkat edin:

<!DOCTYPE html>
<html>
<head>
	<title>{block title}My App{/block}</title>
</head>
<body>
	<header>...</header>
	{include content}
	<footer>...</footer>
</body>
</html>

Bu da eylem şablonu olabilir:

{block title}Homepage{/block}

{block content}
<h1>Homepage</h1>
...
{/block}

Düzende {include content} yerine eklenen content bloğunu tanımlar ve ayrıca düzende {block title} 'un üzerine yazılan title bloğunu yeniden tanımlar. Sonucu hayal etmeye çalışın.

Şablon Arama

Sunucularda, hangi şablonun işleneceğini belirtmenize gerek yoktur; çerçeve yolu otomatik olarak belirleyerek kodlamayı sizin için kolaylaştıracaktır.

Her sunucunun kendi dizinine sahip olduğu bir dizin yapısı kullanıyorsanız, şablonu bu dizine eylemin adı (yani görünüm) altında yerleştirmeniz yeterlidir. Örneğin, default eylemi için default.latte şablonunu kullanın:

app/
└── UI/
    └── Home/
        ├── HomePresenter.php
        └── default.latte

Sunucuların tek bir dizinde ve şablonların templates klasöründe bir arada olduğu bir yapı kullanıyorsanız, bunu bir dosyaya kaydedin <Presenter>.<view>.latte veya <Presenter>/<view>.latte:

app/
└── Presenters/
    ├── HomePresenter.php
    └── templates/
        ├── Home.default.latte  ← 1st variant
        └── Home/
            └── default.latte   ← 2nd variant

templates dizini, sunum yapan sınıfların bulunduğu dizinle aynı seviyede, bir seviye daha yükseğe de yerleştirilebilir.

Şablon bulunamazsa, sunum yapan kişi 404 – sayfa bulunamadı hatası ile yanıt verir.

Görünümü $this->setView('anotherView') adresini kullanarak değiştirebilirsiniz. Şablon dosyasını $this->template->setFile('/path/to/template.latte') ile doğrudan belirtmek de mümkündür.

Şablonların arandığı dosyalar, olası dosya adlarından oluşan bir dizi döndüren formatTemplateFiles() yöntemi geçersiz kılınarak değiştirilebilir.

Düzen Şablonu Arama

Nette ayrıca otomatik olarak yerleşim dosyasını arar.

Her sunum yapan kişinin kendi dizinine sahip olduğu bir dizin yapısı kullanıyorsanız, düzeni ya sadece sunum yapan kişiye özelse sunum yapan kişinin bulunduğu klasöre ya da birden fazla sunum yapan kişi için ortaksa bir üst seviyeye yerleştirin:

app/
└── UI/
    ├── @layout.latte           ← common layout
    └── Home/
        ├── @layout.latte       ← only for Home presenter
        ├── HomePresenter.php
        └── default.latte

Sunum yapanların tek bir dizinde gruplandığı ve şablonların templates klasöründe bulunduğu bir yapı kullanıyorsanız, düzen aşağıdaki yerlerde beklenecektir:

app/
└── Presenters/
    ├── HomePresenter.php
    └── templates/
        ├── @layout.latte       ← common layout
        ├── Home.@layout.latte  ← only for Home, 1st variant
        └── Home/
            └── @layout.latte   ← only for Home, 2nd variant

Sunucu bir modüldeyse, modülün iç içe geçmesine göre dizin ağacının daha yukarısında da arama yapacaktır.

Düzenin adı $this->setLayout('layoutAdmin') kullanılarak değiştirilebilir ve ardından @layoutAdmin.latte dosyasında beklenir. Düzen şablon dosyasını $this->setLayout('/path/to/template.latte') adresini kullanarak doğrudan da belirtebilirsiniz.

Şablon içinde $this->setLayout(false) veya {layout none} etiketinin kullanılması düzen aramayı devre dışı bırakır.

Düzen şablonlarının arandığı dosyalar, olası dosya adlarından oluşan bir dizi döndüren formatLayoutTemplateFiles() yöntemi geçersiz kılınarak değiştirilebilir.

Şablondaki Değişkenler

Değişkenler $this->template adresine yazılarak şablona aktarılır ve daha sonra yerel değişkenler olarak şablonda kullanılabilir:

$this->template->article = $this->articles->getById($id);

Bu şekilde herhangi bir değişkeni şablonlara kolayca aktarabiliriz. Ancak, sağlam uygulamalar geliştirirken, kendimizi sınırlamak genellikle daha yararlıdır. Örneğin, şablonun beklediği değişkenlerin ve türlerinin bir listesini açıkça tanımlayarak. Bu, PHP'nin tip kontrolü yapmasına, IDE'nin doğru şekilde otomatik tamamlama yapmasına ve statik analizin hataları tespit etmesine olanak tanıyacaktır.

Peki böyle bir numaralandırmayı nasıl tanımlarız? Basitçe bir sınıf ve onun özellikleri şeklinde. Bunu presenter'a benzer şekilde adlandırıyoruz, ancak sonunda Template var:

/**
 * @property-read ArticleTemplate $template
 */
class ArticlePresenter extends Nette\Application\UI\Presenter
{
}

class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template
{
	public Model\Article $article;
	public Nette\Security\User $user;

	// ve diğer değişkenler
}

Sunucudaki $this->template nesnesi artık ArticleTemplate sınıfının bir örneği olacaktır. Böylece PHP, yazıldıklarında bildirilen türleri kontrol edecektir. PHP 8.2'den başlayarak, varolmayan bir değişkene yazma konusunda da uyaracaktır, önceki sürümlerde aynı şey Nette\SmartObject özelliği kullanılarak elde edilebilir.

@property-read ek açıklaması IDE ve statik analiz içindir, otomatik tamamlamanın çalışmasını sağlar, PhpStorm ve $this->template için kod tamamlama bölümüne bakın.

Şablonlarda da fısıldama lüksünün tadını çıkarabilirsiniz, sadece PhpStorm'da Latte eklentisini kurun ve şablonun başında sınıf adını belirtin, Latte: sistem nasıl yazılır makalesine bakın:

{templateType App\UI\Article\ArticleTemplate}
...

Şablonlar bileşenlerde de bu şekilde çalışır, sadece adlandırma kuralını takip edin ve bileşen için bir şablon sınıfı FifteenTemplate oluşturun, örneğin FifteenControl.

Başka bir sınıfın örneği olarak bir $template oluşturmanız gerekiyorsa, createTemplate() yöntemini kullanın:

public function renderDefault(): void
{
	$template = $this->createTemplate(SpecialTemplate::class);
	$template->foo = 123;
	// ...
	$this->sendTemplate($template);
}

Varsayılan Değişkenler

Sunucular ve bileşenler çeşitli faydalı değişkenleri şablonlara otomatik olarak aktarır:

  • $basePath kök dizine giden mutlak bir URL yoludur (örneğin /CD-collection)
  • $baseUrl kök dizine mutlak bir URL'dir (örneğin http://localhost/CD-collection)
  • $user kullanıcıyı temsil eden bir nesnedir
  • $presenter şu anki sunucu
  • $control geçerli bileşen veya sunum yapan kişidir
  • $flashes yöntem tarafından gönderilen mesajların listesi flashMessage()

Özel bir şablon sınıfı kullanıyorsanız, bu değişkenler için bir özellik oluşturduğunuzda bu değişkenler geçirilir.

Şablonda diğer sunumculara ve eylemlere aşağıdaki gibi bağlantılar oluşturuyoruz:

<a n:href="Product:show">detail</a>

Öznitelik n:href HTML etiketleri için çok kullanışlıdır <a>. Bağlantıyı başka bir yere, örneğin metnin içine yazdırmak istiyorsak {link} adresini kullanırız:

URL is: {link Home:default}

Daha fazla bilgi için Bağlantı Oluşturma bölümüne bakın.

Özel Filtreler, Etiketler vb.

Latte şablonlama sistemi özel filtreler, fonksiyonlar, etiketler vb. ile genişletilebilir. Bu işlem doğrudan render<View> veya beforeRender() yöntemini kullanabilirsiniz:

public function beforeRender(): void
{
	// bir filtre ekleme
	$this->template->addFilter('foo', /* ... */);

	// veya Latte\Engine nesnesini doğrudan yapılandırın
	$latte = $this->template->getLatte();
	$latte->addFilterLoader(/* ... */);
}

Latte sürüm 3, her web projesi için bir uzantı oluşturarak daha gelişmiş bir yol sunar. İşte böyle bir sınıfın kabaca bir örneği:

namespace App\UI\Accessory;

final class LatteExtension extends Latte\Extension
{
	public function __construct(
		private App\Model\Facade $facade,
		private Nette\Security\User $user,
		// ...
	) {
	}

	public function getFilters(): array
	{
		return [
			'timeAgoInWords' => $this->filterTimeAgoInWords(...),
			'money' => $this->filterMoney(...),
			// ...
		];
	}

	public function getFunctions(): array
	{
		return [
			'canEditArticle' =>
				fn($article) => $this->facade->canEditArticle($article, $this->user->getId()),
			// ...
		];
	}

	// ...
}

configuration kullanarak kaydediyoruz:

latte:
	extensions:
		- App\UI\Accessory\LatteExtension

Çeviri

Çok dilli bir uygulama programlıyorsanız, muhtemelen şablondaki bazı metinlerin çıktısını farklı dillerde almanız gerekecektir. Bunu yapmak için Nette Framework, translate() tek bir yöntemi olan bir çeviri arayüzü Nette\Localization\Translator tanımlar. Bu, genellikle bir dize olan $message mesajını ve diğer parametreleri kabul eder. Görev, çevrilmiş dizeyi döndürmektir. Nette'de varsayılan bir uygulama yoktur, Componette'de bulunabilecek çeşitli hazır çözümler arasından ihtiyaçlarınıza göre seçim yapabilirsiniz. Belgeleri size çevirmeni nasıl yapılandıracağınızı anlatır.

Şablonlar, setTranslator() yöntemi kullanılarak bize iletilecek bir çevirmen ile kurulabilir:

protected function beforeRender(): void
{
	// ...
	$this->template->setTranslator($translator);
}

Alternatif olarak, çevirmen yapılandırma kullanılarak ayarlanabilir:

latte:
	extensions:
		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)

Çevirmen daha sonra örneğin |translate filtresi olarak kullanılabilir ve ek parametreler translate() yöntemine aktarılabilir (bkz. foo, bar):

<a href="basket">{='Basket'|translate}</a>
<span>{$item|translate}</span>
<span>{$item|translate, foo, bar}</span>

Veya bir alt çizgi etiketi olarak:

<a href="basket">{_'Basket'}</a>
<span>{_$item}</span>
<span>{_$item, foo, bar}</span>

Şablon bölüm çevirisi için eşleştirilmiş bir {translate} etiketi vardır (Latte 2.11'den beri, daha önce {_} etiketi kullanılıyordu):

<a href="order">{translate}Order{/translate}</a>
<a href="order">{translate foo, bar}Order{/translate}</a>

Çevirmen, şablon oluşturulurken varsayılan olarak çalışma zamanında çağrılır. Ancak Latte sürüm 3, şablon derleme sırasında tüm statik metni çevirebilir. Bu performans tasarrufu sağlar çünkü her dize yalnızca bir kez çevrilir ve sonuçta ortaya çıkan çeviri derlenmiş forma yazılır. Bu, önbellek dizininde şablonun her dil için bir tane olmak üzere birden fazla derlenmiş sürümünü oluşturur. Bunu yapmak için yalnızca ikinci parametre olarak dili belirtmeniz gerekir:

protected function beforeRender(): void
{
	// ...
	$this->template->setTranslator($translator, $lang);
}

Statik metin ile örneğin {_'hello'} veya {translate}hello{/translate} kastedilmektedir. {_$foo} gibi statik olmayan metinler anında derlenmeye devam edecektir.

versiyon: 4.0