Yönlendirme
Router, URL adresleriyle ilgili her şeyi üstlenir, böylece onları düşünmek zorunda kalmazsınız. Size şunları göstereceğiz:
- URL'lerin istediğiniz gibi görünmesi için router nasıl yapılandırılır
- SEO ve yönlendirme üzerine konuşacağız
- ve kendi router'ınızı nasıl yazacağınızı göstereceğiz
İnsana daha dostça URL'ler (havalı veya güzel URL de denir) daha kullanışlıdır, akılda daha iyi kalır ve SEO'ya olumlu katkı yapar. Nette bunu göz önünde bulundurur ve geliştiricilerin ihtiyaçlarını tam olarak karşılar. Uygulamanız için istediğiniz URL yapısını tam olarak tasarlayabilirsiniz. Üstelik uygulama zaten tamamlandığında bile tasarlayabilirsiniz, çünkü kodda veya şablonlarda hiçbir değişiklik gerektirmez. Tüm presenter'lara anotasyon olarak dağılmak yerine tek bir yerde, router'da zarif biçimde tanımlanır.
Nette'teki router olağanüstüdür, çünkü çift yönlüdür. Hem HTTP isteklerinden URL'leri çözebilir hem de bağlantı oluşturabilir. Böylece Nette Application içinde çok önemli bir rol oynar: yalnızca geçerli isteği hangi presenter'ın ve eylemin yürüteceğine karar vermekle kalmaz, şablonlarda vb. URL üretmek için de kullanılır.
Ancak router'ın kullanımı bununla sınırlı değildir; onu presenter'ların hiç kullanılmadığı uygulamalarda, REST API'lerde vb. de kullanabilirsiniz. Daha fazla ayrıntı Bağımsız kullanım bölümünde.
Rota koleksiyonu
Bir uygulamadaki URL adreslerinin yapısını tanımlamanın en hoş yolunu Nette\Application\Routers\RouteList sınıfı sunar. Tanım, rota denilen şeylerin listesinden oluşur; yani basit bir API ile URL adreslerinin maskeleri ve onlara bağlı presenter'lar ile eylemler. Rotaları hiçbir şekilde adlandırmamız gerekmez.
$router = new Nette\Application\Routers\RouteList;
$router->addRoute('rss.xml', 'Feed:rss');
$router->addRoute('article/<id>', 'Article:view');
// ...
Örnek şunu gösterir: tarayıcıda https://domain.com/rss.xml açarsak, rss eylemiyle
Feed presenter'ı gösterilir. https://domain.com/article/12 ise view eylemiyle
Article presenter'ını gösterir vb. Uygun bir rota bulunamazsa Nette Application, kullanıcıya 404 Not Found hata
sayfası olarak gösterilen bir BadRequestException fırlatarak
yanıt verir.
Rotaların sırası
Rotaların listelenme sırası kesinlikle çok önemlidir, çünkü yukarıdan aşağıya sırayla değerlendirilirler. Kural şudur: rotaları özelden genele doğru bildiririz:
// YANLIŞ: 'rss.xml' ilk rota tarafından yakalanır ve bu dize <slug> sanılır
$router->addRoute('<slug>', 'Article:view');
$router->addRoute('rss.xml', 'Feed:rss');
// DOĞRU
$router->addRoute('rss.xml', 'Feed:rss');
$router->addRoute('<slug>', 'Article:view');
Bağlantı üretilirken de rotalar yukarıdan aşağıya değerlendirilir:
// YANLIŞ: 'Feed:rss' bağlantısı 'admin/feed/rss' olarak üretilir
$router->addRoute('admin/<presenter>/<action>', 'Admin:default');
$router->addRoute('rss.xml', 'Feed:rss');
// DOĞRU
$router->addRoute('rss.xml', 'Feed:rss');
$router->addRoute('admin/<presenter>/<action>', 'Admin:default');
Rotaları doğru kurmanın biraz beceri gerektirdiğini sizden saklamayacağız. Bunda ustalaşana kadar yönlendirme paneli işinize yarayacak bir araç olacak.
Maske ve parametreler
Maske, sitenin kök dizininden itibaren göreli yolu tanımlar. En basit maske statik bir URL'dir:
$router->addRoute('products', 'Products:default');
Maskeler sıklıkla parametre denilen şeyleri içerir. Bunlar açılı parantez içine alınır (örneğin
<year>) ve hedef presenter'a, örneğin renderShow(int $year) metoduna veya $year
kalıcı parametresine aktarılır:
$router->addRoute('chronicle/<year>', 'History:show');
Örnek şunu gösterir: tarayıcıda https://example.com/chronicle/2020 açarsak, show eylemiyle ve
year: 2020 parametresiyle History presenter'ı gösterilir.
Parametreler için doğrudan maskede varsayılan bir değer belirtebiliriz; bu onları isteğe bağlı yapar:
$router->addRoute('chronicle/<year=2020>', 'History:show');
Rota artık https://example.com/chronicle/ URL'sini de kabul edecek ve yine year: 2020 parametresiyle
History:show'u gösterecektir.
Elbette presenter ve eylem adları da parametre olabilir. Örneğin:
$router->addRoute('<presenter>/<action>', 'Home:default');
Belirtilen rota örneğin /article/edit veya /catalog/list biçimindeki URL'leri kabul eder ve
onları sırasıyla Article:edit ile Catalog:list presenter'ları ve eylemleri olarak anlar.
Aynı zamanda presenter ve action parametrelerine Home ve default
varsayılan değerlerini verir, bu da onları da isteğe bağlı yapar. Böylece rota /article gibi bir URL'yi de
kabul eder ve onu Article:default olarak anlar. Ya da tersine, Product:default'a giden bir bağlantı
/product yolunu, varsayılan Home:default'a giden bir bağlantı ise / yolunu üretir.
Maske yalnızca sitenin kök dizininden itibaren göreli yolu değil, eğik çizgiyle başlıyorsa mutlak yolu, hatta iki eğik çizgiyle başlıyorsa tüm mutlak URL'yi de tanımlayabilir:
// document root'a göreli
$router->addRoute('<presenter>/<action>', /* ... */);
// mutlak yol (alan adına göreli)
$router->addRoute('/<presenter>/<action>', /* ... */);
// alan adı dahil mutlak URL (şemaya göreli)
$router->addRoute('//<lang>.example.com/<presenter>/<action>', /* ... */);
// şema dahil mutlak URL
$router->addRoute('https://<lang>.example.com/<presenter>/<action>', /* ... */);
Doğrulama ifadeleri
Her parametre için bir düzenli ifadeyle
doğrulama koşulu belirtilebilir. Örneğin id parametresi için, \d+ regex'iyle yalnızca rakam
içerebileceğini belirtiriz:
$router->addRoute('<presenter>/<action>[/<id \d+>]', /* ... */);
Tüm parametreler için varsayılan düzenli ifade [^/]+'dir, yani eğik çizgi dışındaki her şey. Bir
parametrenin eğik çizgi de kabul etmesi gerekiyorsa ifadeyi .+ yaparız:
// https://example.com/a/b/c kabul eder, path 'a/b/c' olur
$router->addRoute('<path .+>', /* ... */);
İsteğe bağlı diziler
Maskede isteğe bağlı bölümler köşeli parantezle işaretlenebilir. Maskenin herhangi bir bölümü isteğe bağlı olabilir ve parametre içerebilir:
$router->addRoute('[<lang [a-z]{2}>/]<name>', /* ... */);
// Şu yolları kabul eder:
// /en/download => lang => en, name => download
// /download => lang => null, name => download
Bir parametre isteğe bağlı bir dizinin parçası olduğunda, doğal olarak kendisi de isteğe bağlı olur. Belirtilmiş bir varsayılan değeri yoksa null olacaktır.
İsteğe bağlı bölümler alan adında da olabilir:
$router->addRoute('//[<lang=en>.]example.com/<presenter>/<action>', /* ... */);
Diziler iç içe geçirilebilir ve istenildiği gibi birleştirilebilir:
$router->addRoute(
'[<lang [a-z]{2}>[-<sublang>]/]<name>[/page-<page=0>]',
'Home:default',
);
// Şu yolları kabul eder:
// /en/hello
// /en-us/hello
// /hello
// /hello/page-12
URL üretilirken en kısa seçenek yeğlenir, bu yüzden atlanabilecek her şey atlanır. Bu nedenle örneğin
index[.html] rotası /index yolunu üretir. Bu davranış, sol köşeli parantezin ardına ünlem
işareti konarak tersine çevrilebilir:
// /hello ve /hello.html kabul eder, /hello üretir
$router->addRoute('<name>[.html]', /* ... */);
// /hello ve /hello.html kabul eder, /hello.html üretir
$router->addRoute('<name>[!.html]', /* ... */);
Köşeli parantezsiz isteğe bağlı parametreler (yani varsayılan değeri olanlar) aslında şöyle sarılmış gibi davranır:
$router->addRoute('<presenter=Home>/<action=default>/<id=>', /* ... */);
// buna karşılık gelir:
$router->addRoute('[<presenter=Home>/[<action=default>/[<id>]]]', /* ... */);
Sondaki eğik çizginin davranışını etkilemek, örneğin /home/ yerine /home üretilmesini
istemek istersek, bu şöyle sağlanabilir:
$router->addRoute('[<presenter=Home>[/<action=default>[/<id>]]]', /* ... */);
Joker karakterler
Mutlak URL maskesinde, örneğin geliştirme ve üretim ortamları arasında farklı olabilecek alan adını maskeye yazmak zorunda kalmamak için şu joker karakterleri kullanabiliriz:
%tld%= üst düzey alan adı, örneğincomveyaorg%sld%= ikinci düzey alan adı, örneğinexample%domain%= alt alan adları olmadan alan adı, örneğinexample.com%host%= tüm host, örneğinwww.example.com%basePath%= kök dizine giden yol
$router->addRoute('//www.%domain%/%basePath%/<presenter>/<action>', /* ... */);
$router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action>', /* ... */);
Gelişmiş yazım
Genellikle Presenter:eylem biçiminde yazılan rota hedefi, tek tek parametreleri ve varsayılan değerlerini
tanımlayan bir dizi kullanılarak da yazılabilir:
$router->addRoute('<presenter>/<action>[/<id \d+>]', [
'presenter' => 'Home',
'action' => 'default',
]);
Daha ayrıntılı belirtim için, varsayılan değerlerin yanı sıra başka parametre özelliklerini de (örneğin bir
doğrulama düzenli ifadesini, bkz. id parametresi) ayarlayabildiğimiz daha da genişletilmiş bir biçim
kullanılabilir:
use Nette\Routing\Route;
$router->addRoute('<presenter>/<action>[/<id>]', [
'presenter' => [
Route::Value => 'Home',
],
'action' => [
Route::Value => 'default',
],
'id' => [
Route::Pattern => '\d+',
],
]);
Şunu belirtmek önemlidir: dizide tanımlanan parametreler yol maskesinde listelenmiyorsa, değerleri değiştirilemez; URL'de soru işaretinden sonra belirtilen sorgu parametreleriyle bile.
Bu, sabit parametreler için yararlıdır; belirli bir sayfaya kısa, akılda kalan bir URL vermek. Örneğin
/tos'un her zaman id: 123 ile Article:view'u açması için:
$router->addRoute('tos', [
'presenter' => 'Article',
'action' => 'view',
'id' => 123,
]);
Filtreler ve çeviriler
Uygulamanın kaynak kodunu İngilizce yazarız, ama sitenin Çekçe URL'leri olması gerekiyorsa, şöyle basit bir yönlendirme:
$router->addRoute('<presenter>/<action>', 'Home:default');
İngilizce URL'ler üretecektir, örneğin /product/123 veya /cart. URL'deki presenter'ların ve
eylemlerin Çekçe sözcüklerle temsil edilmesini istiyorsak (örneğin /produkt/123 veya /kosik), bir
çeviri sözlüğü kullanabiliriz. Onu yazmak için ikinci parametrenin “daha ayrıntılı” seçeneğine
ihtiyacımız var:
use Nette\Routing\Route;
$router->addRoute('<presenter>/<action>', [
'presenter' => [
Route::Value => 'Home',
Route::FilterTable => [
// URL'deki dize => presenter
'produkt' => 'Product',
'kosik' => 'Cart',
'katalog' => 'Catalog',
],
],
'action' => [
Route::Value => 'default',
Route::FilterTable => [
'seznam' => 'list',
],
],
]);
Çeviri sözlüğündeki birden fazla anahtar aynı presenter'a gidebilir. Bu, onun için çeşitli takma adlar oluşturur. Son anahtar kanonik seçenek sayılır (yani üretilen URL'de yer alacak olan).
Çeviri tablosu bu şekilde herhangi bir parametre için kullanılabilir. Bir çeviri yoksa özgün değer alınır. Bu
davranışı Route::FilterStrict => true ekleyerek değiştirebiliriz; o zaman rota, değer sözlükte yoksa
URL'yi reddeder.
Dizi biçimindeki çeviri sözlüğünün yanı sıra kendi çeviri fonksiyonlarınız da devreye sokulabilir.
use Nette\Routing\Route;
$router->addRoute('<presenter>/<action>/<id>', [
'presenter' => [
Route::Value => 'Home',
Route::FilterIn => function (string $s): string { /* ... */ },
Route::FilterOut => function (string $s): string { /* ... */ },
],
'action' => 'default',
'id' => null,
]);
Route::FilterIn fonksiyonu, URL'deki parametre ile sonra presenter'a aktarılan dize arasında dönüşüm yapar;
FilterOut fonksiyonu ise ters yöndeki dönüşümü sağlar.
presenter, action ve module parametrelerinin, PascalCase veya camelCase stili ile
URL'lerde kullanılan kebab-case arasında dönüşüm yapan önceden tanımlı filtreleri vardır. Parametrelerin varsayılan
değeri, uygulamaya aktarıldığı biçimde yazılır (presenter ve module için PascalCase, action için camelCase); yani
örneğin bir presenter söz konusuysa <presenter=ProductEdit> yazarız,
<presenter=product-edit> değil.
Genel filtreler
Belirli parametreler için tasarlanmış filtrelerin yanı sıra, tüm parametrelerin ilişkisel dizisini alan, onu istediği gibi değiştirip döndürebilen genel filtreler de tanımlayabiliriz. Genel filtreler boş anahtar altında tanımlanır.
use Nette\Routing\Route;
$router->addRoute('<presenter>/<action>', [
'presenter' => 'Home',
'action' => 'default',
'' => [
Route::FilterIn => function (array $params): array { /* ... */ },
Route::FilterOut => function (array $params): array { /* ... */ },
],
]);
Genel filtreler, rotanın davranışını kesinlikle her şekilde değiştirme olanağı sunar. Onları örneğin parametreleri
başka parametrelere göre değiştirmek için kullanabiliriz. Örneğin <presenter> ve
<action>'ı <lang> parametresinin geçerli değerine göre çevirmek için.
Bir parametrenin kendi filtresi tanımlıysa ve bir de genel filtre varsa, kendi FilterIn'i genelden önce, buna
karşılık genel FilterOut kendi filtreden önce çalıştırılır. Böylece genel filtrenin içinde
presenter ve action parametrelerinin değerleri sırasıyla PascalCase ve camelCase stilinde
yazılıdır.
Bu filtrelerin pratik bir kullanımı için, hiçbir şablonu değiştirmeden /article/123-ekmek-nasil-pisirilir
gibi SEO dostu URL'ler üretmeyi anlatan Slug'lu güzel URL'ler
bölümüne bakın.
OneWay bayrağı
Tek yönlü rotalar, uygulamanın artık üretmediği ama hâlâ kabul ettiği eski URL'lerin işlevselliğini korumaya yarar.
Onları OneWay bayrağıyla işaretleriz:
// eski URL /product-info?id=123
$router->addRoute('product-info', 'Product:detail', oneWay: true);
// yeni URL /product/123
$router->addRoute('product/<id>', 'Product:detail');
Eski URL'ye erişildiğinde presenter otomatik olarak yeni URL'ye yönlendirir, böylece arama motorları bu sayfaları iki kez indekslemez (bkz. SEO ve kanonikleştirme).
Callback'lerle dinamik yönlendirme
Callback'lerle dinamik yönlendirme, rotalara doğrudan, ilgili yol ziyaret edildiğinde çalıştırılan fonksiyonlar (callback'ler) atamanızı sağlar. Bu esnek işlevsellik, uygulamanız için çeşitli uç noktaları hızlı ve verimli biçimde oluşturmanıza olanak tanır:
$router->addRoute('test', function () {
echo '/test adresindesiniz';
});
Maskede, callback'inize otomatik aktarılan parametreler de tanımlayabilirsiniz:
$router->addRoute('<lang cs|en>', function (string $lang) {
echo match ($lang) {
'cs' => 'Sitemizin Çekçe sürümüne hoş geldiniz!',
'en' => 'Sitemizin İngilizce sürümüne hoş geldiniz!',
};
});
Maskeden gelen parametrelerin yanı sıra callback, DI konteynerinden servisler de alabilir. Bunlar parametre tipine göre
aktarılır. Ayrıca $presenter parametresi, rotayı işleyen MicroPresenter örneğini alır:
$router->addRoute('<lang cs|en>', function (string $lang, Nette\Http\Request $httpRequest, NetteModule\MicroPresenter $presenter) {
// ...
});
Modüller
Ortak bir modüle ait
birden fazla rotamız varsa withModule() kullanırız. Verilen modül, gruptaki her rotanın presenter'ının önüne
otomatik eklenir ve URL'den tamamen kaybolur:
$router = new RouteList;
$router->withModule('Forum') // sonraki rotalar Forum modülünün parçasıdır
->addRoute('rss', 'Feed:rss') // presenter Forum:Feed olacak
->addRoute('<presenter>/<action>')
->withModule('Admin') // sonraki rotalar Forum:Admin modülünün parçasıdır
->addRoute('sign:in', 'Sign:in');
Bir alternatif de module parametresidir; o da sabit bir modül belirler ve onu URL'nin dışında tutar:
// manage/dashboard/default URL'si Admin:Dashboard presenter'ına eşlenir
$router->addRoute('manage/<presenter>/<action>', [
'module' => 'Admin',
]);
Her presenter adı ancak modülüyle birlikte tamdır, örneğin Front:Admin:ProductList. Böyle bir tam ad bir
URL parametresine düştüğünde, router onu iki basit kuralla kodlar: her iki nokta üst üste : (modül
ayırıcısı) bir noktaya, PascalCase bir addaki her sözcük sınırı ise bir kısa çizgiye dönüşür. Yani
Front:Admin:ProductList, URL'de front.admin.product-list olarak görünür ve aynı şekilde geri
çözülür. Modüler bir uygulamanın, yukarıdaki araçlar olmadan, noktalarla dolu URL'ler üretmesinin nedeni budur.
Hem withModule() hem de module parametresi bundan tam olarak şu yüzden kaçınır: presenter adı
URL'ye ulaşmadan önce bilinen modül ön ekini ondan soyarlar; modül sabit olduğundan hiç kodlanması gerekmez.
Bazen modülün kendisinin değişmesini ve URL'de görünmesini isteriz, bu yüzden doğrudan maskede
<module>'e başvururuz. Çok önemli bir ayrıntıya dikkat edin: <module> tüm modül
yolunu yakalar, yani presenter adındaki son iki nokta üst üsteye kadar olan her şeyi. Shop:Admin:Product
presenter'ı için bu, Shop:Admin modülü ve Product presenter'ı demektir; iki nokta üst üste
noktaya dönüştüğünden şunu elde ederiz:
Alt alan adları
Rota koleksiyonları alt alan adlarına göre bölünebilir:
$router = new RouteList;
$router->withDomain('example.com')
->addRoute('rss', 'Feed:rss')
->addRoute('<presenter>/<action>');
Alan adında Joker karakterler de kullanılabilir:
$router = new RouteList;
$router->withDomain('example.%tld%')
// ...
Yol ön eki
Rota koleksiyonları URL'deki yola göre bölünebilir:
$router = new RouteList;
$router->withPath('eshop')
->addRoute('rss', 'Feed:rss') // /eshop/rss URL'siyle eşleşir
->addRoute('<presenter>/<action>'); // /eshop/<presenter>/<action> URL'siyle eşleşir
Bileşimler
Yukarıdaki gruplamalar birbirleriyle birleştirilebilir:
$router = (new RouteList)
->withDomain('admin.example.com')
->withModule('Admin')
->addRoute(/* ... */)
->addRoute(/* ... */)
->end()
->withModule('Images')
->addRoute(/* ... */)
->end()
->end()
->withDomain('example.com')
->withPath('export')
->addRoute(/* ... */)
// ...
Sorgu parametreleri
Maskeler sorgu parametreleri de (URL'de soru işaretinden sonraki parametreler) içerebilir. Bunlar için doğrulama ifadesi tanımlanamaz, ama presenter'a aktarıldıkları ad değiştirilebilir:
// 'cat' sorgu parametresini uygulamada 'categoryId' adıyla kullanmak istiyoruz
$router->addRoute('product ? id=<productId> & cat=<categoryId>', /* ... */);
Foo parametreleri
Şimdi daha derine iniyoruz. Foo parametreleri aslında bir düzenli ifadeyle eşleşmeyi sağlayan adsız parametrelerdir. Bir
örnek, /index, /index.html, /index.htm ve /index.php kabul eden bir
rotadır:
$router->addRoute('index<? \.html?|\.php|>', /* ... */);
URL üretilirken kullanılacak dizeyi açıkça tanımlamak da mümkündür. Dize doğrudan soru işaretinin ardına
konmalıdır. Aşağıdaki rota öncekine benzer, ama /index yerine /index.html üretir, çünkü
üretim değeri olarak .html dizesi ayarlanmıştır:
$router->addRoute('index<?.html \.html?|\.php|>', /* ... */);
Entegrasyon
Oluşturduğumuz router'ı uygulamaya entegre etmek için DI konteynerine ondan söz etmemiz gerekir. En kolayı, router
nesnesini oluşturacak bir factory hazırlamak ve yapılandırmada konteynere onu kullanmasını söylemektir. Bunun için
App\Core\RouterFactory::createRouter() metodunu yazdığımızı varsayalım:
namespace App\Core;
use Nette\Application\Routers\RouteList;
class RouterFactory
{
public static function createRouter(): RouteList
{
$router = new RouteList;
$router->addRoute(/* ... */);
return $router;
}
}
Sonra yapılandırmaya şunu yazarız:
services:
- App\Core\RouterFactory::createRouter
Örneğin bir veritabanına olan bağımlılıklar, factory metoduna autowiring ile parametreleri olarak aktarılır:
public static function createRouter(Nette\Database\Connection $db): RouteList
{
// ...
}
SimpleRouter
Rota koleksiyonundan çok daha basit bir router SimpleRouter'dır. Onu, URL
biçimiyle ilgili özel gereksinimlerimiz olmadığında, mod_rewrite (veya alternatifleri) kullanılamıyorsa ya da
henüz güzel URL'lerle uğraşmak istemiyorsak kullanırız.
Aşağı yukarı şu biçimde adresler üretir:
http://example.com/?presenter=Product&action=detail&id=123
SimpleRouter constructor'ının parametresi varsayılan bir presenter ve eylemdir; yani örneğin
http://example.com/ adresini ek parametre olmadan açtığımızda çalıştırılacak eylem.
// varsayılan presenter 'Home', eylem 'default' olacak
$router = new Nette\Application\Routers\SimpleRouter('Home:default');
SimpleRouter'ı doğrudan yapılandırmada tanımlamanızı öneririz:
services:
- Nette\Application\Routers\SimpleRouter('Home:default')
SEO ve kanonikleştirme
Framework, aynı içeriğin farklı URL'lerde bulunmasını engelleyerek SEO'ya (arama motoru optimizasyonuna) katkı yapar.
Belirli bir hedefe birden fazla adres gidiyorsa, örneğin /index ve /index.html, framework ilkini
birincil (kanonik) sayar ve diğerlerini HTTP kodu 301 ile ona yönlendirir. Bu sayede arama motorları sayfaları iki kez
indekslemez ve sayfa sıralamalarını seyreltmez.
Bu sürece kanonikleştirme denir. Kanonik URL, router tarafından üretilen, yani koleksiyondaki OneWay bayrağı olmayan ilk uyan rotanın URL'sidir. Bu yüzden koleksiyonda önce birincil rotaları listeleriz.
Kanonikleştirmeyi presenter gerçekleştirir; daha fazlası kanonikleştirme bölümünde.
HTTPS
HTTPS protokolünü kullanmak için onu hosting'de etkinleştirmek ve sunucuyu doğru yapılandırmak gerekir.
Tüm sitenin HTTPS'e yönlendirilmesi sunucu düzeyinde, örneğin uygulamamızın kök dizinindeki .htaccess
dosyasıyla ve HTTP kodu 301 ile ayarlanmalıdır. Ayarlar hosting'e göre değişebilir ve aşağı yukarı şöyle
görünür:
<IfModule mod_rewrite.c>
RewriteEngine On
...
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
...
</IfModule>
Router, URL'leri sayfanın yüklendiği protokolün aynısıyla üretir, bu yüzden başka bir şey ayarlamaya gerek yoktur.
Ancak istisnai olarak farklı rotaların farklı protokoller altında çalışmasına ihtiyaç duyarsak, bunu rota maskesinde belirtiriz:
// HTTP adresi üretecek
$router->addRoute('http://%host%/<presenter>/<action>', /* ... */);
// HTTPS adresi üretecek
$router->addRoute('https://%host%/<presenter>/<action>', /* ... */);
Router'ın hata ayıklaması
Tracy Bar'da görünen yönlendirme paneli, rotaların listesini ve ayrıca router'ın URL'den elde ettiği parametreleri gösteren yararlı bir yardımcıdır.
✓ simgeli yeşil çubuk, geçerli URL'yi işleyen rotayı temsil eder; mavi renk ve ≈ simgesi ise, yeşil olan onların önüne geçmeseydi URL'yi işleyecek olan rotaları gösterir. Ayrıca geçerli presenter'ı ve eylemi görürüz.

Aynı zamanda kanonikleştirme nedeniyle beklenmedik bir yönlendirme olursa, panelin redirect çubuğuna bakmak yararlıdır; orada router'ın URL'yi başlangıçta nasıl anladığını ve neden yönlendirdiğini öğrenebilirsiniz.
Router'ın hata ayıklamasını yaparken, yönlendirmelerin orada saklanmaması için tarayıcıda Developer Tools'u açmanızı (Ctrl+Shift+I veya Cmd+Option+I) ve Network panelinde önbelleği kapatmanızı öneririz.
Performans
Rotaların sayısı router'ın hızını etkiler. Sayıları kesinlikle birkaç düzineyi aşmamalıdır. Sitenizin URL yapısı fazla karmaşıksa, kendi Kendi router'ınız'ınızı yazabilirsiniz.
Router'ın örneğin bir veritabanına bağımlılığı yoksa ve factory'si argüman almıyorsa, derlenmiş biçimini doğrudan DI konteynerine serileştirebilir ve böylece uygulamayı biraz hızlandırabiliriz.
routing:
cache: true
Kendi router'ınız
Aşağıdaki satırlar çok ileri düzey kullanıcılar içindir. Kendi router'ınızı oluşturabilir ve onu doğal olarak rota koleksiyonuna entegre edebilirsiniz. Router, iki metotlu Nette\Routing\Router arayüzünün bir uygulamasıdır:
use Nette\Http\IRequest as HttpRequest;
use Nette\Http\UrlScript;
class MyRouter implements Nette\Routing\Router
{
public function match(HttpRequest $httpRequest): ?array
{
// ...
}
public function constructUrl(array $params, UrlScript $refUrl): ?string
{
// ...
}
}
match metodu, yalnızca URL'nin değil header'ların vb. de elde edilebildiği geçerli istek $httpRequest'i, presenter adını ve parametrelerini içeren bir diziye işler.
İsteği işleyemezse null döndürür. İsteği işlerken en azından presenter'ı döndürmemiz gerekir; eylem isteğe
bağlıdır ve belirtilmezse default olur. Presenter adı tamdır ve varsa modülleri de içerir:
[
'presenter' => 'Front:Home',
'action' => 'default',
]
constructUrl metodu ise tam tersine, parametre dizisinden sonuçtaki mutlak URL'yi kurar. Geçerli URL olan $refUrl parametresindeki bilgilerden
yararlanabilir.
Onu rota koleksiyonuna add() ile ekleyin:
$router = new Nette\Application\Routers\RouteList;
$router->add($myRouter);
$router->addRoute(/* ... */);
// ...
Bağımsız kullanım
Bağımsız kullanımdan kastımız, router'ın yeteneklerinden Nette Application ve presenter'ları kullanmayan bir uygulamada yararlanmaktır. Bu bölümde gösterdiğimiz hemen her şey onun için de geçerlidir, şu farklarla:
- rota koleksiyonları için Nette\Routing\RouteList sınıfını kullanırız
- basit router olarak Nette\Routing\SimpleRouter sınıfını
Presenter:eylemçifti var olmadığından Gelişmiş yazım kullanırız
Yine router'ı bizim için kuracak bir metot oluştururuz, örneğin:
namespace App\Core;
use Nette\Routing\RouteList;
class RouterFactory
{
public static function createRouter(): RouteList
{
$router = new RouteList;
$router->addRoute('rss.xml', [
'controller' => 'RssFeedController',
]);
$router->addRoute('article/<id \d+>', [
'controller' => 'ArticleController',
]);
// ...
return $router;
}
}
Önerdiğimiz gibi bir DI konteyneri kullanıyorsanız, metodu yine yapılandırmaya ekleyin ve sonra router'ı HTTP isteğiyle birlikte konteynerden alın:
$router = $container->getByType(Nette\Routing\Router::class);
$httpRequest = $container->getByType(Nette\Http\IRequest::class);
Ya da nesneleri doğrudan oluşturun:
$router = App\Core\RouterFactory::createRouter();
$httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();
Şimdi geriye yalnızca router'ın işini yapmasına izin vermek kalıyor:
$params = $router->match($httpRequest);
if ($params === null) {
// uyan rota bulunamadı, 404 hatası gönder
exit;
}
// elde edilen parametreleri işle
$controller = $params['controller'];
// ...
Ve tersine, bir bağlantı kurmak için router'ı kullanın:
$params = ['controller' => 'ArticleController', 'id' => 123];
$url = $router->constructUrl($params, $httpRequest->getUrl());