/
how-it-works.texy
204 lines (130 loc) · 16.7 KB
/
how-it-works.texy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
Uygulamalar Nasıl Çalışır?
**************************
<div class=perex>
Şu anda Nette dokümantasyonunun temel belgesini okumaktasınız. Web uygulamalarının tüm prensiplerini öğreneceksiniz. A'dan Z'ye, doğum anından PHP betiğinin son nefesine kadar güzel. Okuduktan sonra bileceksiniz:
- her şey nasil i̇şli̇yor
- Bootstrap, Presenter ve DI konteyner nedir
- dizin yapısının neye benzediği
</div>
Dizin Yapısı .[#toc-directory-structure]
========================================
[WebProject |https://github.com/nette/web-project] adlı bir web uygulamasının iskelet örneğini açın ve hakkında yazılan dosyaları izleyebilirsiniz.
Dizin yapısı şuna benzer:
/--pre
<b>web-project/</b>
├── <b>app/</b> ← directory with application
│ ├── <b>Presenters/</b> ← presenter classes
│ │ ├── <b>HomePresenter.php</b> ← Home presenter class
│ │ └── <b>templates/</b> ← templates directory
│ │ ├── <b>@layout.latte</b> ← template of shared layout
│ │ └── <b>Home/</b> ← templates for Home presenter
│ │ └── <b>default.latte</b> ← template for action `default`
│ ├── <b>Router/</b> ← configuration of URL addresses
│ └── <b>Bootstrap.php</b> ← booting class Bootstrap
├── <b>bin/</b> ← scripts for the command line
├── <b>config/</b> ← configuration files
│ ├── <b>common.neon</b>
│ └── <b>services.neon</b>
├── <b>log/</b> ← error logs
├── <b>temp/</b> ← temporary files, cache, …
├── <b>vendor/</b> ← libraries installed by Composer
│ ├── ...
│ └── <b>autoload.php</b> ← autoloading of libs installed by Composer
├── <b>www/</b> ← public directory, document root of project
│ ├── <b>.htaccess</b> ← mod_rewrite rules etc
│ └── <b>index.php</b> ← initial file that launches the application
└── <b>.htaccess</b> ← prohibits access to all directories except www
\--
Dizin yapısını herhangi bir şekilde değiştirebilir, klasörleri yeniden adlandırabilir veya taşıyabilir ve ardından `Bootstrap.php` dosyasındaki `log/` ve `temp/` yollarını ve `autoload` bölümündeki `composer.json` içindeki bu dosyanın yolunu düzenleyebilirsiniz. Başka bir şey yok, karmaşık yeniden yapılandırma yok, sürekli değişiklik yok. Nette [akıllı |bootstrap#development-vs-production-mode] bir [otomatik algılamaya |bootstrap#development-vs-production-mode] sahiptir.
Biraz daha büyük uygulamalar için, sunum ve şablon içeren klasörleri alt dizinlere (diskte) ve [modül |modules] olarak adlandırdığımız ad alanlarına (kodda) bölebiliriz.
`www/` dizini, projenin genel dizini veya belge köküdür. Uygulama tarafında başka bir şey ayarlamanıza gerek kalmadan yeniden adlandırabilirsiniz. Sadece [barındırmayı |nette:troubleshooting#How to change or remove www directory from URL], belge kökünün bu dizine gideceği şekilde [yapılandırmanız |nette:troubleshooting#How to change or remove www directory from URL] gerekir.
[Composer'ı |best-practices:composer] kullanarak Nette dahil olmak üzere WebProject'i doğrudan da indirebilirsiniz:
```shell
composer create-project nette/web-project
```
Linux veya macOS üzerinde, `log/` ve `temp/` dizinleri için [yazma izinlerini |nette:troubleshooting#Setting directory permissions] ayarlayın.
WebProject uygulaması çalışmaya hazırdır, başka 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 .[#toc-http-request]
================================
Her şey bir kullanıcının sayfayı tarayıcıda açması ve tarayıcının sunucuya bir HTTP isteği göndermesiyle başlar. İstek, `index.php` olan `www/` genel dizininde bulunan bir PHP dosyasına gider. Bunun `https://example.com/product/123` dosyasına eşlenir ve çalıştırılır.
Görevi:
1) ortamı başlatın
2) fabrikayı alın
3) talebi işleyen Nette uygulamasını başlatın
Ne tür bir fabrika? Traktör değil, web sitesi üretiyoruz! Bekleyin, hemen açıklayacağım.
"Ortamı başlatmak" derken, örneğin, hataları günlüğe kaydetmek veya görselleştirmek için harika bir araç olan [Tracy |tracy:] 'nin etkinleştirilmesini kastediyoruz. Üretim sunucusundaki hataları günlüğe kaydeder ve bunları doğrudan geliştirme sunucusunda görüntüler. Bu nedenle, başlatmanın sitenin üretim modunda mı yoksa geliştirici modunda mı çalıştığına da karar vermesi gerekir. Bunu yapmak için Nette otomatik algılama kullanır: siteyi localhost üzerinde çalıştırırsanız, geliştirici modunda çalışır. Hiçbir şey yapılandırmanız gerekmez ve uygulama hem geliştirme hem de üretim dağıtımı için hazırdır. Bu adımlar [Bootstrap sınıfı |bootstrap] ile ilgili bölümde ayrıntılı olarak açıklanmıştır.
Üçüncü nokta (evet, ikinciyi atladık, ancak ona geri döneceğiz) uygulamayı başlatmaktır. Nette HTTP isteklerinin işlenmesi `Nette\Application\Application` sınıfı (bundan sonra `Application` olarak anılacaktır) tarafından yapılır, bu nedenle "bir uygulamayı çalıştır" dediğimizde, bu sınıfın bir nesnesi üzerinde `run()` adlı bir yöntemi çağırmayı kastediyoruz.
Nette, kanıtlanmış metodolojilerle temiz uygulamalar yazmanız için size rehberlik eden bir akıl hocasıdır. Ve en kanıtlanmış olanı **bağımlılık enjeksiyonu**, kısaltılmış DI olarak adlandırılır. Şu anda sizi DI'yi açıklamakla meşgul etmek istemiyoruz, çünkü [ayrı bir bölüm |dependency-injection:introduction] var, burada önemli olan şey, anahtar nesnelerin genellikle **DI container** (kısaltılmış DIC) adı verilen nesneler için bir fabrika tarafından oluşturulacağıdır. Evet, bu bir süre önce bahsedilen fabrikadır. Ayrıca bizim için `Application` nesnesini de oluşturur, bu yüzden önce bir konteynere ihtiyacımız var. Bunu `Configurator` sınıfını kullanarak elde ediyoruz ve `Application` nesnesini üretmesine izin veriyoruz, `run()` yöntemini çağırıyoruz ve bu Nette uygulamasını başlatıyor. Bu tam olarak [index.php |bootstrap#index.php] dosyasında olan şeydir.
Nette Uygulama .[#toc-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, belirli bir web sitesi sayfasını temsil eden sınıflar olan birçok sözde sunucuya (diğer çerçevelerde aynı olan denetleyici terimiyle karşılaşabilirsiniz) ayrılır: örneğin ana sayfa; e-mağazadaki ürün; oturum açma formu; site haritası beslemesi vb. Uygulama bir ila binlerce sunucuya sahip olabilir.
Uygulama, yönlendirici olarak adlandırılan kişiden mevcut talebin işlenmek üzere hangi sunuculara iletileceğine karar vermesini isteyerek başlar. Yönlendirici bunun kimin sorumluluğunda olduğuna karar verir. `https://example.com/product/123` ile bir ürünü `id: 123` eylem olarak isteyen **sunucu** `Product` için bir iş olduğuna karar verir. Sunucu + eylem çiftlerini iki nokta üst üste ile ayırarak `Product:show` şeklinde yazmak iyi bir alışkanlıktır.
Böylece yönlendirici URL'yi bir `Presenter:action` + parametreler çiftine dönüştürdü, bizim durumumuzda `Product:show` + `id: 123`. Bir yönlendiricinin nasıl göründüğünü `app/Router/RouterFactory.php` dosyasında görebilirsiniz ve bunu [Yönlendirme |Routing] bölümünde ayrıntılı olarak açıklayacağız.
Devam edelim. Uygulama zaten sunucunun adını biliyor ve devam edebilir. Sunum yapan kişinin kodu olan `ProductPresenter` nesnesini oluşturarak `Product`. Daha doğrusu, DI konteynerinden sunucuyu yaratmasını ister, çünkü nesneleri üretmek onun işidir.
Sunucu şöyle görünebilir:
```php
class ProductPresenter extends Nette\Application\UI\Presenter
{
public function __construct(
private ProductRepository $repository,
) {
}
public function renderShow(int $id): void
{
// modelden veri alıyoruz ve bunu şablona aktarıyoruz
$this->template->product = $this->repository->getProduct($id);
}
}
```
Talep, sunum yapan kişi tarafından ele alınır. Ve görev açıktır: `id: 123` ile `show` eylemini gerçekleştirin. Sunucuların dilinde bu, `renderShow()` yönteminin çağrıldığı ve `$id` parametresinde `123` aldığı anlamına gelir.
Bir sunum yapan kişi birden fazla eylemi işleyebilir, yani birden fazla yönteme sahip olabilir `render<Action>()`. Ancak sunum yapanların bir veya mümkün olduğunca az eylemle tasarlanmasını öneriyoruz.
Böylece, kodu kurgusal bir örnek olan `renderShow(123)` yöntemi çağrıldı, ancak verilerin şablona nasıl aktarıldığını, yani `$this->template` adresine yazarak görebilirsiniz.
Daha sonra, sunum yapan kişi yanıtı döndürür. Bu bir HTML sayfası, bir resim, bir XML belgesi, diskten bir dosya gönderme, JSON veya başka bir sayfaya yönlendirme olabilir. Daha da önemlisi, nasıl yanıt verileceğini açıkça belirtmezsek ( `ProductPresenter` adresinde olduğu gibi), yanıt şablonu bir HTML sayfası ile işlemek olacaktır. Neden mi? Çünkü vakaların %99'unda bir şablon çizmek isteriz, dolayısıyla sunum yapan kişi bu davranışı varsayılan olarak kabul eder ve işimizi kolaylaştırmak ister. Nette'in amacı da bu.
Hangi şablonun çizileceğini belirtmemize bile gerek yok, basit bir mantıkla o şablona giden yolu türetiyor. Sunucu `Product` ve eylem `show` durumunda, bu şablon dosyalarından birinin `ProductPresenter` sınıfının bulunduğu dizine göre var olup olmadığını görmeye çalışır:
- `templates/Product/show.latte`
- `templates/Product.show.latte`
Ayrıca `@layout.latte` dosyasında düzeni bulmaya çalışacak ve ardından şablonu oluşturacaktır. Artık sunucunun ve tüm uygulamanın görevi tamamlanmıştır. Şablon mevcut değilse, 404 hatalı bir sayfa döndürülecektir. Sunumcular hakkında daha fazla bilgiyi [Sunumcular |Presenters] sayfasında bulabilirsiniz.
[* request-flow.svg *]
Sadece emin olmak için, tüm süreci biraz farklı bir URL ile özetlemeye çalışalım:
1) URL şu şekilde olacaktır `https://example.com`
2) uygulamayı önyüklüyoruz, bir konteyner oluşturuyoruz ve `Application::run()`
3) yönlendirici URL'yi bir çift olarak çözer `Home:default`
4) bir `HomePresenter` nesnesi oluşturulur
5) `renderDefault()` yöntemi çağrılır (eğer varsa)
6) `templates/@layout.latte` düzenine sahip bir `templates/Home/default.latte` şablonu oluşturulur
Şu anda birçok yeni kavramla karşılaşmış olabilirsiniz, ancak bunların anlamlı olduğuna inanıyoruz. Nette'de uygulama oluşturmak çocuk oyuncağı.
Şablonlar .[#toc-templates]
===========================
Şablonlar söz konusu olduğunda, Nette [Latte |latte:] şablon sistemini kullanır. Bu yüzden şablon içeren dosyalar `.latte` ile biter. Latte, PHP için en güvenli şablon sistemi ve aynı zamanda en sezgisel sistem olduğu için kullanılır. Yeni bir şey öğrenmenize gerek yok, sadece PHP ve birkaç Latte etiketi bilmeniz yeterli. Her şeyi [dokümantasyonda |templates] bulacaksınız.
Şablonda diğer sunumculara ve eylemlere aşağıdaki gibi [bir bağlantı oluşturuyoruz |creating-links]:
```latte
<a n:href="Product:show $productId">product detail</a>
```
Gerçek URL yerine tanıdık `Presenter:action` çiftini yazmanız ve parametreleri eklemeniz yeterlidir. İşin püf noktası, bu özelliğin Nette tarafından işleneceğini söyleyen `n:href` adresidir. Ve oluşturacaktır:
```latte
<a href="/product/456">product detail</a>
```
Daha önce bahsedilen yönlendirici URL'nin oluşturulmasından sorumludur. Aslında, Nette'deki yönlendiriciler, yalnızca bir URL'den bir sunumcu:eylem çiftine dönüşüm gerçekleştirebilmeleri açısından değil, aynı zamanda sunumcu + eylem + parametrelerin adından bir URL oluşturabilmeleri açısından da benzersizdir.
Bu sayede Nette'de, şablonda veya sunum yapan kişide tek bir karakteri bile değiştirmeden, sadece yönlendiriciyi değiştirerek tüm bitmiş uygulamadaki URL'nin şeklini tamamen değiştirebilirsiniz.
Ve bu sayede, Nette'nin bir başka benzersiz özelliği olan ve farklı URL'lerde yinelenen içeriğin varlığını otomatik olarak önleyerek SEO'yu (internette aranabilirliğin optimizasyonu) geliştiren sözde kanonizasyon çalışır.
Birçok programcı bunu şaşırtıcı buluyor.
İnteraktif Bileşenler .[#toc-interactive-components]
====================================================
Sunucular hakkında size söylememiz gereken bir şey daha var: yerleşik bir bileşen sistemine sahipler. Daha yaşlılarınız Delphi veya ASP.NET Web Forms'dan benzer bir şeyi hatırlayabilir. React veya Vue.js uzaktan benzer bir şey üzerine inşa edilmiştir. PHP çerçeveleri dünyasında bu tamamen benzersiz bir özelliktir.
Bileşenler, sayfalara (yani sunumlara) yerleştirdiğimiz ayrı yeniden kullanılabilir birimlerdir. Bunlar [formlar |forms:in-presenter], [datagridler |https://componette.org/contributte/datagrid/], menüler, anketler, aslında tekrar tekrar kullanılması mantıklı olan her şey olabilir. Kendi bileşenlerimizi oluşturabilir veya [çok çeşitli |https://componette.org] açık kaynak bileşenlerinden bazılarını kullanabiliriz.
Bileşenler, uygulama geliştirme yaklaşımını temelden değiştirmektedir. Önceden tanımlanmış birimlerden sayfalar oluşturmak için yeni olanaklar sunacaklar. Ve [Hollywood |components#Hollywood style] ile ortak bir yönleri var.
DI Konteyneri ve Yapılandırması .[#toc-di-container-and-configuration]
======================================================================
DI konteyneri (nesneler için fabrika) tüm uygulamanın kalbidir.
Merak etmeyin, önceki kelimelerden anlaşılabileceği gibi sihirli bir kara kutu değil. Aslında, Nette tarafından oluşturulan ve bir önbellek dizininde saklanan oldukça sıkıcı bir PHP sınıfıdır. `createServiceAbcd()` şeklinde adlandırılan ve her biri bir nesne yaratan ve döndüren çok sayıda metodu vardır. Evet, uygulamayı çalıştırmak için `index.php` dosyasında ihtiyaç duyduğumuz `Nette\Application\Application` nesnesini üretecek bir `createServiceApplication()` yöntemi de var. Ve tek tek sunum yapan kişileri üretmek için yöntemler var. Ve böyle devam eder.
DI konteynerinin oluşturduğu nesneler bir nedenden dolayı servis olarak adlandırılır.
Bu sınıfla ilgili gerçekten özel olan şey, sizin tarafınızdan değil, çerçeve tarafından programlanmış olmasıdır. Aslında PHP kodunu üretir ve diske kaydeder. Siz sadece konteynerin hangi nesneleri tam olarak nasıl üretmesi gerektiğine dair talimatlar verirsiniz. Ve bu talimatlar [NEON formatındaki |neon:format] [yapılandırma dosyalarına |bootstrap#DI Container Configuration] yazılır ve bu nedenle `.neon` uzantısına sahiptir.
Yapılandırma dosyaları yalnızca DI konteynerine talimat vermek için kullanılır. Örneğin, [oturum |http:configuration#Session] bölümünde `expiration: 14 days` seçeneğini belirtirsem, DI konteyneri oturumu temsil eden `Nette\Http\Session` nesnesini oluştururken `setExpiration('14 days')` yöntemini çağırır ve böylece yapılandırma gerçek olur.
Nelerin [yapılandırılabileceğini |nette:configuring] ve [kendi servislerinizi |dependency-injection:services] nasıl [tanımlayacağınızı |dependency-injection:services] anlatan koca bir bölüm sizin için hazır.
Hizmetlerin oluşturulmasına girdiğinizde, [otomatik kab |dependency-injection:autowiring] lolama kelimesiyle karşılaşacaksınız. Bu, hayatınızı inanılmaz derecede kolaylaştıracak bir araçtır. Hiçbir şey yapmanıza gerek kalmadan nesneleri ihtiyaç duyduğunuz yerlere (örneğin sınıflarınızın kurucularına) otomatik olarak aktarabilir. Nette'deki DI konteynerinin küçük bir mucize olduğunu göreceksiniz.
Sırada Ne Var? .[#toc-what-next]
================================
Nette uygulamaların temel prensiplerini gözden geçirdik. Şimdiye kadar çok yüzeysel olarak, ancak yakında derinliklere inecek ve sonunda harika web uygulamaları oluşturacaksınız. Nereden devam edelim? [İlk Uygulamanızı Oluşturun |quickstart:] eğitimini denediniz mi?
Yukarıdakilere ek olarak, Nette [yararlı sınıflardan |utils:], [veritabanı katmanından |database:] vb. oluşan bir cephaneliğe sahiptir. Kasıtlı olarak sadece belgelere tıklamayı deneyin. Veya [blogu |https://blog.nette.org] ziyaret edin. Birçok ilginç şey keşfedeceksiniz.
Çerçeve size bolca neşe getirsin 💙