Nette Documentation Preview

syntax
Blog Ana Sayfası
****************

.[perex]
Şimdi son gönderileri gösteren bir ana sayfa oluşturacağız.


Başlamadan önce, Model-View-Presenter tasarım deseninin (MVC((Model-View-Controller)) benzeri) en azından temellerini bilmek gerekir:

- **Model** - verilerle çalışan katman. Uygulamanın geri kalanından tamamen ayrılmıştır. Yalnızca presenter ile iletişim kurar.

- **View** - ön uç katmanı. İstenen verileri şablonlar kullanarak oluşturur ve kullanıcıya gösterir.

- **Presenter** (veya Controller) - bağlantı katmanı. Presenter, Model ve View'u birbirine bağlar. İstekleri işler, Model'den veri sorgular ve bunları View'a geri döndürür.


Blogumuz gibi basit uygulamalar durumunda, tüm model katmanı yalnızca veritabanı sorgularından oluşacaktır - bunun için henüz ekstra koda ihtiyacımız yok. Başlangıç olarak, yalnızca presenter'ları ve şablonları oluşturacağız. Nette'de her presenter'ın kendi şablonları vardır, bu yüzden onları aynı anda oluşturacağız.


Adminer Kullanarak Veritabanı Oluşturma
=======================================

Verileri depolamak için MySQL veritabanını kullanacağız, çünkü web uygulaması programcıları arasında en yaygın olanıdır. Ancak kullanmak istemiyorsanız, kendi seçiminize göre bir veritabanı seçmekten çekinmeyin.

Şimdi blogumuzun makalelerinin saklanacağı veritabanı yapısını hazırlayacağız. Çok basit başlayacağız - yalnızca gönderiler için bir tablo oluşturacağız.

Veritabanını oluşturmak için [Adminer |https://www.adminer.org]'ı veya veritabanlarını yönetmek için favori aracınızı indirebiliriz.


Adminer'ı açalım ve `quickstart` adında yeni bir veritabanı oluşturalım.

`posts` adında yeni bir tablo ve şu sütunlarla oluşturalım:
- `id` int, autoincrement (AI) işaretleyin
- `title` varchar, uzunluk 255
- `content` text
- `created_at` timestamp

Sonuç yapısı şöyle görünmelidir:

[* adminer-posts.webp *]

```sql
CREATE TABLE `posts` (
	`id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
	`title` varchar(255) NOT NULL,
	`content` text NOT NULL,
	`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB CHARSET=utf8;
```

.[caution]
**InnoDB** depolama motorunu kullanmak gerçekten önemlidir. Birazdan nedenini göstereceğiz. Şimdilik, sadece seçin ve kaydet'e tıklayın.

Uygulama aracılığıyla veritabanına makale ekleme seçeneği oluşturmadan önce, bloga manuel olarak birkaç örnek makale ekleyin.

```sql
INSERT INTO `posts` (`id`, `title`, `content`, `created_at`) VALUES
(1,	'Article One',	'Lorem ipusm dolor one',	CURRENT_TIMESTAMP),
(2,	'Article Two',	'Lorem ipsum dolor two',	CURRENT_TIMESTAMP),
(3,	'Article Three',	'Lorem ipsum dolor three',	CURRENT_TIMESTAMP);
```


Veritabanına Bağlanma
=====================

Veritabanı oluşturulduğuna ve içinde birkaç makale sakladığımıza göre, onları güzel yeni sayfamızda göstermenin tam zamanı.

Öncelikle uygulamaya hangi veritabanını kullanacağını söylemeliyiz. Veritabanı bağlantısını `config/common.neon` dosyasında DSN((Veri Kaynağı Adı)) ve giriş bilgileri kullanarak ayarlayacağız. Şöyle görünmelidir:

```neon .{file:config/common.neon}
database:
	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
	user: *buraya kullanıcı adını girin*
	password: *buraya veritabanı şifresini girin*
```

.[note]
Bu dosyayı düzenlerken satır girintisine dikkat edin. [NEON |neon:format] formatı hem boşluklarla hem de sekmelerle girintiyi kabul eder, ancak ikisini aynı anda kabul etmez. Web Projesi'ndeki varsayılan yapılandırma dosyası sekmeleri kullanır.


Veritabanı Bağlantısını Aktarma
===============================

Makalelerin listelenmesinden sorumlu olacak `HomePresenter`, veritabanına bir bağlantıya ihtiyaç duyar. Bunu elde etmek için, şöyle görünecek bir yapıcı (constructor) kullanacağız:

```php .{file:app/Presentation/Home/HomePresenter.php}
<?php
namespace App\Presentation\Home;

use Nette;

final class HomePresenter extends Nette\Application\UI\Presenter
{
	public function __construct(
		private Nette\Database\Explorer $database,
	) {
	}

	// ...
}
```


Veritabanından Gönderileri Yükleme
==================================

Şimdi gönderileri veritabanından yükleyeceğiz ve onları HTML kodu olarak oluşturacak olan şablona göndereceğiz. Bunun için *render* metodu olarak adlandırılan metot kullanılır:

```php .{file:app/Presentation/Home/HomePresenter.php}
public function renderDefault(): void
{
	$this->template->posts = $this->database
		->table('posts')
		->order('created_at DESC')
		->limit(5);
}
```

Presenter şimdi veritabanından verileri şablona (View) aktaran bir render metodu `renderDefault()` içerir. Şablonlar `app/Presentation/{PresenterName}/{viewName}.latte` içinde bulunur, bu yüzden bu durumda şablon `app/Presentation/Home/default.latte` içinde bulunur. Şablonda şimdi veritabanından alınan gönderileri içeren `$posts` değişkeni mevcut olacaktır.


Şablon
======

Tüm web sitesi için ana bir şablonumuz (adı *layout*, başlık, stiller, altbilgi,... içerir) ve her görünüm (View) için belirli şablonlarımız (örneğin, blogdaki gönderileri görüntülemek için) vardır, bunlar ana şablonun bazı bölümlerini geçersiz kılabilir.

Varsayılan olarak, layout şablonu `app/Presentation/@layout.latte` içinde bulunur ve şunları içerir:

```latte .{file:app/Presentation/@layout.latte}
...
{include content}
...
```

`{include content}` ifadesi, ana şablona `content` adlı bloğu ekler. Bunu bireysel görünümlerin (View) şablonlarında tanımlayacağız. Bizim durumumuzda, `Home/default.latte` dosyasını aşağıdaki gibi düzenleyeceğiz:

```latte .{file:app/Presentation/Home/default.latte}
{block content}
	Merhaba Dünya
{/block}
```

Bununla, ana layout'a eklenecek olan *content* [bloğunu |latte:tags#block] tanımladık. Tarayıcıyı tekrar yenilersek, "Merhaba Dünya" metnini içeren bir sayfa göreceğiz (kaynak kodunda `@layout.latte` içinde tanımlanan HTML başlığı ve altbilgisi ile birlikte).

Blog gönderilerini görüntüleyelim - şablonu aşağıdaki gibi düzenleyeceğiz:

```latte .{file:app/Presentation/Home/default.latte}
{block content}
	<h1>Blogum</h1>

	{foreach $posts as $post}
	<div class="post">
		<div class="date">{$post->created_at|date:'F j, Y'}</div>

		<h2>{$post->title}</h2>

		<div>{$post->content|truncate:256}</div>
	</div>
	{/foreach}
{/block}
```

Tarayıcıyı yenilersek, tüm gönderilerin bir listesini göreceğiz. Liste henüz pek güzel veya renkli değil, bu yüzden `www/css/style.css` dosyasına birkaç [CSS stili |https://github.com/nette-examples/quickstart/blob/v4.0/www/css/style.css] ekleyebilir ve layout'ta bağlayabiliriz:

```latte .{file:app/Presentation/@layout.latte}
	...
	<link rel="stylesheet" href="{$basePath}/css/style.css">
</head>
...
```

`{foreach}` etiketi, `$posts` değişkeninde şablona aktardığımız tüm gönderiler üzerinde yinelenir ve her biri için verilen HTML parçasını oluşturur. Tam olarak PHP kodu gibi davranır.

`|date:` ifadesine filtre diyoruz. Filtreler çıktıyı biçimlendirmek için tasarlanmıştır. Bu özel filtre, tarihi (örneğin `2013-04-12`) daha okunabilir bir biçime (`April 12, 2013`) dönüştürür. `|truncate` filtresi, karakter dizisini belirtilen maksimum uzunluğa kırpar ve karakter dizisi kısaltılırsa sonuna üç nokta ekler. Bu bir önizleme olduğundan, makalenin tüm içeriğini göstermenin bir anlamı yoktur. Diğer varsayılan filtreleri [belgelerde bulabiliriz |latte:filters] veya gerektiğinde kendi filtrelerimizi oluşturabiliriz.

Bir şey daha var. Önceki kodu kısaltabilir ve basitleştirebiliriz. Bunu *Latte etiketlerini* *n:nitelikleri* ile değiştirerek başarırız:

```latte .{file:app/Presentation/Home/default.latte}
{block content}
	<h1>Blogum</h1>

	<div n:foreach="$posts as $post" class="post">
		<div class="date">{$post->created_at|date:'F j, Y'}</div>

		<h2>{$post->title}</h2>

		<div>{$post->content|truncate:256}</div>
	</div>
{/block}
```

`n:foreach` niteliği, *div* bloğunu *foreach* ile sarar (önceki kodla tamamen aynı şekilde çalışır).


Özet
====

Şimdi birkaç gönderi içeren çok basit bir MySQL veritabanımız var. Uygulama bu veritabanına bağlanır ve bu gönderilerin basit bir listesini şablonda görüntüler.

{{priority: -1}}
{{sitename: Nette Quickstart}}

Blog Ana Sayfası

Şimdi son gönderileri gösteren bir ana sayfa oluşturacağız.

Başlamadan önce, Model-View-Presenter tasarım deseninin (MVC benzeri) en azından temellerini bilmek gerekir:

  • Model – verilerle çalışan katman. Uygulamanın geri kalanından tamamen ayrılmıştır. Yalnızca presenter ile iletişim kurar.
  • View – ön uç katmanı. İstenen verileri şablonlar kullanarak oluşturur ve kullanıcıya gösterir.
  • Presenter (veya Controller) – bağlantı katmanı. Presenter, Model ve View'u birbirine bağlar. İstekleri işler, Model'den veri sorgular ve bunları View'a geri döndürür.

Blogumuz gibi basit uygulamalar durumunda, tüm model katmanı yalnızca veritabanı sorgularından oluşacaktır – bunun için henüz ekstra koda ihtiyacımız yok. Başlangıç olarak, yalnızca presenter'ları ve şablonları oluşturacağız. Nette'de her presenter'ın kendi şablonları vardır, bu yüzden onları aynı anda oluşturacağız.

Adminer Kullanarak Veritabanı Oluşturma

Verileri depolamak için MySQL veritabanını kullanacağız, çünkü web uygulaması programcıları arasında en yaygın olanıdır. Ancak kullanmak istemiyorsanız, kendi seçiminize göre bir veritabanı seçmekten çekinmeyin.

Şimdi blogumuzun makalelerinin saklanacağı veritabanı yapısını hazırlayacağız. Çok basit başlayacağız – yalnızca gönderiler için bir tablo oluşturacağız.

Veritabanını oluşturmak için Adminer'ı veya veritabanlarını yönetmek için favori aracınızı indirebiliriz.

Adminer'ı açalım ve quickstart adında yeni bir veritabanı oluşturalım.

posts adında yeni bir tablo ve şu sütunlarla oluşturalım:

  • id int, autoincrement (AI) işaretleyin
  • title varchar, uzunluk 255
  • content text
  • created_at timestamp

Sonuç yapısı şöyle görünmelidir:

CREATE TABLE `posts` (
	`id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
	`title` varchar(255) NOT NULL,
	`content` text NOT NULL,
	`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB CHARSET=utf8;

InnoDB depolama motorunu kullanmak gerçekten önemlidir. Birazdan nedenini göstereceğiz. Şimdilik, sadece seçin ve kaydet'e tıklayın.

Uygulama aracılığıyla veritabanına makale ekleme seçeneği oluşturmadan önce, bloga manuel olarak birkaç örnek makale ekleyin.

INSERT INTO `posts` (`id`, `title`, `content`, `created_at`) VALUES
(1,	'Article One',	'Lorem ipusm dolor one',	CURRENT_TIMESTAMP),
(2,	'Article Two',	'Lorem ipsum dolor two',	CURRENT_TIMESTAMP),
(3,	'Article Three',	'Lorem ipsum dolor three',	CURRENT_TIMESTAMP);

Veritabanına Bağlanma

Veritabanı oluşturulduğuna ve içinde birkaç makale sakladığımıza göre, onları güzel yeni sayfamızda göstermenin tam zamanı.

Öncelikle uygulamaya hangi veritabanını kullanacağını söylemeliyiz. Veritabanı bağlantısını config/common.neon dosyasında DSN ve giriş bilgileri kullanarak ayarlayacağız. Şöyle görünmelidir:

database:
	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
	user: *buraya kullanıcı adını girin*
	password: *buraya veritabanı şifresini girin*

Bu dosyayı düzenlerken satır girintisine dikkat edin. NEON formatı hem boşluklarla hem de sekmelerle girintiyi kabul eder, ancak ikisini aynı anda kabul etmez. Web Projesi'ndeki varsayılan yapılandırma dosyası sekmeleri kullanır.

Veritabanı Bağlantısını Aktarma

Makalelerin listelenmesinden sorumlu olacak HomePresenter, veritabanına bir bağlantıya ihtiyaç duyar. Bunu elde etmek için, şöyle görünecek bir yapıcı (constructor) kullanacağız:

<?php
namespace App\Presentation\Home;

use Nette;

final class HomePresenter extends Nette\Application\UI\Presenter
{
	public function __construct(
		private Nette\Database\Explorer $database,
	) {
	}

	// ...
}

Veritabanından Gönderileri Yükleme

Şimdi gönderileri veritabanından yükleyeceğiz ve onları HTML kodu olarak oluşturacak olan şablona göndereceğiz. Bunun için render metodu olarak adlandırılan metot kullanılır:

public function renderDefault(): void
{
	$this->template->posts = $this->database
		->table('posts')
		->order('created_at DESC')
		->limit(5);
}

Presenter şimdi veritabanından verileri şablona (View) aktaran bir render metodu renderDefault() içerir. Şablonlar app/Presentation/{PresenterName}/{viewName}.latte içinde bulunur, bu yüzden bu durumda şablon app/Presentation/Home/default.latte içinde bulunur. Şablonda şimdi veritabanından alınan gönderileri içeren $posts değişkeni mevcut olacaktır.

Şablon

Tüm web sitesi için ana bir şablonumuz (adı layout, başlık, stiller, altbilgi,… içerir) ve her görünüm (View) için belirli şablonlarımız (örneğin, blogdaki gönderileri görüntülemek için) vardır, bunlar ana şablonun bazı bölümlerini geçersiz kılabilir.

Varsayılan olarak, layout şablonu app/Presentation/@layout.latte içinde bulunur ve şunları içerir:

...
{include content}
...

{include content} ifadesi, ana şablona content adlı bloğu ekler. Bunu bireysel görünümlerin (View) şablonlarında tanımlayacağız. Bizim durumumuzda, Home/default.latte dosyasını aşağıdaki gibi düzenleyeceğiz:

{block content}
	Merhaba Dünya
{/block}

Bununla, ana layout'a eklenecek olan content bloğunu tanımladık. Tarayıcıyı tekrar yenilersek, „Merhaba Dünya“ metnini içeren bir sayfa göreceğiz (kaynak kodunda @layout.latte içinde tanımlanan HTML başlığı ve altbilgisi ile birlikte).

Blog gönderilerini görüntüleyelim – şablonu aşağıdaki gibi düzenleyeceğiz:

{block content}
	<h1>Blogum</h1>

	{foreach $posts as $post}
	<div class="post">
		<div class="date">{$post->created_at|date:'F j, Y'}</div>

		<h2>{$post->title}</h2>

		<div>{$post->content|truncate:256}</div>
	</div>
	{/foreach}
{/block}

Tarayıcıyı yenilersek, tüm gönderilerin bir listesini göreceğiz. Liste henüz pek güzel veya renkli değil, bu yüzden www/css/style.css dosyasına birkaç CSS stili ekleyebilir ve layout'ta bağlayabiliriz:

	...
	<link rel="stylesheet" href="{$basePath}/css/style.css">
</head>
...

{foreach} etiketi, $posts değişkeninde şablona aktardığımız tüm gönderiler üzerinde yinelenir ve her biri için verilen HTML parçasını oluşturur. Tam olarak PHP kodu gibi davranır.

|date: ifadesine filtre diyoruz. Filtreler çıktıyı biçimlendirmek için tasarlanmıştır. Bu özel filtre, tarihi (örneğin 2013-04-12) daha okunabilir bir biçime (April 12, 2013) dönüştürür. |truncate filtresi, karakter dizisini belirtilen maksimum uzunluğa kırpar ve karakter dizisi kısaltılırsa sonuna üç nokta ekler. Bu bir önizleme olduğundan, makalenin tüm içeriğini göstermenin bir anlamı yoktur. Diğer varsayılan filtreleri belgelerde bulabiliriz veya gerektiğinde kendi filtrelerimizi oluşturabiliriz.

Bir şey daha var. Önceki kodu kısaltabilir ve basitleştirebiliriz. Bunu Latte etiketlerini n:nitelikleri ile değiştirerek başarırız:

{block content}
	<h1>Blogum</h1>

	<div n:foreach="$posts as $post" class="post">
		<div class="date">{$post->created_at|date:'F j, Y'}</div>

		<h2>{$post->title}</h2>

		<div>{$post->content|truncate:256}</div>
	</div>
{/block}

n:foreach niteliği, div bloğunu foreach ile sarar (önceki kodla tamamen aynı şekilde çalışır).

Özet

Şimdi birkaç gönderi içeren çok basit bir MySQL veritabanımız var. Uygulama bu veritabanına bağlanır ve bu gönderilerin basit bir listesini şablonda görüntüler.