Nette Documentation Preview

syntax
Основна страница на блога
*************************

.[perex]
Нека създадем начална страница, на която да се показват последните ви публикации.


Преди да започнем, трябва да знаете поне някои основни неща за шаблона за проектиране Model-View-Presenter (подобен на MVC((Model-View-Controller))):

- **Моделът** е слоят за манипулиране на данни. Той е напълно отделен от останалата част на приложението и комуникира само с презентаторите.

- **Виж** (или _Представяне_) е външният слой за дефиниране. Той показва на потребителя исканите данни с помощта на шаблони.

- **Presenter** (или _Controller_) е нивото на връзката. Водещият свързва модела и изгледа. Той обработва заявките, изисква данни от модела и след това ги предава на текущия изглед.


В случай на много просто приложение, каквото е нашият блог, слоят Model всъщност ще се състои само от заявки към самата база данни - за това не е необходим допълнителен код на PHP. Необходимо е само да създадем слоевете Presenter и View. В Nette всеки презентатор има свои собствени изгледи, така че ще продължим и с двата едновременно.


Създаване на база данни с помощта на Adminer .[#toc-creating-the-database-with-adminer]
=======================================================================================

Ще използваме база данни MySQL за съхранение на данни, тъй като това е най-разпространеният избор сред уеб разработчиците. Но ако не ви харесва, не се колебайте да използвате база данни по ваш избор.

Нека подготвим базата данни, в която ще се съхраняват записите в блога ни. Нека започнем с една таблица за публикациите.

Можем да изтеглим [Adminer |https://www.adminer.org], за да създадем базата данни, или можете да използвате друг инструмент за управление на бази данни.


Нека да отворим Adminer и да създадем нова база данни, наречена `quickstart`.

Създайте нова таблица с име `posts` и добавете тези колони към нея:
- `id` int, щракнете върху автоматичното увеличаване (AI)
- `title` varchar, дължина 255
- `content` текст
- `created_at` timestamp

Това трябва да изглежда по следния начин

[* 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**. Причината за това ще видите по-късно. Засега просто създайте всичко, както е указано, и щракнете върху Запис. Или използвайте пълен код за създаване на таблица и бутон за SQL заявка в Adminer.

Опитайте се да добавите няколко записа в блога, преди да въведем възможността за добавяне на нови записи директно от нашето приложение.

```sql
INSERT INTO `posts` (`id`, `title`, `content`, `created_at`) VALUES
(1,	'Статья первая',	'Lorem ipusm dolor one',	CURRENT_TIMESTAMP),
(2,	'Статья вторая',	'Lorem ipsum dolor two',	CURRENT_TIMESTAMP),
(3,	'Статья третья',	'Lorem ipsum dolor three',	CURRENT_TIMESTAMP);
```


Свързване с база данни .[#toc-connecting-to-the-database]
=========================================================

Сега, след като базата данни е създадена и в нея има няколко публикации, е време да ги покажем на нашата нова блестяща страница.

Първо, трябва да укажем на приложението коя база данни да използва. Конфигурацията на връзката с базата данни се съхранява във файла `config/common.neon`. Създайте връзка DSN((Име на източника на данни)) и вашите пълномощия. Това трябва да изглежда по следния начин:

```neon .{file:config/common.neon}
database:
	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
	user: *укажите здесь имя пользователя*
	password: *укажите здесь пароль*
```

.[note]
Не забравяйте да правите отстъпи, когато редактирате този файл. [Форматът NEON |neon:format] приема както интервали, така и табулации, но не и двете заедно! В конфигурационния файл в уеб проекта по подразбиране се използва таблично представяне.


Осъществяване на връзката с базата данни .[#toc-injecting-the-database-connection]
==================================================================================

Презентаторът (намиращ се на адрес `app/UI/Home/HomePresenter.php`), който ще изписва статиите, трябва да се свърже с базата данни. За да направите това, модифицирайте конструктора по следния начин:

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

use Nette;

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

	// ...
}
```


Зареждане на публикации от базата данни .[#toc-loading-posts-from-the-database]
===============================================================================

Нека сега да извлечем публикациите от базата данни и да ги подадем към шаблона, който след това ще визуализира HTML кода. За това е предназначен така нареченият метод *render*:

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

Сега презентаторът има един метод за визуализация `renderDefault()`, който предава данните на изглед, наречен `default`. Шаблоните Preenter могат да бъдат намерени в `app/UI/{PresenterName}/{viewName}.latte`, така че в този случай шаблонът ще се намира в `app/UI/Home/default.latte`. В шаблона вече е налична променливата `$posts`, която съдържа публикациите от базата данни.


Шаблон .[#toc-template]
=======================

Има общ шаблон за цялата страница (наречен *layout*, със заглавие, стилове, колонтитул и т.н.), както и специфични шаблони за всеки изглед (например за показване на списък със записи в блога), които могат да отменят някои части от шаблона за оформление.

По подразбиране шаблонът за оформление се намира във файла `app/UI/@layout.latte`, който съдържа:

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

`{include content}` вмъква блок с име `content` в главния шаблон. Можете да го определите в шаблоните на всеки изглед. В нашия случай ще редактираме файла `app/UI/Home/default.latte` по следния начин

```latte .{file:app/UI/Home/default.latte}
{block content}
	Привет, мир!
{/block}
```

Той определя [блока |latte:tags#block] от *съдържание*, който ще бъде вмъкнат в оформлението. Ако опресните браузъра си, ще видите страница с текст "Hello, world! (в изходния код също с HTML заглавието и колонтитула, определени в `@layout.latte`).

Нека покажем записите в блога - за целта редактираме шаблона по следния начин:

```latte .{file:app/UI/Home/default.latte}
{block content}
	<h1 n:block="title">Мой блог</h1>

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

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

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

Ако опресните браузъра си, ще видите списък със записите в блога си. Списъкът не е много изискан или цветен, така че не се колебайте да добавите някой [блестящ CSS |https://github.com/nette-examples/quickstart/blob/v4.0/www/css/style.css] към `www/css/style.css`, а след това да поставите връзка към този файл в оформлението (файл `@layout.latte`):

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

Тагът `{foreach}` преминава през всички публикации, предадени на шаблона в променливата `$posts`, и извежда фрагмент от HTML код за всяка публикация. Точно по същия начин се прави и в кода на PHP.

Функцията `|date` се нарича филтър. Филтрите се използват за форматиране на изхода. Този конкретен филтър преобразува датата (напр. `2013-04-12`) в по-разбираема форма (`12.04.2013`). Филтърът `|truncate` съкращава низ до определена максимална дължина и добавя елипса в края, ако низът е съкратен. Тъй като това е предварителен преглед, няма смисъл да се показва пълното съдържание на статията. Други филтри по подразбиране [можете да намерите в документацията |latte:filters] или можете да създадете свои собствени, ако е необходимо.

И още нещо. Можем да направим кода малко по-кратък и следователно по-прост. Можем да заменим *tags Latte* с *n:attributes* по следния начин:

```latte .{file:app/UI/Home/default.latte}
{block content}
	<h1>My blog</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}</div>
	</div>
{/block}
```

`n:foreach` просто обвийте *div* с блок *foreach* (той прави точно същото нещо като предишния блок код).


За да обобщим .[#toc-summary]
=============================

Имаме много проста база данни MySQL с няколко публикации в блогове. Приложението се свързва с базата данни и извежда прост списък с публикации.

{{priority: -1}}
{{sitename: Быстрый старт с Nette}}

Основна страница на блога

Нека създадем начална страница, на която да се показват последните ви публикации.

Преди да започнем, трябва да знаете поне някои основни неща за шаблона за проектиране Model-View-Presenter (подобен на MVC):

  • Моделът е слоят за манипулиране на данни. Той е напълно отделен от останалата част на приложението и комуникира само с презентаторите.
  • Виж (или _Представяне_) е външният слой за дефиниране. Той показва на потребителя исканите данни с помощта на шаблони.
  • Presenter (или _Controller_) е нивото на връзката. Водещият свързва модела и изгледа. Той обработва заявките, изисква данни от модела и след това ги предава на текущия изглед.

В случай на много просто приложение, каквото е нашият блог, слоят Model всъщност ще се състои само от заявки към самата база данни – за това не е необходим допълнителен код на PHP. Необходимо е само да създадем слоевете Presenter и View. В Nette всеки презентатор има свои собствени изгледи, така че ще продължим и с двата едновременно.

Създаване на база данни с помощта на Adminer

Ще използваме база данни MySQL за съхранение на данни, тъй като това е най-разпространеният избор сред уеб разработчиците. Но ако не ви харесва, не се колебайте да използвате база данни по ваш избор.

Нека подготвим базата данни, в която ще се съхраняват записите в блога ни. Нека започнем с една таблица за публикациите.

Можем да изтеглим Adminer, за да създадем базата данни, или можете да използвате друг инструмент за управление на бази данни.

Нека да отворим Adminer и да създадем нова база данни, наречена quickstart.

Създайте нова таблица с име posts и добавете тези колони към нея:

  • id int, щракнете върху автоматичното увеличаване (AI)
  • title varchar, дължина 255
  • content текст
  • created_at timestamp

Това трябва да изглежда по следния начин

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. Причината за това ще видите по-късно. Засега просто създайте всичко, както е указано, и щракнете върху Запис. Или използвайте пълен код за създаване на таблица и бутон за SQL заявка в Adminer.

Опитайте се да добавите няколко записа в блога, преди да въведем възможността за добавяне на нови записи директно от нашето приложение.

INSERT INTO `posts` (`id`, `title`, `content`, `created_at`) VALUES
(1,	'Статья первая',	'Lorem ipusm dolor one',	CURRENT_TIMESTAMP),
(2,	'Статья вторая',	'Lorem ipsum dolor two',	CURRENT_TIMESTAMP),
(3,	'Статья третья',	'Lorem ipsum dolor three',	CURRENT_TIMESTAMP);

Свързване с база данни

Сега, след като базата данни е създадена и в нея има няколко публикации, е време да ги покажем на нашата нова блестяща страница.

Първо, трябва да укажем на приложението коя база данни да използва. Конфигурацията на връзката с базата данни се съхранява във файла config/common.neon. Създайте връзка DSN и вашите пълномощия. Това трябва да изглежда по следния начин:

database:
	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
	user: *укажите здесь имя пользователя*
	password: *укажите здесь пароль*

Не забравяйте да правите отстъпи, когато редактирате този файл. Форматът NEON приема както интервали, така и табулации, но не и двете заедно! В конфигурационния файл в уеб проекта по подразбиране се използва таблично представяне.

Осъществяване на връзката с базата данни

Презентаторът (намиращ се на адрес app/UI/Home/HomePresenter.php), който ще изписва статиите, трябва да се свърже с базата данни. За да направите това, модифицирайте конструктора по следния начин:

<?php
namespace App\UI\Home;

use Nette;

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

	// ...
}

Зареждане на публикации от базата данни

Нека сега да извлечем публикациите от базата данни и да ги подадем към шаблона, който след това ще визуализира HTML кода. За това е предназначен така нареченият метод render:

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

Сега презентаторът има един метод за визуализация renderDefault(), който предава данните на изглед, наречен default. Шаблоните Preenter могат да бъдат намерени в app/UI/{PresenterName}/{viewName}.latte, така че в този случай шаблонът ще се намира в app/UI/Home/default.latte. В шаблона вече е налична променливата $posts, която съдържа публикациите от базата данни.

Шаблон

Има общ шаблон за цялата страница (наречен layout, със заглавие, стилове, колонтитул и т.н.), както и специфични шаблони за всеки изглед (например за показване на списък със записи в блога), които могат да отменят някои части от шаблона за оформление.

По подразбиране шаблонът за оформление се намира във файла app/UI/@layout.latte, който съдържа:

...
{include content}
...

{include content} вмъква блок с име content в главния шаблон. Можете да го определите в шаблоните на всеки изглед. В нашия случай ще редактираме файла app/UI/Home/default.latte по следния начин

{block content}
	Привет, мир!
{/block}

Той определя блока от съдържание, който ще бъде вмъкнат в оформлението. Ако опресните браузъра си, ще видите страница с текст "Hello, world! (в изходния код също с HTML заглавието и колонтитула, определени в @layout.latte).

Нека покажем записите в блога – за целта редактираме шаблона по следния начин:

{block content}
	<h1 n:block="title">Мой блог</h1>

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

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

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

Ако опресните браузъра си, ще видите списък със записите в блога си. Списъкът не е много изискан или цветен, така че не се колебайте да добавите някой блестящ CSS към www/css/style.css, а след това да поставите връзка към този файл в оформлението (файл @layout.latte):

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

Тагът {foreach} преминава през всички публикации, предадени на шаблона в променливата $posts, и извежда фрагмент от HTML код за всяка публикация. Точно по същия начин се прави и в кода на PHP.

Функцията |date се нарича филтър. Филтрите се използват за форматиране на изхода. Този конкретен филтър преобразува датата (напр. 2013-04-12) в по-разбираема форма (12.04.2013). Филтърът |truncate съкращава низ до определена максимална дължина и добавя елипса в края, ако низът е съкратен. Тъй като това е предварителен преглед, няма смисъл да се показва пълното съдържание на статията. Други филтри по подразбиране можете да намерите в документацията или можете да създадете свои собствени, ако е необходимо.

И още нещо. Можем да направим кода малко по-кратък и следователно по-прост. Можем да заменим tags Latte с n:attributes по следния начин:

{block content}
	<h1>My blog</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}</div>
	</div>
{/block}

n:foreach просто обвийте div с блок foreach (той прави точно същото нещо като предишния блок код).

За да обобщим

Имаме много проста база данни MySQL с няколко публикации в блогове. Приложението се свързва с базата данни и извежда прост списък с публикации.