C/C++ week November Black Friday
Black Friday je tu! Využij jedinečnou příležitost a získej až 80 % znalostí navíc zdarma! Více zde
Pouze tento týden sleva až 80 % na e-learning týkající se C/C++

Lekce 2 - CMS v Nette a Doctrine 2 - Kostra aplikace

Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem.
Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, Úvod do Doctrine 2 v Nette frameworku, jsme si představili potřebné technologie. V dnešním Nette tutoriálu si pomocí Composeru stáhneme všechny důležité knihovny a vytvoříme základní kostru naší aplikace.

Založení projektu

Získání potřebných knihoven

K získání knihoven použijeme Composer. Veškeré důležité informace naleznete na oficiálním webu https://getcomposer.org.

Composer využívá souboru composer.json, ve kterém je uvedeno jaké všechny knihovny mají v aplikaci být. Můžeme pak pomocí příkazového řádku všechny knihovny stáhnout.

Poté, co Composer nainstalujete, v příkazovém řádku zadejte cestu ke složce, kde chcete mít náš projekt, např.:

cd xampp/htdocs/nette_doctrine

a napište:

composer create-project nette/sandbox nazev_projektu
composer.json

Předchozím příkazem se nám stáhne sandbox Nette s adresářovou strukturou. Automaticky se také vytvořil soubor composer.json. Ten otevřete a do parametru require přidejte:

...
"doctrine/orm": "*",
"kdyby/annotations": "^2.2",
"kdyby/console": "^2.4",
"kdyby/events": "^2.4",
"kdyby/doctrine-cache": "^2.4",
"kdyby/doctrine": "~2.3.1",
"symfony/config": "~2.7",
"symfony/translation": "~2.7",
"kdyby/translation": "~2.2"
...

Tímto určíme, aby se nám stáhly všechny potřebné knihovny pro náš projekt. Nakonec v příkazovém řádku zadejte cestu ke složce, kde je soubor composer.json, a napište:

composer update

Tímto Composer projede soubor, zjistí, které knihovny jsou nové nebo upravené, a provede aktualizaci. Všechny knihovny stahuje do složky vendor/.

Pokud budeme chtít v průběhu stahovat další knihovny, nemusíme ručně upravovat soubor, stačí v příkazovém řádku napsat příkaz

composer require nazev/knihovny

např.:

composer require kdyby/translation

Jelikož jsme stáhli sandbox nette, máme adresářovou strukturu vytvořenou automaticky.

Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Poznámka: Zkoušel jsem to pouze na Windows, na Linuxu bude zřejmě trochu jiný postup. Vše je ale na oficiálních stránkách Composeru vysvětleno.

Konfigurace

app/config/con­fig.local.neon

V našem lokálním konfiguračním souboru config.local.neon změníme informace o naší databázi pro Doctrine:

parameters:


doctrine:
    user: root
    password: ****
    dbname: doctrine
    metadata:
        App: %appDir%

Přihlašovací jméno a heslo si samozřejmě nastavte podle sebe.

Metadata (informace o entitách atp.) bude Doctrine hledat v naší složce app/.

app/config/con­fig.neon

Do hlavního konfiguračního souboru config.neon poté zaregistrujeme všechna naše rozšíření:

...
extensions:
        console: Kdyby\Console\DI\ConsoleExtension
        events: Kdyby\Events\DI\EventsExtension
        annotations: Kdyby\Annotations\DI\AnnotationsExtension
        doctrine: Kdyby\Doctrine\DI\OrmExtension
        translation: Kdyby\Translation\DI\TranslationExtension

A na závěr si připravíme možnost překladů a povolíme češtinu a angličtinu (defaultně bude použita čeština).

...
translation:
        default: cs
        fallback: [cs, en]
        whitelist: [cs, en]

Úprava routeru

app/router/Rou­terFactory.php

Abychom mohli rozpoznat, v jakém jazyce chce uživatel stránky zobrazit, přidáme do masky routeru nepovinný parametr locale.

<?php

namespace App;

use Nette;
use Nette\Application\IRouter;
use Nette\Application\Routers\Route;
use Nette\Application\Routers\RouteList;

/**
 * Routovací továrnička.
 * Řídí routování v celé aplikaci.
 * @package App
 */
class RouterFactory
{

        /**
         * Vytváří router pro aplikaci.
         * @return IRouter výsledný router pro aplikaci
         */
        public static function createRouter()
        {
                $router = new RouteList();
                $router[] = new Route("[<locale=cs cs|en>/]<presenter>/<action>[/<id>]", "Homepage:default");
                return $router;
        }
}

Pomocí hranatých závorek jsme určili, že parametr locale není povinný a pokud nebude v URL vyplněn, použije se defaultně čeština.

Naše URL poté mohou vypadat např. en/article-category/list.

Způsob překladu

Všechny texty, které se budou překládat, budou uloženy pod klíčem v NEON souboru (stejný používá i konfigurační soubor). Jak to funguje, si můžete zkusit zde: http://ne-on.org.

Překlady budeme psát do jednotlivých souborů podle toho, kam dané texty spadají (texty ohledně článků budou v souborech article, pro formuláře v souborech form, pro výjimky exception, obecné texty common apod.). Kdyby\Translation se poté automaticky postará o načtení všech důležitých souborů. Způsob rozdělení je tedy na nás, jak se nám to zdá přehledné (přiznávám, že nakonec stejně budou texty různě poházeny).

Výhodou tohoto nástroje také je, že můžeme překládat i texty s proměnlivým obsahem - jednoduše napíšeme zástupný identifikátor, který se poté přepíše hodnotou, např.:

textKey: "Celkem je zde %articlesCount% článků a %usersCount% aktivních uživatelů"

V šabloně poté hodnoty dosadíme pomocí pole.

{_textKey, ["articlesCount" => 500, "usersCount" => 30]}

// vypíše  Celkem je zde 500 článků a 30 aktivních uživatelů

Překlad již na úrovni vrstvy Presenteru obstarává třída Kdyby\Translation\Translator. Tu si automaticky injectujeme do třídy BasePresenter a také se bude předávat konstruktorem do form factory tříd.

app/presenter­s/BasePresenter­.php

Konečně se dostáváme k troše akce. Jako první si upravíme náš BasePresenter a vytvoříme mu atribut locale a Translator, který se automaticky injectuje. Nezapomínejte, že všechny atributy, které se injectují automaticky, musí mít viditelnost public.

<?php

namespace App\Presenters;

use App\Model;
use Nette;
use Nette\Application\UI\Presenter;

/**
 * Základní presenter pro všechny ostatní presentery aplikace.
 * @package App\Presenters
 */
abstract class BasePresenter extends Presenter
{
        /** @persistent null|string Určuje jazykovou verzi webu. */
        public $locale;

        /**
         * @var \Kdyby\Translation\Translator Obstarává jazykový překlad na úrovni presenteru.
         * @inject
         */
        public $translator;
}

Atribut $locale obsahuje informaci o jazyku. Díky anotaci @persistent je hodnota automaticky předávána při každém požadavku - nemusíme ji proto uvádět v odkazech.

Makro na překlad

Dále si ještě do třídy BasePresenter zaregistrujeme makro na překlad:

...
/**
 * Registrace makra na překlad.
 * @inheritdoc
 */
protected function createTemplate()
{
        /** @var Template $template Latte šablona pro aktuální presenter. */
        $template = parent::createTemplate();
        $this->translator->createTemplateHelpers()
                ->register($template->getLatte());
        return $template;
}

Tímto zaregistrujeme makro {_}, díky kterému lze v šabloně jednoduše přeložit text, a nemusíme tak překlady ukládat do proměnných a předávat šablonám.

Databázová struktura

Abychom nemuseli v každém dalším článku něco přidávat nebo upravovat, přiložím rovnou soubor db.sql s SQL příkazem, který celou databázi vytvoří.

Databáze obsahuje pět tabulek:

  • article
  • article_category
  • article_comment
  • user
  • user_settings

Do databáze budou automaticky přidání dva uživatelé:

Jméno Heslo Popis
admin admin administrátor
user user uživatel

Poznámka: Doctrine umí z entit vygenerovat strukturu databáze a opačně. Více se dozvíte zde.

Přebytečné soubory v Nette sandboxu

  • model/UserManager.php - tento soubor z projektu úplně odstraňte - nejen, že nám k ničemu nebude, ale naopak by nám překážel (kvůli implementaci rozhraní Nette\Security\IAuthenticator). Také ho odstraňte ze souboru config.neon.
  • forms/SignFormFactory.php - můžete odstranit, my si budeme vytvářet náš vlastní, trochu odlišný.
  • presenters/SignPresenter.php - také si budeme vytvářet vlastní.

Tímto druhou lekci zakončíme. V lekci příští, CMS v Nette a Doctrine 2 - Modely a Layout, začneme pomalu stavět naši modelovou vrstvu.


 

Stáhnout

Staženo 231x (3.43 MB)
Aplikace je včetně zdrojových kódů v jazyce PHP

 

 

Článek pro vás napsal Martin Konečný (pavelco1998)
Avatar
Jak se ti líbí článek?
5 hlasů
Autor se o IT moc nezajímá, raději by se věnoval speciálním jednotkám jako jsou SEALs nebo SAS. Když už to ale musí být něco z IT, tak tvorba web. aplikací v PHP. Také vyvýjí novou českou prohlížečovou RPG hru a provozuje osobní web http://www.mkonecny.cz
Předchozí článek
Úvod do Doctrine 2 v Nette frameworku
Všechny články v sekci
CMS v Nette a Doctrine 2
Miniatura
Následující článek
CMS v Nette a Doctrine 2 - Modely a Layout
Aktivity (2)

 

 

Komentáře
Zobrazit starší komentáře (7)

Avatar
Marek Průša:4.6.2017 11:40

Díky. Vypnuto, už to funguje :)

 
Odpovědět
4.6.2017 11:40
Avatar
Aleš Kopecký:8.4.2018 20:01

Ahoj,
jakým způsobem mám provést změnu verzí (vzhledem k tomu, že článek byl napsán před nějakou dobou) v souboru composer.json u přidaných balíčků (viz přidání require záznamů v začátku článku)?

To, že si vyhledám balíčky na packagist.org a k balíčkům v composer.json napíšu vždy nejnovější verzi, se mi nezdá jako správný způsob...
Děkuji za každou radu :)

 
Odpovědět
8.4.2018 20:01
Avatar
Odpovídá na Aleš Kopecký
Martin Konečný (pavelco1998):8.4.2018 21:04

Ahoj,
popravdě neznám způsob, který by ti dokázal aktualizovat balíčky na tu úplně nejnovější verzi. Důvod je ten, že určité verze spolu nemusí být kompatibilní, tedy se v composeru určuje konkrétní verze (příp. rozsah verzí, z nichž se ti nainstaluje ta aktuální), aby se ti s každým composer update nerozpadl program.
Můžeš v composeru zadat, že se ti verze balíčku bude držet třeba na "2.4", ale když máš aktuálně verzi "2.4.2" a bude nová verze "2.4.5", tak se ti to aktualizuje na tu "2.4.5", ale verze "2.5" se ti už nenainstaluje, pokud ji explicitně neuvedeš.
Z hlavy přesně neznám ten způsob, detailně je to popsané v dokumentaci, viz https://getcomposer.org/…/versions.md.

Jen ještě takové upozornění - pokud si aktualizuješ balíčky na novější verze, než které jsou v seriálu, je možné, že ti něco přestane fungovat (př. Kdyby\BaseEntity je v nových verzích zavrhnutá). Počítej tedy s tím, že možná budeš muset udělat i pár úprav v kódu. Neměly by ale být nějak zásadní, např. místo Kdyby\BaseEntity se nově používá trait MagicAccessors. Na příkladu

class MyEntity extends Kdyby\Doctrine\BaseEntity
{

}

tento kód nahradíš za

class MyEntity
{

        use Kdyby\Doctrine\Entities\MagicAccessors;

}

Takže by v tom nijak velký problém být neměl.

Editováno 8.4.2018 21:06
Odpovědět
8.4.2018 21:04
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Vincent
Člen
Avatar
Vincent:4. října 13:58

dobrý den,
nemám zkušenost s kdyby, kdyby/doctrine
zapasím už skoro den ale nemohl jsem rozjet tenhle projekt.

Mám php 7.3.9 a na na jiné laptopu php 5.5.9

Nemohl byste někdo mi poslat composer.json soubor nebo jeho "require" část
pro jednu z těch uvedených php?

děkuji, danke.

 
Odpovědět
4. října 13:58
Avatar
Odpovídá na Vincent
Martin Konečný (pavelco1998):4. října 14:05

Ahoj, nejde to na verzi PHP 7 ani PHP 5.5.9? Mohl by jsi prosím ukázat screen, jakou chybovou hlášku píše konzole?
Děkuji

Odpovědět
4. října 14:05
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
Vincent
Člen
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Vincent:4. října 14:59

ahoj Martine,
tech chyb je strasne moc u tech mych php, zkousel jsem hodne kombinaci. Treba:

[Fri Oct 04 13:45:25.511892 2019] [php7:error] [pid 3704:tid 928] [client ::1:8747] PHP Fatal error: Cannot use 'Object' as class name as it is reserved in D:\\Bitnami\\wam­pstack-7.3.9-0\\apache2\\htdoc­s\\cms_nette_doc­trine\\vendor\\net­te\\utils\\src\\U­tils\\Object.php on line 52

klidne sdilej sem nejenom mi ten composer.json :) pak ja downgrade php :)
dik.

setris mi cas.

 
Odpovědět
4. října 14:59
Avatar
Odpovídá na Vincent
Martin Konečný (pavelco1998):4. října 16:04

Aplikace je stavěna pro verzi Nette 2.3, kde se v Nette nachází Nette\Utils\Object, a v PHP 7 je slovo "object" rezervované slovo, a nelze to tedy použít.

Když aplikaci zkusíš na té PHP 5.5.9, jakou to prosím hlásí chybu?

Odpovědět
4. října 16:04
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Vincent
Člen
Avatar
Vincent:4. října 19:05

ahoj Martine,

tak jsem zkousel nette 2.3 v php 5.5.9
a narazil jsem na screen s error

Parse error: syntax error, unexpected 'function' (T_FUNCTION), expecting identifier (T_STRING) or \\ (T_NS_SEPARATOR) in D:\htdocs\cms-nette23-doctrine\vendor\doc­trine\event-manager\lib\Doc­trine\Common\E­ventManager.php on line 4

a line 4 je:
use function spl_object_hash;

:) co mam delat s tou Docrinou?

dik za tvuj cas.

 
Odpovědět
4. října 19:05
Avatar
Vincent
Člen
Avatar
Odpovídá na Vincent
Vincent:4. října 19:13

pridam jeste vystup z composer:

Updating dependencies (including require-dev)
Package operations: 24 installs, 0 updates, 0 removals
- Installing tracy/tracy (v2.3.12): Loading from cache
- Installing latte/latte (v2.3.13): Loading from cache
- Installing nette/utils (v2.3.11): Loading from cache
- Installing nette/tokenizer (v2.2.4): Loading from cache
- Installing nette/security (v2.3.2): Loading from cache
- Installing nette/safe-stream (v2.3.3): Loading from cache
- Installing nette/finder (v2.3.2): Loading from cache
- Installing nette/caching (v2.3.5): Loading from cache
- Installing nette/robot-loader (v2.3.2): Loading from cache
- Installing nette/reflection (v2.3.2): Loading from cache
- Installing nette/php-generator (v2.3.6): Loading from cache
- Installing nette/neon (v2.3.5): Loading from cache
- Installing nette/mail (v2.3.5): Loading from cache
- Installing nette/http (v2.3.9): Loading from cache
- Installing nette/component-model (v2.2.5): Loading from cache
- Installing nette/forms (v2.3.12): Loading from cache
- Installing nette/di (v2.3.14): Loading from cache
- Installing nette/deprecated (v2.3.3): Downloading (100%)
- Installing nette/database (v2.3.11): Loading from cache
- Installing nette/bootstrap (v2.3.5): Loading from cache
- Installing nette/application (v2.3.13): Loading from cache
- Installing nette/nette (v2.3.10): Downloading (100%)
- Installing dg/adminer-custom (v1.18.0): Loading from cache
- Installing nette/tester (v1.7.2): Loading from cache
latte/latte suggests installing ext-fileinfo (to use filter |datastream)
nette/utils suggests installing ext-intl (for script transliteration in Strings:
:webalize() and toAscii())
nette/mail suggests installing ext-fileinfo (to detect type of attached files)
nette/http suggests installing ext-fileinfo (to detect type of uploaded files)
Writing lock file
Generating autoload files

 
Odpovědět
4. října 19:13
Avatar
Vincent
Člen
Avatar
Vincent:5. října 10:16

ahoj Martine,

děkuji Ti za pomoc, teď zkoumám lekci 3.

 
Odpovědět
5. října 10:16
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 17. Zobrazit vše