Uzayan Latte
Latte çok esnektir ve birçok şekilde genişletilebilir: özel filtreler, işlevler, etiketler, yükleyiciler vb. ekleyebilirsiniz. Size nasıl yapılacağını göstereceğiz.
Bu bölümde Latte'yi genişletmenin farklı yolları açıklanmaktadır. Yaptığınız değişiklikleri farklı projelerde yeniden kullanmak veya başkalarıyla paylaşmak istiyorsanız, sözde uzantı oluşturmalısınız.
Roma'ya Kaç Yol Çıkar?
Latte'yi genişletmenin bazı yolları harmanlanabildiğinden, önce aralarındaki farkları açıklamaya çalışalım. Örnek olarak, üretilecek kelime sayısı verilen bir Lorem ipsum üretecini uygulamaya çalışalım.
Latte dilinin ana yapısı etikettir. Latte'yi yeni bir etiketle genişleterek bir üreteç uygulayabiliriz:
{lipsum 40}
Etiket harika çalışacaktır. Ancak, etiket biçimindeki oluşturucu bir ifadede kullanılamayacağı için yeterince esnek olmayabilir. Bu arada, pratikte etiket oluşturmaya nadiren ihtiyaç duyarsınız; ve bu iyi bir haber, çünkü etiketler genişletmek için daha karmaşık bir yoldur.
Tamam, etiket yerine bir filtre oluşturmayı deneyelim:
{=40|lipsum}
Yine geçerli bir seçenek. Ancak filtre geçirilen değeri başka bir şeye dönüştürmelidir. Burada, dönüştürmek
istediğimiz değer olarak değil, filtre argümanı olarak üretilen kelime sayısını gösteren 40
değerini
kullanıyoruz.
Öyleyse fonksiyon kullanmayı deneyelim:
{lipsum(40)}
İşte bu kadar! Bu özel örnek için, bir fonksiyon oluşturmak kullanılacak ideal uzantı noktasıdır. Örneğin, bir ifadenin kabul edildiği her yerde onu çağırabilirsiniz:
{var $text = lipsum(40)}
Filtreler
Adını ve işlev gibi herhangi bir PHP çağrılabilirini kaydederek bir süzgeç oluşturun:
$latte = new Latte\Engine;
$latte->addFilter('shortify', fn(string $s) => mb_substr($s, 0, 10)); // metni 10 karaktere kısaltır
Bu durumda filtrenin ek bir parametre alması daha iyi olacaktır:
$latte->addFilter('shortify', fn(string $s, int $len = 10) => mb_substr($s, 0, $len));
Bunun gibi bir şablonda kullanırız:
<p>{$text|shortify}</p>
<p>{$text|shortify:100}</p>
Gördüğünüz gibi, fonksiyon |
as the first argument and the arguments passed to the filter after
:
borusundan önce filtrenin sol tarafını sonraki argümanlar olarak alır.
Elbette, filtreyi temsil eden fonksiyon herhangi bir sayıda parametre kabul edebilir ve değişken parametreler de desteklenir.
Filtre HTML'de bir dize döndürürse, Latte'nin otomatik olarak (ve bu nedenle çift) kaçış yapmaması için
işaretleyebilirsiniz. Bu, şablonda |noescape
belirtme ihtiyacını ortadan kaldırır. En kolay yol dizeyi bir
Latte\Runtime\Html
nesnesine sarmaktır, diğer yol ise Bağlamsal
Filtrelerdir.
$latte->addFilter('money', fn(float $amount) => new Latte\Runtime\Html("<i>$amount EUR</i>"));
Bu durumda, filtre verilerin doğru şekilde kaçmasını sağlamalıdır.
Sınıfı Kullanan Filtreler
Bir filtre tanımlamanın ikinci yolu sınıf kullanmaktır.
TemplateFilter
niteliği ile bir yöntem oluşturuyoruz:
class TemplateParameters
{
public function __construct(
// parametreler
) {}
#[Latte\Attributes\TemplateFilter]
public function shortify(string $s, int $len = 10): string
{
return mb_substr($s, 0, $len);
}
}
$params = new TemplateParameters(/* ... */);
$latte->render('template.latte', $params);
Filtre Yükleyici
Süzgeçleri tek tek kaydetmek yerine, süzgeç adını argüman olarak kullanarak çağrılan ve PHP çağrılabilirini veya null döndüren bir işlev olan yükleyici adı verilen bir işlev oluşturabilirsiniz.
$latte->addFilterLoader([new Filters, 'load']);
class Filters
{
public function load(string $filter): ?callable
{
if (in_array($filter, get_class_methods($this))) {
return [$this, $filter];
}
return null;
}
public function shortify($s, $len = 10)
{
return mb_substr($s, 0, $len);
}
// ...
}
Bağlamsal Filtreler
Bağlamsal bir filtre, ilk parametrede Latte\Runtime\FilterInfo nesnesini kabul eden ve ardından klasik filtrelerde olduğu gibi diğer parametreleri kabul eden bir filtredir. Aynı şekilde kaydedilir, Latte filtrenin bağlamsal olduğunu kendisi tanır:
use Latte\Runtime\FilterInfo;
$latte->addFilter('foo', function (FilterInfo $info, string $str): string {
// ...
});
Bağlam filtreleri, $info->contentType
değişkeninde aldıkları içerik türünü algılayabilir ve
değiştirebilir. Filtre klasik olarak bir değişken üzerinden çağrılırsa (örneğin {$var|foo}
),
$info->contentType
null içerecektir.
Filtre öncelikle girdi dizesinin içerik türünün desteklenip desteklenmediğini kontrol etmelidir. Ayrıca bunu değiştirebilir. Metin (veya null) kabul eden ve HTML döndüren bir filtre örneği:
use Latte\Runtime\FilterInfo;
$latte->addFilter('money', function (FilterInfo $info, float $amount): string {
// önce girdinin içerik türünün metin olup olmadığını kontrol ederiz
if (!in_array($info->contentType, [null, ContentType::Text])) {
throw new Exception("Filter |money used in incompatible content type $info->contentType.");
}
// içerik türünü HTML olarak değiştir
$info->contentType = ContentType::Html;
return "<i>$amount EUR</i>";
});
Bu durumda, filtre verilerin doğru şekilde kaçmasını sağlamalıdır.
Bloklar üzerinde kullanılan tüm filtreler (örn. {block|foo}...{/block}
)
bağlamsal olmalıdır.
Fonksiyonlar
Öntanımlı olarak, sandbox devre dışı bırakmadığı sürece tüm yerel PHP işlevleri Latte'de kullanılabilir. Ancak kendi işlevlerinizi de tanımlayabilirsiniz. Bunlar yerel işlevleri geçersiz kılabilir.
Adını ve herhangi bir PHP çağrılabilirini kaydederek bir işlev oluşturun:
$latte = new Latte\Engine;
$latte->addFunction('random', function (...$args) {
return $args[array_rand($args)];
});
Bu durumda kullanım PHP fonksiyonunun çağrılmasıyla aynıdır:
{random(apple, orange, lemon)} // prints for example: apple
Sınıfı Kullanan İşlevler
Bir fonksiyon tanımlamanın ikinci yolu sınıf kullanmaktır.
TemplateFunction
niteliği ile bir metot oluşturuyoruz:
class TemplateParameters
{
public function __construct(
// parametreler
) {}
#[Latte\Attributes\TemplateFunction]
public function random(...$args)
{
return $args[array_rand($args)];
}
}
$params = new TemplateParameters(/* ... */);
$latte->render('template.latte', $params);
Yükleyiciler
Yükleyiciler, şablonları dosya sistemi gibi bir kaynaktan yüklemekten sorumludur. setLoader()
yöntemi
kullanılarak ayarlanırlar:
$latte->setLoader(new MyLoader);
Yerleşik yükleyiciler şunlardır:
FileLoader
Varsayılan yükleyici. Şablonları dosya sisteminden yükler.
Temel dizin ayarlanarak dosyalara erişim kısıtlanabilir:
$latte->setLoader(new Latte\Loaders\FileLoader($templateDir));
$latte->render('test.latte');
StringLoader
Şablonları dizelerden yükler. Bu yükleyici birim testi için çok kullanışlıdır. Ayrıca tüm şablonları tek bir PHP dosyasında saklamanın mantıklı olabileceği küçük projeler için de kullanılabilir.
$latte->setLoader(new Latte\Loaders\StringLoader([
'main.file' => '{include other.file}',
'other.file' => '{if true} {$var} {/if}',
]));
$latte->render('main.file');
Basitleştirilmiş kullanım:
$template = '{if true} {$var} {/if}';
$latte->setLoader(new Latte\Loaders\StringLoader);
$latte->render($template);
Özel Yükleyici Oluşturma
Yükleyici, Latte\Loader arayüzünü uygulayan bir sınıftır.
Etiketler
Şablonlama motorunun en ilginç özelliklerinden biri, etiketleri kullanarak yeni dil yapıları tanımlama yeteneğidir. Bu aynı zamanda daha karmaşık bir işlevdir ve Latte'nin dahili olarak nasıl çalıştığını anlamanız gerekir.
Ancak çoğu durumda etikete gerek yoktur:
- eğer bir çıktı üretmesi gerekiyorsa, bunun yerine fonksiyon kullanın
- bazı girdileri değiştirip döndürmek içinse, bunun yerine filtre kullanın
- bir metin alanını düzenlemek olsaydı, onu bir
{block}
etiketi ve bir filtre kullanın - eğer herhangi bir çıktı vermeyip sadece bir fonksiyon çağırması gerekiyorsa
{do}
Eğer hala bir etiket oluşturmak istiyorsanız, harika! Tüm temel bilgileri Uzantı Oluşturma bölümünde bulabilirsiniz.
Derleyici Geçişleri
Derleyici geçişleri AST'leri değiştiren veya içlerindeki bilgileri toplayan işlevlerdir. Örneğin Latte'de bir sandbox şu şekilde uygulanır: AST'nin tüm düğümlerini dolaşır, işlev ve yöntem çağrılarını bulur ve bunları kontrollü çağrılarla değiştirir.
Etiketlerde olduğu gibi, bu daha karmaşık bir işlevdir ve Latte'nin kaputun altında nasıl çalıştığını anlamanız gerekir. Tüm temel bilgileri Uzantı Oluşturma bölümünde bulabilirsiniz.