Uygulamalar Nasıl Çalışır?

Şu anda Nette dokümantasyonunun temel sayfasını okuyorsunuz. Web uygulamalarının çalışma prensibini öğreneceksiniz. A'dan Z'ye, başlangıç anından PHP betiğinin son nefesine kadar. Okuduktan sonra şunları bileceksiniz:

  • her şey nasıl çalışır
  • Bootstrap, Presenter ve DI konteynerinin ne olduğu
  • dizin yapısının nasıl göründüğü

Dizin Yapısı

WebProject adlı web uygulaması iskelet örneğini açın ve okurken bahsedilen dosyalara bakabilirsiniz.

Dizin yapısı aşağı yukarı şöyle görünür:

web-project/
├── app/                      ← uygulama dizini
│   ├── Core/                 ← çalışması için gerekli temel sınıflar
│   │   └── RouterFactory.php ← URL adreslerinin yapılandırılması
│   ├── Presentation/         ← presenter'lar, şablonlar ve ilgili dosyalar
│   │   ├── @layout.latte     ← düzen şablonu
│   │   └── Home/             ← Home presenter dizini
│   │       ├── HomePresenter.php ← Home presenter sınıfı
│   │       └── default.latte ← default eyleminin şablonu
│   └── Bootstrap.php         ← Bootstrap başlatma sınıfı
├── bin/                      ← komut satırından çalıştırılan betikler
├── config/                   ← yapılandırma dosyaları
│   ├── common.neon
│   └── services.neon
├── log/                      ← günlüğe kaydedilen hatalar
├── temp/                     ← geçici dosyalar, önbellek, …
├── vendor/                   ← Composer tarafından kurulan kütüphaneler
│   ├── ...
│   └── autoload.php          ← kurulan tüm paketlerin otomatik yüklenmesi
├── www/                      ← genel dizin veya projenin document-root'u
│   ├── .htaccess             ← mod_rewrite kuralları
│   └── index.php             ← uygulamanın başlatıldığı ilk dosya
└── .htaccess                 ← www dışındaki tüm dizinlere erişimi yasaklar

Dizin yapısını istediğiniz gibi değiştirebilir, klasörleri yeniden adlandırabilir veya taşıyabilirsiniz, tamamen esnektir. Nette ayrıca akıllı otomatik algılamaya sahiptir ve URL tabanı da dahil olmak üzere uygulamanın konumunu otomatik olarak tanır.

Biraz daha büyük uygulamalarda, presenter ve şablon klasörlerini alt dizinlere ayırabilir ve sınıfları modül dediğimiz isim alanlarına bölebiliriz.

www/ dizini, projenin sözde genel dizinini veya document-root'unu temsil eder. Uygulama tarafında başka bir şey ayarlamaya gerek kalmadan yeniden adlandırabilirsiniz. Yalnızca hosting'i yapılandırmak gerekir, böylece document-root bu dizine işaret eder.

WebProject'i Nette dahil olmak üzere doğrudan Composer kullanarak da indirebilirsiniz:

composer create-project nette/web-project

Linux veya macOS'ta, log/ ve temp/ dizinlerine yazma izinlerini ayarlayın.

WebProject uygulaması çalışmaya hazırdır, hiçbir şey yapılandırmaya gerek yoktur ve www/ klasörüne erişerek doğrudan tarayıcıda görüntüleyebilirsiniz.

HTTP İsteği

Her şey, kullanıcının tarayıcıda bir sayfa açmasıyla başlar. Yani tarayıcı bir HTTP isteği ile sunucuya dokunduğunda. İstek, genel www/ dizininde bulunan tek bir PHP dosyasına, yani index.php'ye yönlendirilir. Diyelim ki istek https://example.com/product/123 adresine yapıldı. Uygun sunucu yapılandırması sayesinde, bu URL bile index.php dosyasına eşlenir ve yürütülür.

Görevi şudur:

  1. ortamı başlatmak
  2. fabrikayı almak
  3. isteği işleyecek Nette uygulamasını başlatmak

Hangi fabrika? Traktör üretmiyoruz, web sayfaları üretiyoruz! Sabırlı olun, hemen açıklanacak.

“Ortamı başlatmak” ifadesiyle, örneğin hataları günlüğe kaydetmek veya görselleştirmek için harika bir araç olan Tracy'nin etkinleştirilmesini kastediyoruz. Üretim sunucusunda hataları günlüğe kaydeder, geliştirme sunucusunda doğrudan görüntüler. Dolayısıyla başlatma, web sitesinin üretim veya geliştirme modunda çalışıp çalışmadığına karar vermeyi de içerir. Bunun için Nette akıllı otomatik algılama kullanır: web sitesini localhost'ta çalıştırırsanız, geliştirme modunda çalışır. Bu nedenle hiçbir şey yapılandırmanıza gerek yoktur ve uygulama hem geliştirme hem de canlı dağıtım için hemen hazırdır. Bu adımlar Bootstrap sınıfı hakkındaki bölümde gerçekleştirilir ve ayrıntılı olarak açıklanır.

Üçüncü nokta (evet, ikincisini atladık, ama ona geri döneceğiz) uygulamayı başlatmaktır. Nette'de HTTP isteklerini işlemekten Nette\Application\Application sınıfı (bundan sonra Application olarak anılacaktır) sorumludur, bu yüzden uygulamayı başlatmak dediğimizde, özellikle bu sınıfın nesnesinde anlamlı bir ada sahip run() metodunu çağırmayı kastediyoruz.

Nette, sizi kanıtlanmış metodolojilere göre temiz uygulamalar yazmaya yönlendiren bir akıl hocasıdır. Ve bu kesinlikle en kanıtlanmış olanlardan biri dependency injection (bağımlılık enjeksiyonu), kısaca DI olarak adlandırılır. Şu anda sizi DI'yi açıklamakla yormak istemiyoruz, bunun için ayrı bir bölüm var, önemli olan sonuç, temel nesnelerin genellikle DI konteyner (kısaca DIC) olarak adlandırılan bir nesne fabrikası tarafından oluşturulacağıdır. Evet, bu az önce bahsedilen fabrika. Ve bize Application nesnesini de üretecek, bu yüzden önce konteynere ihtiyacımız var. Onu Configurator sınıfını kullanarak alırız ve Application nesnesini üretmesine izin veririz, üzerinde run() metodunu çağırırız ve böylece Nette uygulaması başlar. Tam olarak bu, index.php dosyasında olur.

Nette Application

Application sınıfının tek bir görevi vardır: HTTP isteğine yanıt vermek.

Nette'de yazılan uygulamalar, her biri web sitesinin belirli bir sayfasını temsil eden birçok sözde presenter'a (diğer framework'lerde controller terimiyle karşılaşabilirsiniz, aynı şeydir) bölünür: örn. ana sayfa; e-ticaretteki bir ürün; giriş formu; site haritası beslemesi vb. Bir uygulamanın bir ila binlerce presenter'ı olabilir.

Application, mevcut isteği işlemek için hangi presenter'a ileteceğine karar vermesi için sözde yönlendiriciye (router) sorarak başlar. Yönlendirici, bunun kimin sorumluluğu olduğuna karar verir. Giriş URL'si https://example.com/product/123'e bakar ve nasıl ayarlandığına bağlı olarak, bunun örneğin id: 123 olan ürünü görüntüleme (eylem) isteyeceği presenter Product'ın işi olduğuna karar verir. Presenter + eylem çiftini iki nokta üst üste ile Product:show olarak yazmak iyi bir alışkanlıktır.

Yani yönlendirici, URL'yi Presenter:action + parametreler çiftine dönüştürdü, bizim durumumuzda Product:show + id: 123. Böyle bir yönlendiricinin nasıl göründüğünü app/Core/RouterFactory.php dosyasında görebilirsiniz ve onu Yönlendirme bölümünde ayrıntılı olarak açıklıyoruz.

Devam edelim. Application artık presenter'ın adını biliyor ve devam edebilir. ProductPresenter sınıfının nesnesini üreterek, ki bu presenter Product'ın kodudur. Daha doğrusu, presenter'ı üretmesi için DI konteynerine sorar, çünkü üretmek onun işidir.

Presenter şöyle görünebilir:

class ProductPresenter extends Nette\Application\UI\Presenter
{
	public function __construct(
		private ProductRepository $repository,
	) {
	}

	public function renderShow(int $id): void
	{
		// modelden verileri alır ve şablona iletiriz
		$this->template->product = $this->repository->getProduct($id);
	}
}

İsteğin işlenmesini presenter devralır. Ve görev açıktır: id: 123 ile show eylemini gerçekleştirin. Bu, presenter'ların dilinde, renderShow() metodunun çağrılacağı ve $id parametresinde 123 alacağı anlamına gelir.

Presenter birden fazla eylemi işleyebilir, yani birden fazla render<Eylem>() metoduna sahip olabilir. Ancak, bir veya mümkün olduğunca az eyleme sahip presenter'lar tasarlamanızı öneririz.

Yani, renderShow(123) metodu çağrıldı, kodu hayali bir örnek olsa da, verilerin şablona nasıl iletildiğini, yani $this->template'e yazılarak görebilirsiniz.

Ardından presenter yanıtı döndürür. Bu bir HTML sayfası, bir resim, bir XML belgesi, diskten bir dosya gönderimi, JSON veya başka bir sayfaya yönlendirme olabilir. Önemli olan, açıkça nasıl yanıt vereceğini söylemezsek (ki bu ProductPresenter durumudur), yanıtın bir HTML sayfasıyla şablonun oluşturulması olacağıdır. Neden? Çünkü vakaların %99'unda bir şablon oluşturmak istiyoruz, bu yüzden presenter bu davranışı varsayılan olarak kabul eder ve işimizi kolaylaştırmak ister. Nette'nin amacı budur.

Hangi şablonun oluşturulacağını bile belirtmemize gerek yok, yolunu kendisi türetir. show eylemi durumunda, ProductPresenter sınıfıyla aynı dizindeki show.latte şablonunu basitçe yüklemeye çalışır. Ayrıca @layout.latte dosyasındaki düzeni bulmaya çalışır (şablonları bulma hakkında daha fazla bilgi).

Ve ardından şablonları oluşturur. Böylece presenter'ın ve tüm uygulamanın görevi tamamlanır ve iş biter. Şablon mevcut değilse, 404 hata sayfası döndürülür. Presenter'lar hakkında daha fazla bilgiyi Presenter'lar sayfasında okuyabilirsiniz.

Emin olmak için, tüm süreci biraz farklı bir URL ile özetleyelim:

  1. URL https://example.com olacak
  2. uygulamayı başlatırız, konteyner oluşturulur ve Application::run() çalıştırılır
  3. yönlendirici URL'yi Home:default çifti olarak kodlar
  4. HomePresenter sınıfının nesnesi oluşturulur
  5. renderDefault() metodu çağrılır (varsa)
  6. örneğin @layout.latte düzeniyle default.latte şablonu oluşturulur

Şimdi birçok yeni terimle karşılaşmış olabilirsiniz, ancak anlamlı olduklarına inanıyoruz. Nette'de uygulama oluşturmak son derece keyiflidir.

Şablonlar

Şablonlardan bahsetmişken, Nette'de Latte şablonlama sistemi kullanılır. Bu nedenle şablonlarda .latte uzantıları bulunur. Latte kullanılır çünkü hem PHP için en güvenli şablonlama sistemidir hem de en sezgisel sistemdir. Çok fazla yeni şey öğrenmenize gerek yok, PHP bilginiz ve birkaç etiket yeterlidir. Her şeyi belgelerde öğreneceksiniz.

Şablonda, diğer presenter'lara ve eylemlere bağlantılar oluşturulur şu şekilde:

<a n:href="Product:show $productId">ürün detayı</a>

Sadece gerçek URL yerine bilinen Presenter:action çiftini yazın ve olası parametreleri belirtin. İşin püf noktası, bu niteliğin Nette tarafından işleneceğini söyleyen n:href'tir. Ve şunu oluşturur:

<a href="/product/456">ürün detayı</a>

URL oluşturmaktan daha önce bahsedilen yönlendirici sorumludur. Aslında, Nette'deki yönlendiriciler olağanüstüdür çünkü yalnızca URL'den presenter:action çiftine dönüşümler yapmakla kalmaz, aynı zamanda tersini de yapabilirler, yani presenter adı + eylem + parametrelerden bir URL oluşturabilirler. Bu sayede Nette'de, şablonda veya presenter'da tek bir karakteri bile değiştirmeden tüm hazır uygulamanın URL şekillerini tamamen değiştirebilirsiniz. Sadece yönlendiriciyi düzenleyerek. Ayrıca bu sayede, Nette'nin başka bir benzersiz özelliği olan ve farklı URL'lerde yinelenen içeriğin varlığını otomatik olarak önleyerek daha iyi SEO'ya (arama motoru optimizasyonu) katkıda bulunan sözde kanonikleştirme çalışır. Birçok programcı bunu şaşırtıcı buluyor.

Interaktif Bileşenler

Presenter'lar hakkında size bir şey daha söylemeliyiz: yerleşik bir bileşen sistemleri vardır. Delphi veya ASP.NET Web Forms'tan aşina olanlar benzer bir şey hatırlayabilir, React veya Vue.js de uzaktan benzer bir şeye dayanmaktadır. PHP framework dünyasında bu tamamen benzersiz bir özelliktir.

Bileşenler, sayfalara (yani presenter'lara) eklediğimiz bağımsız, yeniden kullanılabilir birimlerdir. Bunlar formlar, veri ızgaraları, menüler, oylama anketleri, aslında tekrar tekrar kullanılması mantıklı olan her şey olabilir. Kendi bileşenlerimizi oluşturabilir veya geniş yelpazedeki açık kaynaklı bileşenlerden bazılarını kullanabiliriz.

Bileşenler, uygulama oluşturma yaklaşımını temelden etkiler. Size sayfaları önceden hazırlanmış birimlerden oluşturma konusunda yeni olanaklar sunarlar. Ve ayrıca Hollywood ile ortak bir yanları vardır.

DI Konteyneri ve Yapılandırma

DI konteyneri veya nesne fabrikası, tüm uygulamanın kalbidir.

Endişelenmeyin, önceki satırlardan görünebileceği gibi sihirli bir kara kutu değildir. Aslında, Nette tarafından oluşturulan ve önbellek dizinine kaydedilen oldukça sıkıcı bir PHP sınıfıdır. createServiceAbcd() gibi adlandırılmış birçok metodu vardır ve her biri belirli bir nesneyi üretebilir ve döndürebilir. Evet, uygulamayı başlatmak için index.php dosyasında ihtiyaç duyduğumuz Nette\Application\Application'ı üreten createServiceApplication() metodu da vardır. Ve bireysel presenter'ları üreten metotlar da vardır. Ve bu böyle devam eder.

DI konteynerinin oluşturduğu nesnelere bir nedenden dolayı servis denir.

Bu sınıfın gerçekten özel olan yanı, onu sizin değil, framework'ün programlamasıdır. Gerçekten PHP kodunu oluşturur ve diske kaydeder. Siz sadece konteynerin hangi nesneleri üretebileceği ve tam olarak nasıl üreteceği konusunda talimatlar verirsiniz. Ve bu talimatlar, NEON formatının kullanıldığı ve dolayısıyla .neon uzantısına sahip olan yapılandırma dosyalarında yazılır.

Yapılandırma dosyaları yalnızca DI konteynerini bilgilendirmek için kullanılır. Yani örneğin, session bölümünde expiration: 14 days seçeneğini belirtirsem, DI konteyneri oturumu temsil eden Nette\Http\Session nesnesini oluştururken onun setExpiration('14 days') metodunu çağırır ve böylece yapılandırma gerçeğe dönüşür.

Nelerin yapılandırılabileceğini ve kendi servislerinizi nasıl tanımlayacağınızı açıklayan tam bir bölüm sizin için hazırlanmıştır.

Servis oluşturmaya biraz daldığınızda, autowiring kelimesiyle karşılaşırsınız. Bu, hayatınızı inanılmaz derecede basitleştiren bir özelliktir. Nesneleri ihtiyaç duyduğunuz yerlere (örneğin sınıflarınızın kurucularına) otomatik olarak iletebilir, hiçbir şey yapmanıza gerek kalmadan. Nette'deki DI konteynerinin küçük bir mucize olduğunu keşfedeceksiniz.

Nereye Devam Edelim?

Nette'deki uygulamaların temel prensiplerini gözden geçirdik. Henüz çok yüzeysel, ancak yakında derinlemesine dalacak ve zamanla harika web uygulamaları oluşturacaksınız. Nereye devam etmeli? İlk Uygulamamızı Yazıyoruz eğitimini denediniz mi?

Yukarıda açıklananlara ek olarak, Nette kullanışlı sınıflar, veritabanı katmanı vb. içeren tam bir cephaneliğe sahiptir. Sadece belgeleri veya blogu gözden geçirmeyi deneyin. Birçok ilginç şey keşfedeceksiniz.

Framework'ün size bolca neşe getirmesini dileriz 💙

versiyon: 4.0