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ür
  • Presenter::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ı kesmez
  • Presenter::InvalidLinkTextual – görsel uyarı, hatayı doğrudan bağlantının içine yazdırır
  • Presenter::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.

versiyon: 4.x