URL bağlantıları oluşturma
Nette'te bağlantı oluşturmak parmakla göstermek kadar basittir. Yalnızca nişan alın, gerisini framework sizin için yapar. Şunları göstereceğiz:
- şablonlarda ve başka yerlerde nasıl bağlantı oluşturulur
- geçerli sayfaya giden bağlantı nasıl ayırt edilir
- geçersiz bağlantılarla ne yapılır
Çift yönlü yönlendirme sayesinde, uygulamanızın daha sonra değişebilecek veya birleştirmesi karmaşık olabilecek URL'lerini şablonlara ya da koda hiçbir zaman sabit yazmanız gerekmez. Bağlantıda yalnızca presenter'ı ve eylemi belirtin, gerekli parametreleri verin; URL'yi framework kendisi üretecektir. Aslında bir fonksiyon çağırmaya çok benzer. Bunu seveceksiniz.
Presenter şablonunda
Bağlantıları çoğu zaman şablonlarda oluştururuz ve n:href niteliği harika bir yardımcıdır:
<a n:href="Product:show">detay</a>
href HTML niteliği yerine n:niteliği
n:href kullandığımıza dikkat edin. Değeri, href niteliğinde olacağı gibi bir URL değil,
presenter'ın ve eylemin adıdır.
Bir bağlantıya tıklamak, basitçe söylersek, ProductPresenter::renderShow() metodunu çağırmak gibi bir
şeydir. İmzasında parametreler varsa onu argümanlarla çağırabiliriz:
<a n:href="Product:show $product->id, $product->slug">ürün detayı</a>
Adlandırılmış parametreler de aktarılabilir. Aşağıdaki bağlantı, lang parametresini en
değeriyle aktarır:
<a n:href="Product:show $product->id, lang: en">ürün detayı</a>
ProductPresenter::renderShow() metodunun imzasında $lang yoksa, parametrenin değerini
$lang = $this->getParameter('lang') ile veya bir özellikten alabilir.
Parametreler bir dizide saklanıyorsa, ... operatörüyle açılabilirler:
{var $args = [$product->id, lang => en]}
<a n:href="Product:show, ...$args">ürün detayı</a>
Kalıcı parametreler denilen parametreler de bağlantılarda otomatik olarak aktarılır.
n:href niteliği HTML <a> etiketleri için çok kullanışlıdır. Bağlantıyı başka bir
yerde, örneğin metin içinde yazdırmak istersek {link} kullanırız:
URL şudur: {link Home:default}
Kodda
Presenter'da bağlantı oluşturmak için link() metodu kullanılır:
$url = $this->link('Product:show', $product->id);
Parametreler dizi olarak da aktarılabilir; burada adlandırılmış parametreler de belirtilebilir:
$url = $this->link('Product:show', [$product->id, 'lang' => 'en']);
Bağlantılar presenter olmadan da, LinkGenerator ve onun link() metoduyla
oluşturulabilir.
Bazen bir bağlantıyı şimdi oluşturmanız, ama asıl URL'yi ancak daha sonra üretmeniz gerekir. Bunun için bir
Nette\Application\UI\Link nesnesi döndüren lazyLink() metodu vardır. Avantajı, bu nesneyi örneğin
bir şablona aktarabilmeniz ve render edilmeden önce parametrelerini setParameter() metoduyla hâlâ
ayarlayabilmenizdir. URL'nin kendisi ancak nesne bir dizeye dönüştürüldüğünde birleştirilir:
$link = $this->lazyLink('Product:show', $id);
// ...
echo $link; // URL ancak burada üretilir
Presenter'lara bağlantılar
Bağlantının hedefi bir presenter ve eylem ise, sözdizimi şöyledir:
[//] [[[[:]modül:]presenter:]eylem | this] [#fragman]
Bu formatı tüm Latte etiketleri ve bağlantılarla çalışan tüm presenter metotları destekler, yani n:href,
{link}, {plink}, link(), lazyLink(), isLinkCurrent(),
redirect(), redirectPermanent(), forward(), canonicalize() ve ayrıca LinkGenerator. Yani örneklerde n:href kullanılsa da, orada bu fonksiyonlardan
herhangi biri olabilirdi.
Temel biçim dolayısıyla Presenter:eylem'dir:
<a n:href="Home:default">ana sayfa</a>
Geçerli presenter'ın bir eylemine bağlantı veriyorsak adını atlayabiliriz:
<a n:href="default">ana sayfa</a>
Hedef eylem default ise onu atlayabiliriz, ama iki nokta üst üste kalmalıdır:
<a n:href="Home:">ana sayfa</a>
Bağlantılar başka modüllere de gidebilir. Burada
bağlantılar, iç içe bir alt modüle göreli veya mutlak olmak üzere ayrılır. İlke, disk yollarına benzer, yalnızca eğik
çizgi yerine iki nokta üst üste kullanılır. Geçerli presenter'ın Front modülünün parçası olduğunu
varsayarsak şöyle yazarız:
<a n:href="Shop:Product:show">Front:Shop:Product:show bağlantısı</a>
<a n:href=":Admin:Product:show">Admin:Product:show bağlantısı</a>
Özel bir durum, hedef olarak this belirttiğimiz kendine giden
bağlantıdır.
<a n:href="this">yenile</a>
Diyez işareti # ardından gelen fragman ile sayfanın belirli bir bölümüne bağlantı verebiliriz:
<a n:href="Home:#main">Home:default'a ve #main fragmanına bağlantı</a>
Fragman, # anahtarıyla argüman olarak dinamik de belirlenebilir. Değeri otomatik kodlanır
ve hedefte belirtilen fragmandan önceliklidir:
$this->link('Home:default', ['#' => $fragment]);
Mutlak yollar
link() veya n:href ile üretilen bağlantılar her zaman mutlak yollardır (yani / ile
başlarlar), ama https://domain gibi protokol ve alan adı içeren mutlak URL'ler değildir.
Mutlak bir URL üretmek için başına iki eğik çizgi ekleyin (örneğin n:href="//Home:"). Alternatif olarak,
$this->absoluteUrls = true ayarlayarak presenter'ı yalnızca mutlak bağlantı üretmeye geçirebilirsiniz.
Şablonda göreli bir yolu mutlak yola dönüştürmek için |absoluteUrl filtresi de kullanılabilir.
Geçerli sayfaya bağlantı
this hedefi, geçerli sayfaya bir bağlantı oluşturur:
<a n:href="this">yenile</a>
Bu sırada action<Eylem>() veya (action<Eylem>() tanımlı değilse)
render<Görünüm>() metodunun imzasında belirtilen tüm parametreler aktarılır. Yani id: 123
ile Product:show sayfasındaysak, this bağlantısı bu parametreyi de aktarır.
Elbette parametreleri doğrudan belirtmek de mümkündür:
<a n:href="this refresh: 1">yenile</a>
isLinkCurrent() fonksiyonu, bağlantının hedefinin geçerli sayfayla aynı olup olmadığını denetler. Bu,
örneğin şablonda bağlantıları ayırt etmek için kullanılabilir.
Parametreleri link() metodununkiyle aynıdır, ama somut bir eylem yerine, o presenter'ın herhangi bir eylemi
anlamına gelen * joker karakteri de kullanılabilir.
{if !isLinkCurrent('Admin:login')}
<a n:href="Admin:login">Giriş</a>
{/if}
<li n:class="isLinkCurrent('Product:*') ? active">
<a n:href="Product:">...</a>
</li>
Tek bir elemanda n:href ile birlikte kısaltılmış bir biçim kullanılabilir:
<a n:class="isLinkCurrent() ? active" n:href="Home:">...</a>
* joker karakteri yalnızca eylemin yerine kullanılabilir, presenter'ın yerine değil.
Belirli bir modülde veya onun alt modülünde olup olmadığımızı belirlemek için isModuleCurrent(modulAdi)
metodunu kullanın.
<li n:class="isModuleCurrent('Forum:Users') ? active">
<a n:href="Product:">...</a>
</li>
Bağlantı tabanını değiştirme
Varsayılan olarak göreli bağlantılar geçerli presenter'dan türetilir. Bu, {linkBase} ile
değiştirilebilir:
{linkBase Admin:Dashboard}
<a n:href="Product:show">ürün detayı</a>
Bağlantı Admin:Dashboard:Product:show'a gidecektir. Yalnızca göreli bağlantılar etkilenir; iki nokta üst
üste ile başlayan mutlak bağlantılar ve geçerli presenter'a giden bağlantılar (this, show)
değişmeden kalır.
{linkBase} tüm şablon için geçerlidir ve özellikle layout şablonlarında kullanışlıdır; orada çağıran
presenter'dan bağımsız olarak tutarlı bağlantılar sağlar. Etiket şablonun başına konmalıdır, aksi halde
CompileException fırlatır.
Sinyallere bağlantılar
Bağlantının hedefi yalnızca bir presenter ve eylem olmak zorunda değildir; bir sinyal de olabilir (handle<Sinyal>() metodunu çağırır). O zaman
sözdizimi şöyledir:
[//] [alt-bileşen:]sinyal! [#fragman]
Sinyal, ünlem işaretiyle ayırt edilir:
<a n:href="click!">sinyal</a>
Bir alt bileşenin (veya alt alt bileşenin) sinyaline de bağlantı oluşturabilirsiniz:
<a n:href="componentName:click!">sinyal</a>
Bileşende bağlantılar
Bileşenler çevredeki presenter'larla hiçbir bağı olmaması gereken ayrı, yeniden
kullanılabilir birimler olduğundan, burada bağlantılar biraz farklı çalışır. Latte niteliği n:href ve
{link} etiketi, ayrıca link() gibi bileşen metotları bağlantı hedefini her zaman sinyal adı
olarak kabul eder. Bu yüzden ünlem işareti eklemek bile gerekmez:
<a n:href="click">sinyal, eylem değil</a>
Bileşen şablonunda presenter'lara bağlantı vermek istersek {plink} etiketini kullanırız:
<a href={plink Home:default}>ana sayfa</a>
ya da kodda
$this->getPresenter()->link('Home:default')
Takma adlar
Bazen bir Presenter:eylem çiftine kolay akılda kalan bir takma ad vermek yararlı olabilir. Örneğin
Front:Home:default ana sayfasını basitçe home, Admin:Dashboard:default'u ise
admin diye adlandırmak.
Takma adlar yapılandırmada application › aliases anahtarı altında
tanımlanır:
application:
aliases:
home: Front:Home:default
admin: Admin:Dashboard:default
sign: Front:Sign:in
Bağlantılarda ise et işaretiyle yazılırlar, örneğin:
<a n:href="@admin">yönetim</a>
redirect() ve benzeri gibi bağlantılarla çalışan tüm metotlarda da desteklenirler.
Geçersiz bağlantılar
Geçersiz bir bağlantı oluşturmamız olabilir; ya var olmayan bir presenter'a gittiği için, ya hedef metodun imzasında
kabul ettiğinden fazla parametre aktardığı için, ya da hedef eylem için URL üretilemediği için. Geçersiz bağlantılarla
nasıl başa çıkılacağı presenter'da $this->invalidLinkMode ile ayarlanır. Şu değerlerin (sabitlerin) bir
bileşimini alabilir:
Presenter::InvalidLinkSilent– sessiz mod, URL olarak # karakterini döndürürPresenter::InvalidLinkWarning– bir E_USER_WARNING uyarısı fırlatılır; üretim modunda günlüğe yazılır, ama betiğin çalışmasını kesmezPresenter::InvalidLinkTextual– görsel uyarı, hatayı doğrudan bağlantının içine yazdırırPresenter::InvalidLinkException– InvalidLinkException fırlatır
Varsayılan ayar, üretim modunda InvalidLinkWarning, geliştirme modunda ise
InvalidLinkWarning | InvalidLinkTextual'dır. Üretim ortamında InvalidLinkWarning betiğin kesilmesine
yol açmaz, ama uyarı günlüğe yazılır. Geliştirme ortamında Tracy onu yakalar ve
bir bluescreen gösterir. InvalidLinkTextual, URL olarak #error: karakterleriyle başlayan bir hata
mesajı döndürerek çalışır. Böyle bağlantıların ilk bakışta göze çarpması için CSS'inize şunu ekleyin:
a[href^="#error:"] {
background: red;
color: white;
}
Geliştirme ortamında uyarı üretilmesini istemiyorsak, onları doğrudan yapılandırmada bastırabiliriz.
application:
silentLinks: true
LinkGenerator
link() metodundaki rahatlıkla, ama presenter olmadan nasıl bağlantı oluşturulur? İşte Nette\Application\LinkGenerator bunun
içindir.
LinkGenerator, constructor üzerinden size aktarılabilen ve sonra link() metoduyla bağlantı
oluşturabileceğiniz bir servistir.
Presenter'lara kıyasla bir fark vardır. LinkGenerator tüm bağlantıları doğrudan mutlak URL olarak oluşturur. Ayrıca
„geçerli presenter“ diye bir şey yoktur, bu yüzden hedef olarak yalnızca eylem adını link('default')
belirtmek veya modüllere göreli yollar kullanmak mümkün değildir.
Geçersiz bağlantılar her zaman Nette\Application\UI\InvalidLinkException fırlatır.