Nette Documentation Preview

syntax
Domača stran spletnega dnevnika
*******************************

.[perex]
Ustvarimo domačo stran, ki prikazuje vaše zadnje objave.


Preden začnemo, morate poznati vsaj nekaj osnov o oblikovnem vzorcu Model-View-Presenter (podobno kot MVC((Model-View-Controller))):

- **Model** - plast za obdelavo podatkov. Je popolnoma ločen od preostalega dela aplikacije. Komunicira samo s predstavniki.

- **Pogled** - sloj za definicijo sprednjega dela. Z uporabo predlog uporabniku prikazuje zahtevane podatke.

- **Predstavitelj** (ali kontroler) - povezovalni sloj. Presenter povezuje model in pogled. Obdeluje zahteve, od Modela zahteva podatke in jih nato posreduje trenutnemu Pogledu.


V primeru zelo preproste aplikacije, kot je naš blog, bo plast Modela dejansko sestavljena le iz poizvedb v podatkovno zbirko - zanjo ne potrebujemo nobene dodatne kode PHP. Ustvariti moramo le plasti Presenter in View. V Netteu ima vsak Presenter svoje Poglede, zato bomo nadaljevali z obema hkrati.


Ustvarjanje podatkovne zbirke s programom Adminer .[#toc-creating-the-database-with-adminer]
============================================================================================

Za shranjevanje podatkov bomo uporabili podatkovno zbirko MySQL, saj je najpogostejša izbira med spletnimi razvijalci. Če pa vam ni všeč, lahko uporabite podatkovno zbirko po lastni izbiri.

Pripravimo podatkovno zbirko, v kateri bomo shranjevali objave našega bloga. Začnemo lahko zelo preprosto - z eno samo tabelo za objave.

Za izdelavo podatkovne zbirke lahko prenesemo [program Adminer |https://www.adminer.org], lahko pa uporabite tudi drugo orodje za upravljanje podatkovnih zbirk.


Odpremo program Adminer in ustvarimo novo zbirko podatkov z imenom `quickstart`.

Ustvarimo novo tabelo z imenom `posts` in dodamo te stolpce:
- `id` int, kliknite na samodejno povečanje (AI).
- `title` varchar, dolžina 255
- `content` besedilo
- `created_at` časovni žig

Izgledati mora takole:

[* 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]
Zelo pomembno je, da uporabite shranjevanje tabele **InnoDB**. Razlog za to boste videli pozneje. Za zdaj izberite to in pošljite. Zdaj lahko pritisnete Shrani.

Poskusite dodati nekaj vzorčnih objav na blogu, preden bomo implementirali zmožnost dodajanja novih objav neposredno iz naše aplikacije.

```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);
```


Povezovanje s podatkovno bazo .[#toc-connecting-to-the-database]
================================================================

Ko je zbirka podatkov ustvarjena in imamo v njej nekaj objav, je zdaj pravi čas, da jih prikažemo na naši novi svetleči strani.

Najprej moramo našemu programu povedati, katero podatkovno zbirko naj uporabi. Konfiguracija povezave s podatkovno bazo je shranjena v `config/common.neon`. Nastavite povezavo DSN((Data Source Name)) in svoje poverilnice. Izgledati mora takole:

```neon .{file:config/common.neon}
database:
	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
	user: *enter user name*
	password: *enter password here*
```

.[note]
Pri urejanju te datoteke bodite pozorni na alineje. [Oblika NEON |neon:format] sprejema tako presledke kot tabulatorje, vendar ne obojega skupaj! Konfiguracijska datoteka v spletnem projektu privzeto uporablja tabulatorje.


Vbrizgavanje povezave s podatkovno bazo .[#toc-injecting-the-database-connection]
=================================================================================

Predstavitveni program `HomePresenter`, ki bo objavil seznam člankov, potrebuje povezavo s podatkovno bazo. Če jo želite prejeti, napišite konstruktor, kot je ta:

```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,
	) {
	}

	// ...
}
```


Nalaganje objav iz zbirke podatkov .[#toc-loading-posts-from-the-database]
==========================================================================

Zdaj prenesimo objave iz zbirke podatkov in jih posredujemo predlogi, ki bo nato prikazala kodo HTML. Za to je namenjena tako imenovana metoda *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);
}
```

Predstavitev ima zdaj eno metodo upodabljanja `renderDefault()`, ki posreduje podatke pogledu z imenom `default`. Predloge predstavnikov se nahajajo v `app/UI/{PresenterName}/{viewName}.latte`, zato se bo v tem primeru predloga nahajala v `app/UI/Home/default.latte`. V predlogi je zdaj na voljo spremenljivka z imenom `$posts`, ki vsebuje objave iz podatkovne zbirke.


Predloga .[#toc-template]
=========================

Obstaja splošna predloga za celotno stran (imenovana *layout*, z glavo, slogovnimi listi, nogo, ...) in nato posebne predloge za vsak pogled (npr. za prikaz seznama blogovskih objav), ki lahko prekrijejo nekatere dele predloge layout.

Privzeto se predloga postavitve nahaja v spletnem mestu `app/UI/@layout.latte`, ki vsebuje:

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

`{include content}` v glavno predlogo vstavi blok z imenom `content`. Določite ga lahko v predlogah vsakega pogleda. V tem primeru bomo tako uredili datoteko `Home/default.latte`:

```latte .{file:app/UI/Home/default.latte}
{block content}
	Hello World
{/block}
```

V njej je opredeljen [blok |latte:tags#block]*vsebina*, ki bo vstavljen v postavitev. Če osvežite brskalnik, boste videli stran z besedilom "Hello world" (v izvorni kodi tudi z glavo in nogo HTML, ki sta definirani v `@layout.latte`).

Prikažimo blogovske objave - predlogo bomo uredili takole:

```latte .{file:app/UI/Home/default.latte}
{block content}
	<h1>My blog</h1>

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

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

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

Če osvežite brskalnik, se bo prikazal seznam vaših blogovskih objav. Seznam ni preveč domišljen ali barvit, zato lahko na `www/css/style.css` dodate nekaj [bleščečih CSS |https://github.com/nette-examples/quickstart/blob/v4.0/www/css/style.css] in ga povežete v postavitev:

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

Oznaka `{foreach}` iterira čez vse objave, ki so bile posredovane predlogi v spremenljivki `$posts`, in za vsako objavo prikaže del kode HTML. Tako kot bi to storila koda PHP.

Ta `|date` se imenuje filter. Filtri se uporabljajo za oblikovanje izpisa. Ta filter pretvori datum (npr. `2013-04-12`) v bolj berljivo obliko (`12. 4. 2013`). Filter `|truncate` skrajša niz na določeno največjo dolžino in na koncu doda elipso, če je niz skrajšan. Ker gre za predogled, nima smisla prikazovati celotne vsebine članka. Druge privzete filtre najdete [v dokumentaciji |latte:filters], po potrebi pa lahko ustvarite tudi svoje.

Še ena stvar. Kodo lahko še nekoliko skrajšamo in s tem poenostavimo. Oznake *Latte* lahko nadomestimo z *n:atributi*, kot sledi:

```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`, preprosto ovije *div* z blokom *foreach* (naredi popolnoma enako stvar kot prejšnji blok kode).


Povzetek .[#toc-summary]
========================

Imamo zelo preprosto podatkovno zbirko MySQL z nekaj objavami v blogih. Aplikacija se poveže s podatkovno bazo in prikaže preprost seznam objav.

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

Domača stran spletnega dnevnika

Ustvarimo domačo stran, ki prikazuje vaše zadnje objave.

Preden začnemo, morate poznati vsaj nekaj osnov o oblikovnem vzorcu Model-View-Presenter (podobno kot MVC):

  • Model – plast za obdelavo podatkov. Je popolnoma ločen od preostalega dela aplikacije. Komunicira samo s predstavniki.
  • Pogled – sloj za definicijo sprednjega dela. Z uporabo predlog uporabniku prikazuje zahtevane podatke.
  • Predstavitelj (ali kontroler) – povezovalni sloj. Presenter povezuje model in pogled. Obdeluje zahteve, od Modela zahteva podatke in jih nato posreduje trenutnemu Pogledu.

V primeru zelo preproste aplikacije, kot je naš blog, bo plast Modela dejansko sestavljena le iz poizvedb v podatkovno zbirko – zanjo ne potrebujemo nobene dodatne kode PHP. Ustvariti moramo le plasti Presenter in View. V Netteu ima vsak Presenter svoje Poglede, zato bomo nadaljevali z obema hkrati.

Ustvarjanje podatkovne zbirke s programom Adminer

Za shranjevanje podatkov bomo uporabili podatkovno zbirko MySQL, saj je najpogostejša izbira med spletnimi razvijalci. Če pa vam ni všeč, lahko uporabite podatkovno zbirko po lastni izbiri.

Pripravimo podatkovno zbirko, v kateri bomo shranjevali objave našega bloga. Začnemo lahko zelo preprosto – z eno samo tabelo za objave.

Za izdelavo podatkovne zbirke lahko prenesemo program Adminer, lahko pa uporabite tudi drugo orodje za upravljanje podatkovnih zbirk.

Odpremo program Adminer in ustvarimo novo zbirko podatkov z imenom quickstart.

Ustvarimo novo tabelo z imenom posts in dodamo te stolpce:

  • id int, kliknite na samodejno povečanje (AI).
  • title varchar, dolžina 255
  • content besedilo
  • created_at časovni žig

Izgledati mora takole:

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;

Zelo pomembno je, da uporabite shranjevanje tabele InnoDB. Razlog za to boste videli pozneje. Za zdaj izberite to in pošljite. Zdaj lahko pritisnete Shrani.

Poskusite dodati nekaj vzorčnih objav na blogu, preden bomo implementirali zmožnost dodajanja novih objav neposredno iz naše aplikacije.

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);

Povezovanje s podatkovno bazo

Ko je zbirka podatkov ustvarjena in imamo v njej nekaj objav, je zdaj pravi čas, da jih prikažemo na naši novi svetleči strani.

Najprej moramo našemu programu povedati, katero podatkovno zbirko naj uporabi. Konfiguracija povezave s podatkovno bazo je shranjena v config/common.neon. Nastavite povezavo DSN in svoje poverilnice. Izgledati mora takole:

database:
	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
	user: *enter user name*
	password: *enter password here*

Pri urejanju te datoteke bodite pozorni na alineje. Oblika NEON sprejema tako presledke kot tabulatorje, vendar ne obojega skupaj! Konfiguracijska datoteka v spletnem projektu privzeto uporablja tabulatorje.

Vbrizgavanje povezave s podatkovno bazo

Predstavitveni program HomePresenter, ki bo objavil seznam člankov, potrebuje povezavo s podatkovno bazo. Če jo želite prejeti, napišite konstruktor, kot je ta:

<?php
namespace App\UI\Home;

use Nette;

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

	// ...
}

Nalaganje objav iz zbirke podatkov

Zdaj prenesimo objave iz zbirke podatkov in jih posredujemo predlogi, ki bo nato prikazala kodo HTML. Za to je namenjena tako imenovana metoda render:

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

Predstavitev ima zdaj eno metodo upodabljanja renderDefault(), ki posreduje podatke pogledu z imenom default. Predloge predstavnikov se nahajajo v app/UI/{PresenterName}/{viewName}.latte, zato se bo v tem primeru predloga nahajala v app/UI/Home/default.latte. V predlogi je zdaj na voljo spremenljivka z imenom $posts, ki vsebuje objave iz podatkovne zbirke.

Predloga

Obstaja splošna predloga za celotno stran (imenovana layout, z glavo, slogovnimi listi, nogo, …) in nato posebne predloge za vsak pogled (npr. za prikaz seznama blogovskih objav), ki lahko prekrijejo nekatere dele predloge layout.

Privzeto se predloga postavitve nahaja v spletnem mestu app/UI/@layout.latte, ki vsebuje:

...
{include content}
...

{include content} v glavno predlogo vstavi blok z imenom content. Določite ga lahko v predlogah vsakega pogleda. V tem primeru bomo tako uredili datoteko Home/default.latte:

{block content}
	Hello World
{/block}

V njej je opredeljen blokvsebina, ki bo vstavljen v postavitev. Če osvežite brskalnik, boste videli stran z besedilom „Hello world“ (v izvorni kodi tudi z glavo in nogo HTML, ki sta definirani v @layout.latte).

Prikažimo blogovske objave – predlogo bomo uredili takole:

{block content}
	<h1>My blog</h1>

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

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

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

Če osvežite brskalnik, se bo prikazal seznam vaših blogovskih objav. Seznam ni preveč domišljen ali barvit, zato lahko na www/css/style.css dodate nekaj bleščečih CSS in ga povežete v postavitev:

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

Oznaka {foreach} iterira čez vse objave, ki so bile posredovane predlogi v spremenljivki $posts, in za vsako objavo prikaže del kode HTML. Tako kot bi to storila koda PHP.

Ta |date se imenuje filter. Filtri se uporabljajo za oblikovanje izpisa. Ta filter pretvori datum (npr. 2013-04-12) v bolj berljivo obliko (12. 4. 2013). Filter |truncate skrajša niz na določeno največjo dolžino in na koncu doda elipso, če je niz skrajšan. Ker gre za predogled, nima smisla prikazovati celotne vsebine članka. Druge privzete filtre najdete v dokumentaciji, po potrebi pa lahko ustvarite tudi svoje.

Še ena stvar. Kodo lahko še nekoliko skrajšamo in s tem poenostavimo. Oznake Latte lahko nadomestimo z n:atributi, kot sledi:

{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, preprosto ovije div z blokom foreach (naredi popolnoma enako stvar kot prejšnji blok kode).

Povzetek

Imamo zelo preprosto podatkovno zbirko MySQL z nekaj objavami v blogih. Aplikacija se poveže s podatkovno bazo in prikaže preprost seznam objav.