Presenter'lar
Nette'te presenter'ların ve şablonların nasıl yazıldığını inceleyeceğiz. Okuduktan sonra şunları anlayacaksınız:
- presenter'ların nasıl çalıştığını
- kalıcı parametrelerin ne olduğunu
- şablonların nasıl render edildiğini
Presenter'ın bir web uygulamasının belirli bir sayfasını (ana sayfa, e-ticaret sitesindeki bir ürün, giriş formu, site haritası beslemesi vb.) temsil eden bir sınıf olduğunu artık biliyoruz. Bir uygulamada birden binlerce presenter olabilir. Başka framework'lerde bunlara controller da denir.
Genellikle presenter terimiyle, web arayüzleri üretmeye uygun olan ve bu bölümün geri kalanının odağı olacak Nette\Application\UI\Presenter sınıfının bir torununu kastederiz. Genel anlamda presenter, Nette\Application\IPresenter arayüzünü uygulayan herhangi bir nesnedir.
Presenter'ın yaşam döngüsü
Presenter'ın görevi bir isteği işlemek ve bir yanıt döndürmektir (bu bir HTML sayfası, bir görsel, bir yönlendirme vb. olabilir).
Yani önce ona bir istek verilir. Bu doğrudan HTTP isteği değil, HTTP isteğinin router yardımıyla dönüştürüldüğü bir Nette\Application\Request nesnesidir. Bu nesneyle genellikle doğrudan uğraşmayız, çünkü presenter isteğin işlenmesini şimdi inceleyeceğimiz başka metotlara akıllıca devreder.
Şema, varsa yukarıdan aşağıya sırayla çağrılan metotların listesini gösterir. Hiçbiri zorunlu değildir; tek bir metodu olmayan tamamen boş bir presenter'ınız olabilir ve üzerine basit bir statik site kurabilirsiniz.
__construct()
Constructor, nesnenin oluşturulduğu anda çağrıldığı için tam olarak presenter'ın yaşam döngüsüne ait değildir. Ancak önemi nedeniyle onu da anıyoruz. Constructor (inject metoduyla birlikte) bağımlılıkları aktarmaya yarar.
Presenter, uygulamanın iş mantığını üstlenmemeli, veritabanına yazmamalı veya ondan okumamalı, hesaplama
yapmamalıdır. Bu, model dediğimiz katmandaki sınıfların işidir. Örneğin bir ArticleRepository sınıfı
makaleleri yüklemekten ve kaydetmekten sorumlu olabilir. Presenter'ın onunla çalışabilmesi için ona bağımlılık enjeksiyonuyla aktarılması
gerekir:
class ArticlePresenter extends Nette\Application\UI\Presenter
{
public function __construct(
private ArticleRepository $articles,
) {
}
}
startup()
İstek alınır alınmaz startup() metodu çağrılır. Onu özellikleri ilklendirmek, kullanıcı izinlerini
denetlemek vb. için kullanabilirsiniz. Bu metodun her zaman üst sınıfını çağırması gerekir:
parent::startup().
action<Eylem>(args...)
render<Görünüm>() metoduna benzer. render<Görünüm>() ardından render edilecek
belirli bir şablon için veri hazırlamayı amaçlarken, action<Eylem>() bir isteği, ardından mutlaka bir
şablon render etmeden işler. Örneğin veriyi işleyebilir, kullanıcının oturumunu açıp kapatabilir vb. ve sonra başka bir yere yönlendirebilir.
Önemli olan, action<Eylem>()'in render<Görünüm>()'den önce
çağrılmasıdır. Bu, eylem metodunun içinde isteğin gidişatını değiştirebilmemizi sağlar; örneğin
setView('digerGorunum') ile render edilecek şablonu, hatta çağrılacak render<Görünüm>()
metodunu değiştirerek.
switch('digerEylem') metoduyla tamamen başka bir eyleme bile geçebilirsiniz. Bu, geçerli
metodu keser ve onun yerine yeni eylemin action<Eylem>() ve render<Görünüm>()
metotlarını çalıştırır (ve otomatik kanonikleştirmeyi kapatır). İsteğin kendisi
devam eder; yalnızca o an çalışan metot kesilir.
Metoda istekten gelen parametreler aktarılır. Bu parametreler için tip belirtmek mümkündür ve önerilir, örneğin
actionShow(int $id, ?string $slug = null). id parametresi eksikse veya tam sayı değilse, presenter 404 hatası döndürür ve sonlanır.
handle<Sinyal>(args...)
Bu metot, bileşenlere ayrılmış bölümde öğreneceğimiz sinyalleri işler. Öncelikle bileşenler ve AJAX isteklerinin işlenmesi içindir.
Metoda, action<Eylem>()'de olduğu gibi, tip denetimi dahil, istekten gelen parametreler aktarılır.
beforeRender()
beforeRender metodu, adının da söylediği gibi, her render<Görünüm>() metodundan önce
çağrılır. Ortak şablon ayarları, layout'a değişken aktarımı ve benzeri işler için kullanılır.
render<Görünüm>(args...)
Burada şablonu ardından render edilmek üzere hazırlar, ona veri aktarırız vb.
Metoda, action<Eylem>()'de olduğu gibi, tip denetimi dahil, istekten gelen parametreler aktarılır.
public function renderShow(int $id): void
{
// model'den veriyi al ve şablona aktar
$this->template->article = $this->articles->getById($id);
}
afterRender()
afterRender metodu, adının yine söylediği gibi, her render<Görünüm>() metodundan sonra
çağrılır. Oldukça ender kullanılır.
shutdown()
Presenter'ın yaşam döngüsünün sonunda çağrılır.
Olaylar
Presenter'ın yaşam döngüsünün parçası olarak çağrılan startup(), beforeRender() ve
shutdown() metotlarının yanı sıra, otomatik çağrılacak başka fonksiyonlar da tanımlanabilir. Presenter, olaylar denilen şeyleri tanımlar; işleyicilerini
$onStartup, $onRender ve $onShutdown dizilerine eklersiniz.
class ArticlePresenter extends Nette\Application\UI\Presenter
{
public function __construct()
{
$this->onStartup[] = function () {
// ...
};
}
}
$onStartup dizisindeki işleyiciler startup() metodundan hemen önce, $onRender
işleyicileri beforeRender() ile render<Görünüm>() arasında ve son olarak
$onShutdown işleyicileri shutdown()'dan hemen önce çağrılır.
Devam etmeden önce bir öneri: Gördüğünüz gibi bir presenter birden fazla eylemi/görünümü işleyebilir, yani
birden fazla render<Görünüm>() metoduna sahip olabilir. Ancak presenter'ları tek veya olabildiğince az
eylemle tasarlamanızı öneririz.
Yanıt gönderme
Presenter'ın yanıtı genellikle bir şablonun HTML sayfasına render edilmesidir, ama bir dosya, JSON gönderimi, hatta başka bir sayfaya yönlendirme de olabilir.
Yaşam döngüsünün herhangi bir noktasında, aşağıdaki metotlardan birini kullanarak bir yanıt gönderip presenter'ı aynı anda sonlandırabiliriz:
redirect(),redirectPermanent(),redirectUrl()veforward()bir yönlendirme gerçekleştirirerror()presenter'ı bir hata nedeniyle sonlandırırsendJson($data)presenter'ı sonlandırır ve veriyi JSON formatında gönderirsendTemplate()presenter'ı sonlandırır ve şablonu hemen render edersendResponse($response)presenter'ı sonlandırır ve kendi yanıtınızı gönderirterminate()presenter'ı yanıtsız sonlandırır
Bu metotların her biri, sessiz sonlandırma istisnası Nette\Application\AbortException'ı fırlatarak
presenter'ı hemen sonlandırır.
Bu metotlardan hiçbirini çağırmazsanız, presenter otomatik olarak şablonu render etmeye geçer. Neden? Çünkü vakaların %99'unda bir şablon render etmek isteriz, bu yüzden presenter işimizi kolaylaştırmak için bu davranışı varsayılan olarak benimser.
Bağlantı oluşturma
Presenter'ın, başka presenter'lara URL bağlantıları oluşturmaya yarayan bir link() metodu vardır. İlk
parametre hedef presenter ve eylemdir, ardından dizi olarak da aktarılabilen argümanlar gelir:
$url = $this->link('Product:show', $id);
$url = $this->link('Product:show', [$id, 'lang' => 'en']);
Şablonda başka presenter'lara ve eylemlere bağlantılar şöyle oluşturulur:
<a n:href="Product:show $id">ürün detayı</a>
Gerçek URL yerine tanıdık Presenter:eylem çiftini yazın ve gerekli parametreleri ekleyin. İşin püf
noktası, Latte'ye bu niteliği işlemesini ve gerçek URL'yi üretmesini söyleyen n:href'tir. Nette'te URL'leri
hiç düşünmeniz gerekmez, yalnızca presenter'ları ve eylemleri.
Daha fazla bilgiyi URL bağlantıları oluşturma bölümünde bulabilirsiniz.
Yönlendirme
Başka bir presenter'a geçmek için redirect() ve forward() metotları kullanılır. Sözdizimleri
link() metodununkine çok benzer.
forward() metodu, HTTP yönlendirmesi olmadan hemen yeni presenter'a geçer:
$this->forward('Product:show');
HTTP kodu 302 ile geçici yönlendirme örneği (geçerli istek yöntemi POST ise 303):
$this->redirect('Product:show', $id);
HTTP kodu 301 ile kalıcı yönlendirme için şunu kullanın:
$this->redirectPermanent('Product:show', $id);
redirectUrl() metoduyla uygulamanın dışındaki başka bir URL'ye yönlendirebilirsiniz. HTTP kodu ikinci
parametre olarak belirtilebilir; varsayılan 302'dir (geçerli istek yöntemi POST ise 303).
$this->redirectUrl('https://nette.org');
Yönlendirme, sessiz sonlandırma istisnası denilen Nette\Application\AbortException'ı fırlatarak presenter'ın
çalışmasını hemen sonlandırır.
Yönlendirmeden önce Flash mesajları, yani yönlendirmeden sonra şablonda gösterilecek mesajlar gönderilebilir.
Flash mesajları
Bunlar genellikle bir işlemin sonucunu bildiren mesajlardır. Flash mesajlarının önemli bir özelliği, yönlendirmeden sonra da şablonda erişilebilir kalmalarıdır. Gösterildikten sonra 30 saniye daha etkin kalırlar; örneğin kullanıcı bir aktarım hatası yüzünden sayfayı yenilerse mesaj hemen kaybolmaz.
flashMessage()
metodunu çağırmanız yeterli, onu şablona aktarmayı presenter üstlenir. İlk parametre mesajın metni, isteğe bağlı
ikinci parametre ise tipidir (örneğin error, warning, info). flashMessage() metodu flash mesajın örneğini
döndürür, böylece ek bilgiler eklenebilir.
$this->flashMessage('Öğe silindi.');
$this->redirect(/* ... */); // ve yönlendir
Şablonda bu mesajlar $flashes değişkeninde, message (mesaj metni), type (mesaj tipi)
ve muhtemelen daha önce sözü geçen kullanıcı bilgilerini içeren stdClass nesneleri olarak sunulur. Onları
şöyle render ederiz:
{foreach $flashes as $flash}
<div class="flash {$flash->type}">{$flash->message}</div>
{/foreach}
Hata 404 vb.
İstek yerine getirilemiyorsa, örneğin göstermek istediğimiz makale veritabanında yoksa,
error(string $message = '', int $httpCode = 404) metoduyla 404 hatası fırlatırız.
public function renderShow(int $id): void
{
$article = $this->articles->getById($id);
if (!$article) {
$this->error();
}
// ...
}
HTTP hata kodu ikinci parametre olarak aktarılabilir; varsayılan 404'tür. Metot, bir
Nette\Application\BadRequestException fırlatarak çalışır; ardından Application denetimi error
presenter'a devreder. Bu, oluşan hatayı bildiren bir sayfa göstermekle görevli bir presenter'dır. Error presenter, uygulama yapılandırmasında ayarlanır.
JSON gönderme
sendJson($data) metodu, verilen veriyi JSON'a kodlar, HTTP yanıtı olarak gönderir ve presenter'ı
sonlandırır. Örnek:
public function actionData(): void
{
$data = ['hello' => 'nette'];
$this->sendJson($data);
}
İsteğin parametreleri
Presenter, ve her bileşen de, parametrelerini HTTP isteğinden alır. Değerlerini getParameter($name) veya
getParameters() metotlarıyla elde edebilirsiniz. Değerler dizelerdir veya dize dizileridir, yani doğrudan URL'den
alınan ham veridir.
Daha fazla rahatlık için parametrelere özellikler üzerinden erişmenizi öneririz. Onları #[Parameter]
niteliğiyle işaretlemeniz yeterlidir:
use Nette\Application\Attributes\Parameter; // bu satır önemli
class HomePresenter extends Nette\Application\UI\Presenter
{
#[Parameter]
public string $theme; // public olmalı
}
Özellik için veri tipini (örneğin string) belirtmenizi öneririz; Nette değeri buna göre otomatik
dönüştürür. Parametre değerleri ayrıca doğrulanabilir.
Bağlantı oluştururken parametrenin değerini doğrudan ayarlayabilirsiniz:
<a n:href="Home:default theme: dark">tıkla</a>
Kalıcı parametreler
Kalıcı parametreler, durumu farklı istekler boyunca korumak için kullanılır. Değerleri, bir bağlantıya tıklandıktan
sonra da aynı kalır. Oturum verilerinin aksine URL'de aktarılırlar. Ve bu tamamen otomatik gerçekleşir, bu yüzden onları
link() veya n:href içinde açıkça belirtmeye gerek yoktur.
Örnek bir kullanım? Çok dilli bir uygulamanız olduğunu düşünün. Geçerli dil, URL'nin her zaman parçası olması
gereken bir parametredir. Ama onu her bağlantıya yazmak inanılmaz sıkıcı olurdu. Bu yüzden onu lang kalıcı
parametresi yaparsınız ve otomatik olarak taşınır. Şahane!
Nette'te kalıcı parametre oluşturmak son derece basittir. Public bir özellik oluşturup onu nitelikle işaretlemeniz
yeterlidir: (önceden /** @persistent */ kullanılıyordu)
use Nette\Application\Attributes\Persistent; // bu satır önemli
class ProductPresenter extends Nette\Application\UI\Presenter
{
#[Persistent]
public string $lang; // public olmalı
}
$this->lang örneğin 'en' değerini taşıyorsa, link() veya n:href ile
oluşturulan bağlantılar da lang=en parametresini içerecektir. Ve bağlantıya tıklandıktan sonra
$this->lang yine 'en' olacaktır.
Özellik için veri tipini (örneğin string) belirtmenizi öneririz, ayrıca bir varsayılan değer de
verebilirsiniz. Parametre değerleri doğrulanabilir.
Kalıcı parametreler genellikle ilgili presenter'ın tüm eylemleri arasında aktarılır. Onları birden fazla presenter arasında da aktarmak için, ya:
- presenter'ların kalıtım aldığı ortak bir atada
- ya da presenter'ların kullandığı bir trait'te tanımlanmaları gerekir:
trait LanguageAware
{
#[Persistent]
public string $lang;
}
class ProductPresenter extends Nette\Application\UI\Presenter
{
use LanguageAware;
}
Bağlantı oluştururken kalıcı parametrenin değeri değiştirilebilir:
<a n:href="Product:show $id, lang: cs">Çekçe detay</a>
Ya da sıfırlanabilir, yani URL'den kaldırılabilir. O zaman varsayılan değerini alır:
<a n:href="Product:show $id, lang: null">tıkla</a>
Ortak parametre alanı
İsteğin parametreleri, kalıcı parametreler ve action,
render ile handle (sinyal) metotlarının parametreleri tek bir alanı paylaşır; her biri adıyla
tanımlanır. Aynı ad birden fazlasında geçerse, hepsi bir ve aynı değere karşılık gelir.
Bu sıkça avantaja çevrilir. Örneğin lang kalıcı parametresi ile bir eylem ya da sinyal metodunun
$lang argümanı bir ve aynıdır; kalıcı bir parametrenin geçerli değerini, onu yalnızca metot imzasına
yazarak okuyabilirsiniz:
#[Persistent]
public string $lang;
public function handleSearch(string $query, string $lang): void
{
// $lang, lang kalıcı parametresinin geçerli değerini taşır
}
Bu alan paylaşıldığı için, bilinçli olarak aynı değeri paylaşmalarını istemiyorsanız parametre adlarını benzersiz tutun. Bu, ayrıca isteğin POST gövdesinden de parametre okuyan sinyaller için de geçerlidir; bkz. Sinyaller derinlemesine.
Etkileşimli bileşenler
Presenter'ların yerleşik bir bileşen sistemi vardır. Bileşenler, presenter'lara gömdüğümüz ayrı ve yeniden kullanılabilir birimlerdir. Formlar, datagrid'ler, menüler, kısacası tekrar tekrar kullanmanın anlamlı olduğu her şey olabilirler.
Bileşenler presenter'lara nasıl gömülür ve sonra nasıl kullanılır? Bunu Bileşenler bölümünde öğreneceksiniz. Hatta Hollywood ile neyi ortak yaptıklarını da öğreneceksiniz.
Peki bileşenleri nereden bulurum? Componette üzerinde, framework topluluğundan gönüllülerin katkıda bulunduğu açık kaynak bileşenleri ve Nette için birçok başka eklentiyi bulacaksınız.
Daha derine
Bu bölümde şu ana kadar ele aldıklarımız çoğu kullanım için yeterli olacaktır. Aşağıdaki kısımlar, presenter'lara daha derinlemesine dalmak ve kesinlikle her şeyi bilmek isteyenler içindir.
Parametrelerin doğrulanması
URL'lerden alınan İsteğin parametreleri ve Kalıcı parametreler değerleri özelliklere loadState() metoduyla yazılır. Bu
metot ayrıca özellikte belirtilen veri tipinin uyup uymadığını denetler; uymuyorsa 404 hatasıyla yanıt verir ve sayfa
gösterilmez.
URL'den gelen parametrelere asla körü körüne güvenmeyin, çünkü kullanıcı onları kolayca değiştirebilir. Örneğin
$this->lang dilinin desteklenenler arasında olup olmadığını böyle doğrularız. Bunun uygun bir yolu, sözü
geçen loadState() metodunu ezmektir:
class ProductPresenter extends Nette\Application\UI\Presenter
{
#[Persistent]
public string $lang;
public function loadState(array $params): void
{
parent::loadState($params); // $this->lang burada ayarlanır
// ardından kendi değer denetimimiz gelir:
if (!in_array($this->lang, ['en', 'cs'])) {
$this->error();
}
}
}
İsteğin kaydedilmesi ve geri yüklenmesi
Presenter'ın işlediği istek, presenter'ın getRequest() metodunun döndürdüğü bir Nette\Application\Request nesnesidir.
Geçerli istek oturuma kaydedilebilir, ya da tersine oturumdan geri yüklenip presenter'a yeniden yürüttürülebilir. Bu,
örneğin kullanıcı bir formu doldururken oturumunun süresi dolduğunda işe yarar. Veri kaybını önlemek için, giriş
sayfasına yönlendirmeden önce geçerli isteği $reqId = $this->storeRequest() ile oturuma kaydederiz. Bu,
isteğin tanımlayıcısını kısa bir dize olarak döndürür; onu giriş presenter'ına parametre olarak aktarırız.
Girişten sonra $this->restoreRequest($reqId) metodunu çağırırız; bu metot isteği oturumdan alır. POST
istekleri ona iletilir, diğerleri (GET) ise isteğin URL'sine yönlendirilir. Metot, isteğin şu anda oturum açmış olan
kullanıcının kendisi tarafından oluşturulduğunu doğrular. Başka bir kullanıcı giriş yaparsa veya anahtar geçersizse
hiçbir şey yapmaz ve program her zamanki gibi devam eder.
Önceki sayfaya nasıl dönülür kılavuzuna bakın.
Kanonikleştirme
Presenter'ların, daha iyi SEO'ya (arama motoru optimizasyonuna) katkıda bulunan gerçekten mükemmel bir özelliği vardır.
Aynı içeriğin farklı URL'lerde bulunmasını otomatik olarak engellerler. Belirli bir hedefe birden fazla URL gidiyorsa,
örneğin /index ve /index?page=1, framework bunlardan birini birincil (kanonik) sayar ve diğerlerini
HTTP kodu 301 ile ona yönlendirir. Bu sayede arama motorları sayfalarınızı iki kez indekslemez ve sayfa sıralamanızı
seyreltmez.
Bu sürece kanonikleştirme denir. Kanonik URL, router tarafından üretilen, genellikle koleksiyondaki ilk uyan rotanın URL'sidir.
Kanonikleştirme varsayılan olarak etkindir ve $this->autoCanonicalize = false ile kapatılabilir.
AJAX veya POST istekleri sırasında yönlendirme yapılmaz, çünkü bu veri kaybına yol açabilir ya da SEO açısından ek bir değer sunmaz.
Kanonikleştirmeyi canonicalize() metoduyla elle de tetikleyebilirsiniz. link() metoduna benzer
şekilde ona presenter'ı, eylemi ve parametreleri verirsiniz. Bir bağlantı üretir ve onu geçerli URL adresiyle
karşılaştırır. Farklılarsa üretilen bağlantıya yönlendirir.
public function actionShow(int $id, ?string $slug = null): void
{
$realSlug = $this->facade->getSlugForId($id);
// $slug, $realSlug'dan farklıysa yönlendirir
$this->canonicalize('Product:show', [$id, $realSlug]);
}
SEO dostu URL'ler üretmek için rota filtrelerini canonicalize() ile birleştiren eksiksiz bir desen için Slug'lu güzel URL'ler bölümüne bakın.
Yanıtlar
Presenter'ın döndürdüğü yanıt, Nette\Application\Response arayüzünü uygulayan bir nesnedir. Hazır birkaç yanıt vardır:
- Nette\Application\Responses\CallbackResponse – bir callback gönderir
- Nette\Application\Responses\FileResponse – dosyayı gönderir
- Nette\Application\Responses\ForwardResponse – forward()
- Nette\Application\Responses\JsonResponse – JSON gönderir
- Nette\Application\Responses\RedirectResponse – yönlendirme
- Nette\Application\Responses\TextResponse – metin gönderir
- Nette\Application\Responses\VoidResponse – boş yanıt
Yanıtlar sendResponse() metoduyla gönderilir:
use Nette\Application\Responses;
// Düz metin
$this->sendResponse(new Responses\TextResponse('Hello Nette!'));
// Dosya gönderir
$this->sendResponse(new Responses\FileResponse(__DIR__ . '/invoice.pdf', 'Invoice13.pdf'));
// Callback gönderir
$callback = function (Nette\Http\IRequest $httpRequest, Nette\Http\IResponse $httpResponse) {
if ($httpResponse->getHeader('Content-Type') === 'text/html') {
echo '<h1>Hello</h1>';
}
};
$this->sendResponse(new Responses\CallbackResponse($callback));
Kendi yanıtınızı da yazabilirsiniz. HTTP isteğini ve yanıtını alan tek bir send() metoduna sahip
Nette\Application\Response arayüzünü uygulamanız yeterlidir. Bu, örneğin bellekte tutmak istemediğiniz veriyi
akışla gönderirken işe yarar:
class CsvResponse implements Nette\Application\Response
{
public function __construct(
private string $fileName,
private iterable $rows,
) {
}
public function send(Nette\Http\IRequest $request, Nette\Http\IResponse $response): void
{
$response->setContentType('text/csv', 'utf-8');
$response->sendAsFile($this->fileName);
$handle = fopen('php://output', 'w');
foreach ($this->rows as $row) {
fputcsv($handle, $row);
}
fclose($handle);
}
}
Sonra onu presenter'da her zamanki gibi
gönderirsiniz: $this->sendResponse(new CsvResponse('export.csv', $rows));
HTTP önbelleklemesi
lastModified() metodu, HTTP önbelleklemesinden kolayca yararlanmayı sağlar. Ona içeriğin son değiştirilme
tarih ve saatini (marka zamanı, dize veya DateTimeInterface nesnesi olarak), isteğe bağlı olarak bir ETag
doğrulayıcısını (içeriğin geçerli sürümünü tanımlayan kısa bir dize, örneğin hash'i) ve bir sona erme süresini
verirsiniz. Tarayıcı zaten uyan bir sürüme sahipse, presenter 304 Not Modified yanıtı gönderir ve sonlanır;
böylece sayfa gereksiz yere render edilmez veya aktarılmaz:
public function renderArticle(int $id): void
{
$article = $this->articles->getById($id);
$this->lastModified($article->updatedAt);
// ...
}
Şablonun tamamlanması
Presenter bir şablonu render ederken, sendTemplate() metodu render'dan hemen önce
completeTemplate()'i çağırır. Bu metot #[TemplateVariable] niteliğiyle işaretlenmiş
değişkenleri doldurur ve şablon dosyasını bulur (varsayılan değişkenler, şablon oluşturulurken zaten
TemplateFactory tarafından ayarlanır). Tüm görünümlerde ortak değişkenler eklemek veya farklı bir dosya
belirlemek için bu protected metodu ezebilirsiniz:
protected function completeTemplate(Nette\Application\UI\Template $template): void
{
parent::completeTemplate($template);
$template->siteName = 'Uygulamam';
}
#[Requires] ile erişimi kısıtlama
#[Requires] niteliği, presenter'lara ve metotlarına erişimi kısıtlamak için gelişmiş seçenekler sunar.
HTTP metotlarını belirtmek, AJAX isteği zorunlu kılmak, aynı origin'e kısıtlamak ve yalnızca forward yoluyla erişime izin
vermek için kullanılabilir. Nitelik hem presenter sınıflarına hem de action<Eylem>(),
render<Görünüm>(), handle<Sinyal>() ve createComponent<Ad>() gibi tek
tek metotlara uygulanabilir.
Şu kısıtlamaları belirtebilirsiniz:
- HTTP metotlarına:
#[Requires(methods: ['GET', 'POST'])] - AJAX isteği zorunluluğu:
#[Requires(ajax: true)] - yalnızca aynı origin'den erişim:
#[Requires(sameOrigin: true)] - yalnızca forward yoluyla erişim:
#[Requires(forward: true)] - belirli eylemlere kısıtlama:
#[Requires(actions: 'default')]
3.3 sürümünden beri aynı origin eşleşmesi, tarayıcının Sec-Fetch-Site header'ı
kullanılarak doğrulanır (önceden bir SameSite çerezi üzerinden); bu daha güvenilirdir ve şemanın, alan adının ve portun
tam eşleşmesini denetler.
Ayrıntıları Requires niteliği nasıl kullanılır kılavuzunda bulabilirsiniz.
HTTP metodunun denetimi
Nette'teki presenter'lar, öncelikle güvenlik nedeniyle, gelen her isteğin HTTP metodunu otomatik doğrular. Varsayılan
olarak GET, POST, HEAD, PUT, DELETE, PATCH
metotlarına izin verilir.
Ek olarak örneğin OPTIONS metoduna da izin vermek isterseniz #[Requires] niteliğini kullanın
(Nette Application v3.2.3'ten beri):
#[Requires(methods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])]
class MyPresenter extends Nette\Application\UI\Presenter
{
}
3.1.13 sürümünden beri doğrulama, istekte belirtilen metodun $presenter->allowedMethods dizisinde bulunup
bulunmadığını denetleyen checkHttpMethod() içinde yapılır. 3.2.3 sürümünden itibaren bu yaklaşım
#[Requires] lehine kullanımdan kaldırılmıştır. Metodu şöyle ezebilirsiniz:
class MyPresenter extends Nette\Application\UI\Presenter
{
protected function checkHttpMethod(): void
{
$this->allowedMethods[] = 'OPTIONS';
parent::checkHttpMethod();
}
}
Şunu vurgulamak önemli: OPTIONS metodunu etkinleştirirseniz, ardından onu presenter'ınızda uygun şekilde
işlemeniz gerekir. Bu metot sıklıkla preflight isteği olarak kullanılır; tarayıcı, isteğin CORS (Cross-Origin Resource
Sharing) politikasına göre izin verilebilir olup olmadığını belirlemek gerektiğinde asıl istekten önce onu otomatik
gönderir. Metodu etkinleştirip doğru yanıtı uygulamazsanız, bu tutarsızlıklara ve olası güvenlik sorunlarına yol
açabilir.
Kullanımdan kaldırılan eylemleri işaretleme
#[Deprecated] niteliği; eylemleri, sinyalleri veya tüm presenter'ları kullanımdan kaldırılmış ve ileride
silinmek üzere planlanmış diye işaretler. Uygulamanın kullanımdan kaldırılmış bölümlerine bağlantı üretilirken
Nette, geliştiricileri uyarmak için bir uyarı fırlatır.
Niteliği ya tüm presenter sınıfına ya da tek tek action<Eylem>(),
render<Görünüm>() ve handle<Sinyal>() metotlarına uygulayabilirsiniz.