Slevový týden - Květen Office week
Pouze tento týden sleva až 80 % na e-learning týkající se MS Office
30 % bodů zdarma na online výuku díky naší Slevové akci!

Lekce 6 - Jednoduchý redakční systém v Nette - Výpis článku

V minulé lekci, Jednoduchý redakční systém v Nette - Struktura projektu, jsme si připravili projektovou strukturu pro jednoduchý redakční systém.

Dnes se rovnou bez zbytečných řečí vrhneme do programování CoreModule. Takže jdeme na to! :)

Databáze

Prvně se podíváme na nastavení a obsah databáze. Vytvoříme si novou databázi pro náš projekt (např. nette-rs) a v ní spustíme následující SQL:

-- ----------------------------
-- Table structure for `article`
-- ----------------------------
DROP TABLE IF EXISTS `article`;
CREATE TABLE `article` (
    `article_id`  int(11) NOT NULL                   AUTO_INCREMENT,
    `title`       varchar(255) COLLATE utf8_czech_ci DEFAULT NULL,
    `content`     text COLLATE utf8_czech_ci,
    `url`         varchar(255) COLLATE utf8_czech_ci DEFAULT NULL,
    `description` varchar(255) COLLATE utf8_czech_ci DEFAULT NULL,
    PRIMARY KEY (`article_id`),
    UNIQUE KEY `url` (`url`)
) ENGINE = InnoDB AUTO_INCREMENT = 3 DEFAULT CHARSET = utf8 COLLATE = utf8_czech_ci;

-- ----------------------------
-- Records of article
-- ----------------------------
INSERT INTO `article` VALUES ('1', 'Úvod', '<p>Vítejte na našem webu!</p><p>Tento web je postaven na <strong>jednoduchém redakčním systému v Nette frameworku</strong>. Toto je úvodní článek, načtený z databáze.</p>', 'uvod', 'Úvodní článek na webu v Nette v PHP');
INSERT INTO `article` VALUES ('2', 'Stránka nebyla nalezena', '<p>Litujeme, ale požadovaná stránka nebyla nalezena. Zkontrolujte prosím URL adresu.</p>', 'chyba', 'Stránka nebyla nalezena.');

To nám vytvoří a naplní tabulku s články, kterou budeme dále potřebovat.

SQL skript naleznete i v archivu ve složce sql/ pod názvem create_script.sql.

app/config/con­fig.neon

Nakonec je ještě potřeba nastavit v Nette připojení do naší databáze. To uděláme v hlavním konfiguračním souboru tak, že upravíme již přednastavené parametry, tj. název naší databáze i uživatelské jméno a heslo. Výsledek by měl vypadat přibližně takto:

...
# Konfigurace databázového připojení v rámci celé aplikace.
database:
    dsn: 'mysql:host=127.0.0.1;dbname=nette-rs' # Typ, adresa a název databáze
    user: root     # Uživatelské jméno
    password: **** # Heslo
    options:
        lazy: yes
...

Pokud máte jinou konfiguraci databáze v různých prostředích (localhost vs. hosting), používá se ještě lokální konfigurační soubor config.local.neon, jehož nastavení přepíše to globální specificky pro dané prostředí.

Model

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

Stejně jako v minulé aplikaci začneme hezky od modelu.

app/model/Data­baseManager.php

Protože jsme všichni znalí OOP a nechceme mít zbytečné duplicity v kódu, připravíme si základní abstraktní modelovou třídu pro práci s databází, která bude pomocí Dependency Injection (zkráceně DI) získávat přístup k Nette rozhraní pro práci s databází a všechny další modelové třídy z ní budou následně dědit, aby automaticky tento přístup získaly. Třída je poměrně jednoduchá a vypadá takto:

<?php

namespace App\Model;

use Nette\Database\Context;
use Nette\SmartObject;

/**
 * Základní model pro všechny ostatní databázové modely aplikace.
 * Poskytuje přístup k práci s databází.
 * @package App\Model
 */
abstract class DatabaseManager
{
    use SmartObject;

    /** @var Context Služba pro práci s databází. */
    protected $database;

    /**
     * Konstruktor s injektovanou službou pro práci s databází.
     * @param Context $database automaticky injektovaná Nette služba pro práci s databází
     */
    public function __construct(Context $database)
    {
        $this->database = $database;
    }
}

app/CoreModule/mo­del/ArticleMa­nager.php

Další na řadě je model pro správu článků, který tedy podědí ze třídy DatabaseManager. Bude již součástí našeho CoreModulu a jeho cílem je definovat metody, které pomocí Nette rozhraní pro práci s databází umožní manipulaci s tabulkou článků, kterou jsme si vytvořili výše.

<?php

namespace App\CoreModule\Model;

use App\Model\DatabaseManager;
use Nette\Database\Table\ActiveRow;
use Nette\Database\Table\Selection;
use Nette\Utils\ArrayHash;

/**
 * Model pro správu článků v redakčním systému.
 * @package App\CoreModule\Model
 */
class ArticleManager extends DatabaseManager
{
    /** Konstanty pro práci s databází. */
    const
        TABLE_NAME = 'article',
        COLUMN_ID = 'article_id',
        COLUMN_URL = 'url';

    /**
     * Vrátí seznam všech článků v databázi seřazený sestupně od naposledy přidaného.
     * @return Selection seznam všech článků
     */
    public function getArticles()
    {
        return $this->database->table(self::TABLE_NAME)->order(self::COLUMN_ID . ' DESC');
    }

    /**
     * Vrátí článek z databáze podle jeho URL.
     * @param string $url URl článku
     * @return false|ActiveRow první článek, který odpovídá URL nebo false pokud článek s danou URL neexistuje
     */
    public function getArticle($url)
    {
        return $this->database->table(self::TABLE_NAME)->where(self::COLUMN_URL, $url)->fetch();
    }

    /**
     * Uloží článek do systému.
     * Pokud není nastaveno ID vloží nový článek, jinak provede editaci článku s daným ID.
     * @param array|ArrayHash $article článek
     */
    public function saveArticle($article)
    {
        if (empty($article[self::COLUMN_ID])) {
            unset($article[self::COLUMN_ID]);
            $this->database->table(self::TABLE_NAME)->insert($article);
        } else
            $this->database->table(self::TABLE_NAME)->where(self::COLUMN_ID, $article[self::COLUMN_ID])->update($article);
    }

    /**
     * Odstraní článek s danou URL.
     * @param string $url URL článku
     */
    public function removeArticle($url)
    {
        $this->database->table(self::TABLE_NAME)->where(self::COLUMN_URL, $url)->delete();
    }
}

Všimněte si, že Nette rozhraní pro práci s databází kopíruje pokládání klasických SQL dotazů, ovšem v rámci PHP kódu v trochu zjednodušeném formátu. A také obsahuje např. ochranu proti SQL injection. ;)

Presentery

Dále budeme pokračovat s presentery. Začneme tím, že smažeme základní presenter app/presenters/HomepagePresenter.php, protože už ho nebudeme potřebovat. Na konci této lekce už totiž budeme mít základ zcela nové aplikace.

app/presenter­s/BasePresenter­.php

Stejně jako ve většině projektů v Nette a podobně jako v našem modelu, začneme od základní abstraktní třídy, ze které dědí všechny ostatní presentery a tou je BasePresenter. V sandboxu, ze kterého vycházíme, už je vytvořen, takže ho jen trošku upravíme:

<?php

namespace App\Presenters;

use Nette\Application\UI\Presenter;

/**
 * Základní presenter pro všechny ostatní presentery aplikace.
 * @package App\Presenters
 */
abstract class BasePresenter extends Presenter
{
}

app/CoreModule/pre­senters/Article­Presenter.php

Nyní se dostáváme k presenteru, který nám pomocí ArticleManager bude předávat data článků do šablony. Tento presenter tvoří hlavní část našeho CoreModule a vypadá následovně:

<?php

namespace App\CoreModule\Presenters;

use App\CoreModule\Model\ArticleManager;
use App\Presenters\BasePresenter;
use Nette\Application\BadRequestException;

/**
 * Presenter pro vykreslování článků.
 * @package App\CoreModule\Presenters
 */
class ArticlePresenter extends BasePresenter
{
    /** @var string URL výchozího článku. */
    private $defaultArticleUrl;

    /** @var ArticleManager Model pro správu s článků. */
    private $articleManager;

    /**
     * Konstruktor s nastavením URL výchozího článku a injektovaným modelem pro správu článků.
     * @param string         $defaultArticleUrl URL výchozího článku
     * @param ArticleManager $articleManager    automaticky injektovaný model pro správu článků
     */
    public function __construct($defaultArticleUrl, ArticleManager $articleManager)
    {
        parent::__construct();
        $this->defaultArticleUrl = $defaultArticleUrl;
        $this->articleManager = $articleManager;
    }

    /**
     * Načte a předá článek do šablony podle jeho URL.
     * @param string|null $url URL článku
     * @throws BadRequestException Jestliže článek s danou URL nebyl nalezen.
     */
    public function renderDefault($url = null)
    {
        if (!$url) $url = $this->defaultArticleUrl; // Pokud není zadaná URL, vezme se URL výchozího článku.

        // Pokusí se načíst článek s danou URL a pokud nebude nalezen vyhodí chybu 404.
        if (!($article = $this->articleManager->getArticle($url)))
            $this->error(); // Vyhazuje výjimku BadRequestException.

        $this->template->article = $article; // Předá článek do šablony.
    }
}

app/CoreModule/con­fig/config.ne­on

Aby fungovalo automatické předávání závislostí pomocí DI, musíme ještě zaregistrovat ArticleManager jako službu v naší aplikaci. Konkrétně to provedeme v konfiguračním souboru našeho modulu, kde i předáme konfiguraci URL výchozího článku do našeho nového presenteru:

#
# Konfigurační soubor pro CoreModule.
#
parameters:
    defaultArticleUrl: 'uvod' # URL výhozího článku


# Nastavení služeb pro CoreModule.
services:
    - App\CoreModule\Model\ArticleManager # Vlastní služba dále přístupná pomocí DI.
    - App\CoreModule\Presenters\ArticlePresenter(%defaultArticleUrl%) # Předání nastavení při vytváření služby presenteru.

Routování

app/router/Rou­terFactory.php

Abychom se opravdu dostali k daným článkům podle jejich URL, je nutné ještě upravit routování naší aplikace. To zařídíme úpravou již existující třídy ze sandboxu RouterFactory, kde nastavíme směrování na náš nový presenter:

<?php

namespace App;

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

/**
 * Továrna na routovací pravidla.
 * Řídí směrování a generovaní URL adres v celé aplikaci.
 * @package App
 */
class RouterFactory
{
    use StaticClass;

    /**
     * Vytváří a vrací seznam routovacích pravidel pro aplikaci.
     * @return IRouter výsledný router pro aplikaci
     */
    public static function createRouter()
    {
        $router = new RouteList;
        $router[] = new Route('[<url>]', 'Core:Article:default');
        return $router;
    }
}

To je zatím vše.

V příští lekci, Jednoduchý redakční systém v Nette - Administrace, se budeme věnovat šablonám a projekt zprovozníme.


 

 

Článek pro vás napsal Jindřich Máca
Avatar
Jak se ti líbí článek?
21 hlasů
Autor se věnuje převážně webovým technologiím, ale má velkou zálibu ve všem vědeckém, nejen ze světa IT. :-)
Předchozí článek
Jednoduchý redakční systém v Nette - Struktura projektu
Všechny články v sekci
Základy Nette frameworku
Miniatura
Následující článek
Jednoduchý redakční systém v Nette - Administrace
Aktivity (9)

 

 

Komentáře

Avatar
Samik11
Redaktor
Avatar
Samik11:9.7.2015 18:58

Super ze prepisujes quickstart do mvc. :) mas nejaky obecny navod jak nejlepe strukturovat modely? Zda 1 model pro 1 tabulku (jako v predchozi verzi quickstartu)? Ja se u vetsich projektu snazim davat do jednoho modelu logicky souvisejici celky i kdyz z ruznych tabulek (objednavaci proces).

Odpovědět
9.7.2015 18:58
„Radost vidět a rozumět, to je nejkrásnější dar přírody.“ Albert Einstein
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Samik11
Jindřich Máca:9.7.2015 21:08

Dělám to stejně. :-) Prostě mám modely, které mají nějakou logickou funkci např. manipuluje s články, s uživateli apod. a je v podstatě jedno, jestli k tomu potřebuje 1 tabulku nebo 10. Počet tabulek je věc návrhu databáze a jeden z hlavních účelů modelu je právě tohle zpracovat do logických funkcí, které poskytne další vrstvě, pro snazší manipulaci, aby se právě ta nemusela ptát 10 modelů. To, jaké funkce má pak poskytovat další vrstvě, je zase otázka návrhu aplikace. ;)

Editováno 9.7.2015 21:10
 
Odpovědět
9.7.2015 21:08
Avatar
Jan Suchánek:10.7.2015 11:10

A co si postavit fasádu? A používáte události i mimo formuláře?

 
Odpovědět
10.7.2015 11:10
Avatar
Jan Suchánek:10.7.2015 11:21

Byl překročen časový limit na editaci zprávy nebo na ni nemáš oprávnění. Mimo formulář je fakt cool :).

 
Odpovědět
10.7.2015 11:21
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Jan Suchánek
Jindřich Máca:10.7.2015 11:22

Samozřejmě, pokud to chceme mít hezky rozdělené a podle OOP, můžeme použít návrhový vzor fasády viz. http://www.itnetwork.cz/…avrhovy-vzor. Ale ta myšlenka, že by měl model zpracovat databázi do logického rozhraní, které poskytne další vrstvě, tady zůstane zachována. :)

A s těmi událostmi se přiznám, že nevím jak to myslíš. :D

 
Odpovědět
10.7.2015 11:22
Avatar
Jan Suchánek:10.7.2015 13:30

Myslel jsem https://filip-prochazka.com/…te-framework, samozřejmě není pro začátečníky ale mohlo by se při vývoji fakt hodně hodit, minimálně je nepoužívat jen u formulářů.

 
Odpovědět
10.7.2015 13:30
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Jan Suchánek
Jindřich Máca:10.7.2015 13:49

Na to taky časem dojde, až se to bude někde hodit. ;-)

 
Odpovědět
10.7.2015 13:49
Avatar
Jan Suchánek:10.7.2015 16:11

Budeš dělat i vlastní komponentu? Já mam rozpracovanej celkem pěknej vlastní data grid kterej chci mít trošku jinačí a možná i odlehčenější než jsou na foru nette, až bude připravenej dám ho na git, bude zájem o code review, tzv. odprasení :)?

Hlavně ho chci mít nezávislej na modelu, mít možnost používat jakoukoliv knihovnu Doctrine, NDBT, NetteDB query apod.

Podpora bude i inline editace a Ajaxu.

 
Odpovědět
10.7.2015 16:11
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Jan Suchánek
Jindřich Máca:10.7.2015 16:49

Na vlastní komponenty taky určitě dojde. ;-) Obecně je pro tenhle seriál v plánu poměrně dost dílů. :-)

 
Odpovědět
10.7.2015 16:49
Avatar
Honza67
Člen
Avatar
Honza67:13.7.2015 10:27

Dotazy v ArticleManager fungují i když zakomentuju use Nette\Database\Ta­ble\IRow a
use Nette\Database\Ta­ble\Selection . Proč to tak je ? díky

 
Odpovědět
13.7.2015 10:27
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Honza67
Jindřich Máca:13.7.2015 12:15

To je dobrá otázka. :-) Vyplývá to částečně z toho, že PHP je dynamicky typovaný jazyk. Já tam tyhle use mám, jenom proto, že je uvádím v komentářích a moje IDE (PhpStrorm) je tam pak automaticky přidá, kvůli napovídání, typové kontrole atd.

Důležité je, že v kódu, jako takovém, nikde použity nejsou a právě díky tomu a dynamickému typování to bude fungovat i když je tam explicitně neuvedu. ;-)

 
Odpovědět
13.7.2015 12:15
Avatar
Honza67
Člen
Avatar
Honza67:13.7.2015 14:18

Děkuji za odpověď, a chtěl jsem tě ještě poprosit jestli bys nemohl (pro všechny začínající v nette) ,pokud v kódech dalších dílů použiješ nějakou anotaci, která není jen komentářem, alespoň stručně objasnit co a jak dělá. Myslím si, že nám to pak určitě zkrátí dobu učení když nebudeme muset hledat co je vlastně jen komentář a co je důležitá součást kódu, bez které se např. nějaká metoda vůbec neprovede..Vypadá to, že do tohodle dílu tam naštěstí žádná taková anotace není. Snad se nepletu :-).

 
Odpovědět
13.7.2015 14:18
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Honza67
Jindřich Máca:13.7.2015 14:30

V podstatě nejpoužívanější důležitá anotace v Nette je @inject a ta zde doposud použita nebyla. :-) Každopádně až jí, či nějakou jinou použiju, určitě k tomu napíšu poznámku, minimálně v článku pod kódem. Ostatně tak to dělám vždy, ke všemu důležitému nebo zajímavému, to se neboj. ;-)

Jinak obecně k mazání komentářů přeci není žádný důvod a pokud Ti něco nefunguje, můžeš si vždy stáhnout originální kód v archivu pod článkem nebo se zeptat zde v komentářích. ;-)

Editováno 13.7.2015 14:32
 
Odpovědět
13.7.2015 14:30
Avatar
Honza67
Člen
Avatar
Honza67:13.7.2015 14:48

Dobře. Děkuju a těším se(a určitě ne jen já) na dlouhé pokračování seriálu..:-)

 
Odpovědět
13.7.2015 14:48
Avatar
apincik
Člen
Avatar
Odpovídá na Samik11
apincik:15.7.2015 12:21

Tiež som spájal modely logicky niekedy ale pri väčšom projekte to je hnus, oveľa lepšie je mať model pre každú tabuľku :)

 
Odpovědět
15.7.2015 12:21
Avatar
apincik
Člen
Avatar
apincik:15.7.2015 12:28

Ešte k tomu modelu, v práci som sa dostal k pomerne čistému riešeniu, v base class modelu sa využívala __call metóda a na základe toho sa volali ostatné metódy, názov tabuľky atď sa doplnili, nemusíš v každej odvodenej triede manager, article .. písať getManager, getArticle. Pri pár volaniach to nespomalí kód a ušetríš si aj písanie.

GetArticle s parametrom by som konvečne nazval getArticleByXXX :) A getArticles, niekto bude chcieť ASC zoradenie tak si bude musieť prepísať tú metódu, moc znovupoužiteľné mi to nepríde :) zas volať order na objekte v presenteri tiež nieje bloody clear ale to už je na každom :)

 
Odpovědět
15.7.2015 12:28
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na apincik
Jindřich Máca:15.7.2015 13:36

Ano, metoda by se měla spíše getArticleBy* a getArticles by v rámci znovupoužitelnosti měli mít na výběr ve způsobu řazení. I když jsou to detaily, tak budiž, pak to opravím. :-) A samozřejmě díky za připomínky. ;-)

Co se týče použití metody __call, ano je to způsob řešení, ale jelikož je tohle tutorial spíše pro začátečníky, radši bych se držel standardního jednoduchého způsobu a tyhle vychytávky bych si nechal třeba na později. ;-)

 
Odpovědět
15.7.2015 13:36
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Jindřich Máca
Jindřich Máca:20.7.2015 1:23

Tak jsem o tom ještě přemýšlel a nakonec to nechám tak, jak to je, s tím, že to důležité je uvedeno zde v komentářích. ;-)

Věc se má asi takhle, metoda getArticles je zde pouze na ukázku a nikde se znovu používat nebude a přejmenování getArticle na getArticleBy* je pouze kosmetický detail, který lze napravit v dobrém IDE do pár sekund. Na druhou stranu, já bych to musel měnit nejen zde, ale i ve všech následujících článcích s tím, že pokud už to má někdo naprogramované popř. stažené, tak mu to přestane fungovat jen kvůli přejmenování metody a on bude muset pracně dohledávat proč...

Tímto se tedy omlouvám a děkuji za pochopení! :-)

 
Odpovědět
20.7.2015 1:23
Avatar
pepapavlik
Člen
Avatar
pepapavlik:20.7.2015 23:09

Ahoj,

mám jen takovou menší otázečku.

v článku se píše:

" Nám zde bude stačit vytvořit si novou databázi, kterou použijeme pro náš projekt, a v ní spustíme upravený SQL skript, který opět naleznete v archivu pod názvem create_script.sql. Jeho obsah je následující: "

(... OBSAH SKRIPTU...)

dále je pak

"Ten nám vytvoří a naplní tabulku s články, kterou budeme příště potřebovat. A nakonec nastavíme v Nette přístup do naší databáze."

A mě jen zajímá, jak tedy ten skript spustit, aby se vytvořily ty tabulky? Možná je to již někde napsáno, a já to nějako přehlédl...

 
Odpovědět
20.7.2015 23:09
Avatar
Odpovídá na pepapavlik
Martin Konečný (pavelco1998):20.7.2015 23:12

Ahoj,

ve článku je uvedeno, že se script nachází v souboru 'create_script.sql' v přiloženém archivu.
Mělo by v tom případě stačit ten soubor nahrát třeba pomocí adminera nebo phpmyadmin :) (tzv. import)

Odpovědět
20.7.2015 23:12
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
pepapavlik
Člen
Avatar
Odpovídá na Martin Konečný (pavelco1998)
pepapavlik:21.7.2015 10:16

Díky, zkusím nějako nahrát.

 
Odpovědět
21.7.2015 10:16
Avatar
pepapavlik
Člen
Avatar
Odpovídá na pepapavlik
pepapavlik:21.7.2015 10:30

Jo dobrý, už vím.

Musíme použít například adminer, nacházející se v Nette, přesunout se na požadovanou databázi, kde potom v levém políčku zadáme import, vyhledáme pak náležitý soubor se skriptem a zpracujeme.

Paráda.

 
Odpovědět
21.7.2015 10:30
Avatar
filipfr
Člen
Avatar
filipfr:29.8.2015 14:09

Vysvětlíš nějak to routování? Pro mě je to blackbox, kterej jen kopíruju.

 
Odpovědět
29.8.2015 14:09
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na filipfr
Jindřich Máca:6.9.2015 15:18

Ahoj, routování samo o sobě je trochu složitější problém a netýká se jenom Nette. :-)

V zkratce a konkrétně pro Nette. Potřebuješ nějak říct svojí aplikaci, pod jakou URL má hledat nějakou metodu presenteru a naopak, v jakou URL vyústí daná metoda. Nette proto pak má nějakou vlastní syntaktickou strukturu, ve které se to právě zapisuje do té RouterFactory. A pokud se chceš o této syntaxi a obecně o routování dozvědět více, doporučuji oficiální Nette manuál https://doc.nette.org/cs/2.3/routing, protože tady Ti to v jednom komentáři nevysvětlím... :-)

 
Odpovědět
6.9.2015 15:18
Avatar
Neaktivní uživatel:14.9.2015 20:11

Zdravím!
Po nějaké době si zase osvěžuji Nette a přijde mi až trapné, že jsem pohořel hned na začátku. :D Laděnka mi vyplivla chybu "Service 'application.1': Service of type App\CoreModule\Mo­del\ArticleMa­nager needed by App\CoreModule\Pre­senters\Article­Presenter::__con­struct() not found. Did you register it in configuration file?", ale ať se dívám jak chci, ta služba je v konfiguráku zaregistrována. Nevíte, čím by to mohlo být?

Předem díky za reakce. :)

Odpovědět
14.9.2015 20:11
Neaktivní uživatelský účet
Avatar
Odpovídá na Neaktivní uživatel
Martin Konečný (pavelco1998):14.9.2015 20:27

Jak to v tom konfigu máš napsaný? Zkusil jsi promazat cache?

Odpovědět
14.9.2015 20:27
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Neaktivní uživatel:14.9.2015 20:29

Cache jsem promazal, konfigurák je jednoduchý:

# Konfigurační soubor pro CoreModule.

parameters:

# Nastavení služeb dále přístupných pomocí DI v rámci celé aplikace.
services:
        - App\CoreModule\Model\ArticleManager

# Vložení konfiguračních souborů z jednotlivých modulů.
includes:
    - ../CoreModule/config/config.neon
Odpovědět
14.9.2015 20:29
Neaktivní uživatelský účet
Avatar
Odpovídá na Neaktivní uživatel
Martin Konečný (pavelco1998):14.9.2015 20:36

hmm, tak to nevim, nic mě nenapadá. Jsi si jistý, že to máš ve správným config souboru a že se ten soubor parsuje?
Tzn. jestli v bootstrapu máš něco jako

$configurator->addConfig(__DIR__ . '/config/tvuj_config_soubor.neon');
Odpovědět
14.9.2015 20:36
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Neaktivní uživatel:14.9.2015 20:51

Mno, řídil jsem se podle seriálu, kde o tomhle nic nepsali. Ale samozřejmě mě to napadlo hned jako první řešení. Nette mi ale hlásí chybovou hlášku, která typuju věstí duplikát. Tedy že se konfigurák parsuje. Tudíž jsem tu lajnu smazal.

Odpovědět
14.9.2015 20:51
Neaktivní uživatelský účet
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Neaktivní uživatel
Jindřich Máca:14.9.2015 22:14

Ahoj, za prvé neon je citlivý na taby a mezery a z tvého kódu mám pocit, že to tam máš jinak odsazené a za druhé bych rád viděl i kód ArticleManager, prosím. :-)

 
Odpovědět
14.9.2015 22:14
Avatar
Odpovídá na Jindřich Máca
Neaktivní uživatel:15.9.2015 16:44

Ano, byla tam nějaká muchlanice tab/mezera. Zkoušel jsem tam dát i vážně blbou chybu, ale laděnka nic neukazuje. Řekl bych, že se ten soubor skutečně neparsuje. Když dám ale do konfiguráku podobný řádek:

$configurator->addConfig(__DIR__ . '/CoreModule/config/core_config.neon');

, hází mi to před to kdo ví proč nějaké další blafy (CoreModule/con­fig/../). Ve výsledku mi to tudíž hodí chybu "File 'C:\xampp\htdoc­s\cms\app/Core­Module/config/­../CoreModule/con­fig/config.ne­on' is missing or is not readable.".

ArticleManager by měl být v pořádku, ale pro jistotu ti ho sem hodím: http://pastebin.com/w7B3Vqyy

Odpovědět
15.9.2015 16:44
Neaktivní uživatelský účet
Avatar
Milan Gallas
Redaktor
Avatar
Milan Gallas:12.10.2015 18:32

Co se týče databáze, tak ta mi vždy vrátí objekt activeRecodrs, nebo se dá nějak nastavit, aby mi to vrátilo jenom pole s hodnotay, abych je mohl převést do formátu JSON a vypsat je v šabloně pomocí frameworku angularJS?

 
Odpovědět
12.10.2015 18:32
Avatar
Odpovídá na Milan Gallas
Martin Konečný (pavelco1998):12.10.2015 18:47

Mělo by jít použít metodu toArray(), kterou třída ActiveRow má

Odpovědět
12.10.2015 18:47
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Milan Gallas
Redaktor
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Milan Gallas:12.10.2015 19:36

Call to undefined method Nette\Database\Ta­ble\Selection::to­Array()

 
Odpovědět
12.10.2015 19:36
Avatar
Odpovídá na Milan Gallas
Martin Konečný (pavelco1998):12.10.2015 19:54

https://api.nette.org/…lection.html

můžeš zkusit např. fetchAssoc() nebo fetchPairs()

Odpovědět
12.10.2015 19:54
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Odpovídá na Jindřich Máca
Dominik Gavrecký:14.12.2015 20:24

Nie je lepšie si vytvoriť BaseModel so základnými dotazmi na databázu ktorú registruješ ako službu a potom ho pridelíš ku každému Modelu a injectneš v Presenteri ?

Odpovědět
14.12.2015 20:24
Hlupák nie je ten kto niečo nevie, hlupákom sa stávaš v momente keď sa na to bojíš opýtať.
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Dominik Gavrecký
Jindřich Máca:15.12.2015 0:08

Samozřejmě, pokud chceš vybavit model nějakými základními dotazy a dále si tak ulehčit práci, tak klidně můžeš. :-)

 
Odpovědět
15.12.2015 0:08
Avatar
Odpovídá na Jindřich Máca
Dominik Gavrecký:15.12.2015 7:20

Určite by si to mohol v ďalšom článku ľudom ukázať predsa je to poriadny uľahčovak k práci.

Odpovědět
15.12.2015 7:20
Hlupák nie je ten kto niečo nevie, hlupákom sa stávaš v momente keď sa na to bojíš opýtať.
Avatar
danhosek
Člen
Avatar
danhosek:20.3.2016 10:54

Ahoj, chci se zeptat, zda mám správně nastavení na databázi:
parameters:
dbname: XXXXXX # XXXXX=název databáze

# Konfigurace databázové služby dále přístupné pomocí DI v rámci celé aplikace.
database:
dsn: 'mysql:host=HHHHHHHHH;­dbname=%dbname%' # HHHH=adresa serveru
user: UUUUU # UUUU=uživatel
password: PPPPP # PPPPP=heslo
options:
lazy: yes

po nahrání na hosting mám chybu 500 Server error. Nevím, jaký druh chyb mám hledat.

Editováno 20.3.2016 10:56
 
Odpovědět
20.3.2016 10:54
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na danhosek
Jindřich Máca:20.3.2016 12:28

Ahoj, pokud Ti laděnka (Tracy) z nějakého důvodu nevypisuje detaily chyby a vidíš jenom error 500, podívej se do logu (složka log/), kde by jsi je měl nalézt. Obecně ta chyba vůbec nemusí souviset s nastavením databáze. :-)

 
Odpovědět
20.3.2016 12:28
Avatar
Odpovídá na danhosek
Dominik Gavrecký:20.3.2016 12:41

Tak isto je dobré zapnúť si debug mode ktorý slúži priamo na takéto situácie pri vývoji aplikácii.

Odpovědět
20.3.2016 12:41
Hlupák nie je ten kto niečo nevie, hlupákom sa stávaš v momente keď sa na to bojíš opýtať.
Avatar
danhosek
Člen
Avatar
danhosek:20.3.2016 12:45

nevím, jak mám povolit laděnku na hostingu.
myslím, že mám špatně nastavený v config.local.neon připojení k Db. Doplněné údaje jsem kontroloval několikrát a je v pořádku nejsem si jistý řádkou dsn: (viz. výše). není rozdíl pro nastavení pro localhost a webhosting?

[2016-03-20 00-47-49] Nette\Database\Con­nectionExcepti­on: SQLSTATE[HY000] [2003] Can't connect to MySQL server on '127.0.0.1' (110) in /data/web/vir­tuals/101955/vir­tual/www/vendor/net­te/database/src/Da­tabase/DriverEx­ception.php:25 caused by PDOException: SQLSTATE[HY000] [2003] Can't connect to MySQL server on '127.0.0.1' (110) in /data/web/vir­tuals/101955/vir­tual/www/vendor/net­te/database/src/Da­tabase/Connec­tion.php:70 @ http://www.danielhosek.cz/ @@ exception-2016-03-20-00-47-49-f206a44f57ac2­18909d8196a214d4c72­.html
[2016-03-20 00-50-17] Nette\Database\Con­nectionExcepti­on: SQLSTATE[HY000] [2003] Can't connect to MySQL server on '127.0.0.1' (110) in /data/web/vir­tuals/101955/vir­tual/www/vendor/net­te/database/src/Da­tabase/DriverEx­ception.php:25 caused by PDOException: SQLSTATE[HY000] [2003] Can't connect to MySQL server on '127.0.0.1' (110) in /data/web/vir­tuals/101955/vir­tual/www/vendor/net­te/database/src/Da­tabase/Connec­tion.php:70 @ http://www.danielhosek.cz/ @@ exception-2016-03-20-00-47-49-f206a44f57ac2­18909d8196a214d4c72­.html
[2016-03-20 03-15-23] Nette\Database\Con­nectionExcepti­on: SQLSTATE[HY000] [2003] Can't connect to MySQL server on '127.0.0.1' (110) in /data/web/vir­tuals/101955/vir­tual/www/vendor/net­te/database/src/Da­tabase/DriverEx­ception.php:25 caused by PDOException: SQLSTATE[HY000] [2003] Can't connect to MySQL server on '127.0.0.1' (110) in /data/web/vir­tuals/101955/vir­tual/www/vendor/net­te/database/src/Da­tabase/Connec­tion.php:70 @ http://danielhosek.cz/ @@ exception-2016-03-20-00-47-49-f206a44f57ac2­18909d8196a214d4c72­.html
[2016-03-20 07-23-20] Nette\Database\Con­nectionExcepti­on: SQLSTATE[HY000] [2003] Can't connect to MySQL server on '127.0.0.1' (110) in /data/web/vir­tuals/101955/vir­tual/www/vendor/net­te/database/src/Da­tabase/DriverEx­ception.php:25 caused by PDOException: SQLSTATE[HY000] [2003] Can't connect to MySQL server on '127.0.0.1' (110) in /data/web/vir­tuals/101955/vir­tual/www/vendor/net­te/database/src/Da­tabase/Connec­tion.php:70 @ http://danielhosek.cz/ @@ exception-2016-03-20-00-47-49-f206a44f57ac2­18909d8196a214d4c72­.html
[2016-03-20 10-38-16] Nette\Database\Con­nectionExcepti­on: SQLSTATE[HY000] [2003] Can't connect to MySQL server on '127.0.0.1' (110) in /data/web/vir­tuals/101955/vir­tual/www/vendor/net­te/database/src/Da­tabase/DriverEx­ception.php:25 caused by PDOException: SQLSTATE[HY000] [2003] Can't connect to MySQL server on '127.0.0.1' (110) in /data/web/vir­tuals/101955/vir­tual/www/vendor/net­te/database/src/Da­tabase/Connec­tion.php:70 @ http://www.danielhosek.cz/ @@ exception-2016-03-20-00-47-49-f206a44f57ac2­18909d8196a214d4c72­.html
[2016-03-20 11-05-57] Nette\Database\Con­nectionExcepti­on: SQLSTATE[HY000] [2003] Can't connect to MySQL server on '127.0.0.1' (110) in /data/web/vir­tuals/101955/vir­tual/www/vendor/net­te/database/src/Da­tabase/DriverEx­ception.php:25 caused by PDOException: SQLSTATE[HY000] [2003] Can't connect to MySQL server on '127.0.0.1' (110) in /data/web/vir­tuals/101955/vir­tual/www/vendor/net­te/database/src/Da­tabase/Connec­tion.php:70 @ http://www.danielhosek.cz/ @@ exception-2016-03-20-00-47-49-f206a44f57ac2­18909d8196a214d4c72­.html
[2016-03-20 11-06-50] Nette\Database\Con­nectionExcepti­on: SQLSTATE[HY000] [2003] Can't connect to MySQL server on '127.0.0.1' (110) in /data/web/vir­tuals/101955/vir­tual/www/vendor/net­te/database/src/Da­tabase/DriverEx­ception.php:25 caused by PDOException: SQLSTATE[HY000] [2003] Can't connect to MySQL server on '127.0.0.1' (110) in /data/web/vir­tuals/101955/vir­tual/www/vendor/net­te/database/src/Da­tabase/Connec­tion.php:70 @ http://www.danielhosek.cz/ @@ exception-2016-03-20-00-47-49-f206a44f57ac2­18909d8196a214d4c72­.html

 
Odpovědět
20.3.2016 12:45
Avatar
Odpovídá na danhosek
Dominik Gavrecký:20.3.2016 13:01

Ladenku povolíš v súbore boostrap.php

$configurator->setDebugMode();

Kde hodnota funkcie setDebugMode() obsahuje Boolean alebo string s tvojou IP. Napríklad:

$configurator->setDebugMode(TRUE);

Môj súbor config.local.neon vyzerá takto:

parameters:

database:
        dsn: 'mysql:host=mysql51.websupport.sk;port=3309;dbname=devgn'
        user: 'xxx'
        password: 'xxx'
        options:
                lazy: yes
Odpovědět
20.3.2016 13:01
Hlupák nie je ten kto niečo nevie, hlupákom sa stávaš v momente keď sa na to bojíš opýtať.
Avatar
danhosek
Člen
Avatar
danhosek:20.3.2016 13:58

config.local.neon obsahuje:
parameters:

database:
dsn: 'mysql:host=wm87­.wedos.net;por­t=3309;dbname=d101955_h­osek'
user: 'xxxx'
password: 'xxxx'
options:
lazy: yes

Laděnku jsem aktivoval (21chyb)-viz. www.danielhosek.cz
nelze se připojit k db

 
Odpovědět
20.3.2016 13:58
Avatar
Odpovídá na danhosek
Dominik Gavrecký:20.3.2016 20:26

Nie som si istý tým portom. Nepripájaš na databázu wedosu bez portu ?

Odpovědět
20.3.2016 20:26
Hlupák nie je ten kto niečo nevie, hlupákom sa stávaš v momente keď sa na to bojíš opýtať.
Avatar
danhosek
Člen
Avatar
Odpovídá na Dominik Gavrecký
danhosek:20.3.2016 20:35

ten port zlobil. děkuji za radu...

 
Odpovědět
20.3.2016 20:35
Avatar
Odpovědět
20.3.2016 21:14
Hlupák nie je ten kto niečo nevie, hlupákom sa stávaš v momente keď sa na to bojíš opýtať.
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na danhosek
Jindřich Máca:20.3.2016 21:25

Koukám, že Dominik Gavrecký to již bez problémů vyřešil. :-) Já bych k tomu jenom doplnil, že povolovat laděnku na produkčním serveru je z bezpečnostního hlediska velice špatný nápad. Maximálně bych ji tam povolil pro danou IP adresu, ale to vyžaduje veřejnou IP adresu z Tvé strany...

 
Odpovědět
20.3.2016 21:25
Avatar
danhosek
Člen
Avatar
danhosek:24.3.2016 23:19

app/router/Rou­terFactory.php
public static function createRouter()
{
$router = new RouteList();
$router[] = new Route('[<url>]', 'Core:Article:de­fault');
return $router;
toto je dúležité jen pro úvodní článek ne? pokud dělám sekci reference, do routerfactory.php toto routování nezadávám, Je to tak správně? nebo jsem něco přehlédl?

 
Odpovědět
24.3.2016 23:19
Avatar
Odpovídá na danhosek
Dominik Gavrecký:24.3.2016 23:24

Áno presne ako hovoríš, ak vytvoríš nový presenter s názvom Reference tak url sa zachová www.tvojweb.sk/reference. Ak by ťa to zaujímalo trošku viac detailnejšie tak https://doc.nette.org/cs/2.3/routing

Odpovědět
24.3.2016 23:24
Hlupák nie je ten kto niečo nevie, hlupákom sa stávaš v momente keď sa na to bojíš opýtať.
Avatar
danhosek
Člen
Avatar
danhosek:24.3.2016 23:53

Mám stále problém vytvořit podstránku reference. Dělám to stejně jako články (article) a stále se mit o nedaří. momentálně pod URL: /reference se mi to zřejmě zacyklí :

Stránka www.danielhosek.cz nefunguje

Web www.danielhosek.cz vás přesměroval příliš mnohokrát.
ERR_TOO_MANY_RE­DIRECTS

u RS v OOP PHP to nebyl problém takto upravit: nahradit slovem article -> reference.
založil jsem příslušnou tabulku v DB ale nejsem si jistý, zda je problém v přesměrování, nebo jinde. DĚKUJI.

 
Odpovědět
24.3.2016 23:53
Avatar
Odpovídá na danhosek
Dominik Gavrecký:24.3.2016 23:57

Posli sem tvoju routu a ReferencePresenter

Editováno 24.3.2016 23:59
Odpovědět
24.3.2016 23:57
Hlupák nie je ten kto niečo nevie, hlupákom sa stávaš v momente keď sa na to bojíš opýtať.
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
danhosek
Člen
Avatar
Odpovídá na Dominik Gavrecký
danhosek:25.3.2016 0:33

Do RouterFactory jsem doplnil
$router[] = new Route('[<acti­on>/][<url>]', array(
'presenter' => 'Core:Reference',
'action' => array(
Route::VALUE => 'default',
Route::FILTER_TABLE => array(
// řetězec v URL => akce presenteru
'reference' => 'list',
'editor' => 'editor',
'odstranit' => 'remove'
),
Route::FILTER_STRICT => true
),
'url' => null,
));
$router[] = new Route('[<url>]', 'Core:Referen­ce:default');
return $router;

a ReferencePresenter:
<?php

/*
Anotace

*/

namespace App\CoreModule\Pre­senters;

use App\CoreModule\Mo­del\Reference­Manager;
use Nette\Applica­tion\BadReques­tException;
use Nette\Applica­tion\UI\Form;
use Nette\Database\U­niqueConstrain­tViolationExcep­tion;
use Nette\Utils\A­rrayHash;

/**
* Zpracovává práci s články.
* @package App\CoreModule\Pre­senters
*/
class ReferencePresenter extends BaseCorePresenter
{
/** @var ArticleManager Instance třídy modelu pro práci s články. */
protected $referenceManager;

/**
* Konstruktor s injektovaným modelem pro práci s články.
* @param ArticleManager $articleManager automaticky injektovaná třída modelu pro práci s články
*/
public function __construct(Re­ferenceManager $referenceManager)
{
parent::__con­struct();
$this->referenceManager = $referenceManager;
}

/** Načte a vykreslí článek článek do šablony podle jeho URL.
* @param string $url URL článku
* @throws BadRequestException Jestliže článek s danou URL nebyl nalezen.
*/

/** Vykreslí seznam článků do šablony. */
public function renderList()
{
$this->template->reference = $this->referenceManager->getReferences();
}

/**
* Odstraní článek.
* @param string $url
*/
public function actionRemove($url)
{
$this->referenceManager->removeReeren­ce($url);
$this->flashMessage('Člá­nek byl úspěšně odstraněn.');
$this->redirect(':Co­re:Reference:lis­t');
}

/**
* Vykresluje editaci článku podle jeho URL.
* @param string $url URL adresa článku, který editujeme, pokud není zadána, vytvoří se nový
*/
public function actionEditor($url)
{
// Pokud byla zadána URL, pokusí se článek načíst a předat jeho hodnoty do editačního formuláře, jinak vypíše chybovou hlášku.
if ($url) ($reference = $this->referenceManager->getReference($ur­l)) ? $this['editorForm']->setDefaults($re­ference) : $this->flashMessage('Re­ference nebyla nalezena.');
}

/**
* Vrátí formulář pro editor článků.
* @return Form formulář pro editor článků
*/
protected function createComponen­tEditorForm()
{
$form = new Form;
$form->addHidden('re­ference_id');
$form->addText('title', 'Titulek')->setRequired();
$form->addText('url', 'URL')->setRequired();
$form->addText('des­cription', 'Popisek')->setRequired();
$form->addTextArea('con­tent', 'Obsah');
$form->addSubmit('sub­mit', 'Uložit referenci');
$form->onSuccess[] = [$this, 'editorFormSuc­ceeded'];
return $form;
}

/**
* Funkce se vykonaná při úspěsném odeslání formuláře; zpracuje hodnoty formuláře.
* @param Form $form formulář editoru
* @param ArrayHash $values odeslané hodnoty formuláře
*/
public function editorFormSuc­ceeded($form, $values)
{
try {
$this->referenceManager->saveReference($va­lues);
$this->flashMessage('Re­ference byla úspěšně uložena.');
$this->redirect(':Co­re:Reference:', $values->url);
} catch (UniqueConstra­intViolationEx­ception $ex) {
$this->flashMessage('Re­ference s touto URL adresou již existuje.');
}
}
}

 
Odpovědět
25.3.2016 0:33
Avatar
danhosek
Člen
Avatar
danhosek:25.3.2016 16:52

momentálně mám na calý web error 500 a v logu:
[2016-03-25 16-40-35] Nette\Invalid­StateException: Resource 'Core:Reference' does not exist. in /data/web/vir­tuals/101955/vir­tual/www/vendor/net­te/security/src/Se­curity/Permis­sion.php:300 @ http://www.danielhosek.cz/ @@ exception-2016-03-25-16-40-24-f41e44703c313­accfae587ddfbd951­e1.html

i když je v routeFactory přidaný stějně jako'Core:Article

 
Odpovědět
25.3.2016 16:52
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na danhosek
Jindřich Máca:25.3.2016 16:55

Ahoj, to je chyba způsobená tím, že jsi sice do routování přidal nový zdroj, ale ve statickém ACL jsi mu nenastavil žádná práva, potažmo jsi ho tam vůbec neuvedl. V našem případě zápisu ověřování práv totiž aplikace vyžaduje, aby každý zdroj byl registrován v rámci ACL, jinak právě začne vyhazovat tuto výjimku. :)

 
Odpovědět
25.3.2016 16:55
Avatar
danhosek
Člen
Avatar
Odpovídá na Jindřich Máca
danhosek:25.3.2016 17:38

Do confin.neon jsem reference přidal.
Nebo je třeba ACL oprávnění přidat ještě jinam?

#  _____ _______         _                      _
# |_   _|__   __|       | |                    | |
#   | |    | |_ __   ___| |___      _____  _ __| | __  ___ ____
#   | |    | | '_ \ / _ \ __\ \ /\ / / _ \| '__| |/ / / __|_  /
#  _| |_   | | | | |  __/ |_ \ V  V / (_) | |  |   < | (__ / /
# |_____|  |_|_| |_|\___|\__| \_/\_/ \___/|_|  |_|\_(_)___/___|
#                                _
#              ___ ___ ___ _____|_|_ _ _____
#             | . |  _| -_|     | | | |     |  LICENCE
#             |  _|_| |___|_|_|_|_|___|_|_|_|
#             |_|
#
# IT ZPRAVODAJSTVÍ  <>  PROGRAMOVÁNÍ  <>  HW A SW  <>  KOMUNITA
#
# Tento zdrojový kód je součástí výukových seriálů na
# IT sociální síti WWW.ITNETWORK.CZ
#
# Kód spadá pod licenci prémiového obsahu a vznikl díky podpoře
# našich členů. Je určen pouze pro osobní užití a nesmí být šířen.
#
# Konfigurační soubor pro CoreModule.

parameters:
        # Presentery.
        administration: Core:Administration
        article: Core:Article
        reference: Core:Reference
        contact: Core:Contact

# Nastavení vlastních služeb dále přístupných pomocí DI v rámci CoreModule.
services:
        security.authorizator: # Nastavení zdrojů a pravidel přístupu k nim v rámci CoreModule pomocí statického ACL.
                setup:
                        - addResource(%administration%)
                        - addResource(%article%)
                        - addResource(%contact%)
                        - App\CoreModule\Model\ReferenceManager
                        - allow(%guest%, %administration%, 'login')
                        - allow(%guest%, %administration%, 'register')
                        - allow(%guest%, %article%, 'default')
                        - allow(%guest%, %article%, 'list')
                        - allow(%guest%, %reference%, 'default')
                        - allow(%guest%, %reference%, 'list')
                        - allow(%guest%, %contact%)
                        - allow(%member%, %administration%, 'default')
                        - allow(%member%, %administration%, 'logout')


        # Nastavení dalších služeb v rámci CoreModule dále přístupných pomocí DI.
        - App\CoreModule\Model\ArticleManager
        - App\CoreModule\Model\ReferenceManager
 
Odpovědět
25.3.2016 17:38
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na danhosek
Jindřich Máca:25.3.2016 18:49

V setupu služby authorizator jsi na něj nepoužil metodu addResource() a tím pádem není zaregistrovaný jako zdroj. Ta definice pod parametry je jenom pomocná zkratka pro Tebe. ;-)

 
Odpovědět
25.3.2016 18:49
Avatar
danhosek
Člen
Avatar
Odpovídá na Jindřich Máca
danhosek:25.3.2016 19:29

našel jsem tu chybu před chvílí, když jsem to upravoval celé znovu a opatrněji. ted mi web jede, ale /reference/ stále nefunguje. Přesměrováno na /chyba.
v @layout.latte:
<li><a n:href=":Core:Ar­ticle:list">Sez­nam článků</li>
<li><a n:href=":Core:Re­ference:list">Re­ference</li>
HTML:

<li>Seznam článků</li>
<li>Reference</li>

Jak je tohle možné?

 
Odpovědět
25.3.2016 19:29
Avatar
danhosek
Člen
Avatar
Odpovídá na danhosek
danhosek:25.3.2016 19:33
<li><a href="/seznam-clanku/">Seznam článků</a></li>
<li><a href="#">Reference</a></li>
 
Odpovědět
25.3.2016 19:33
Avatar
danhosek
Člen
Avatar
Odpovídá na Jindřich Máca
danhosek:26.3.2016 0:39

pokud mi to nevytvořilo ani odkaz v menu, nefunguje mi routování v aplikaci že? zkontroloval jsem app/ComeModule/con­fig/config.ne­on i app/router/ RouterFactory.php a vše vypadá, že je vporádku. Ale není...

 
Odpovědět
26.3.2016 0:39
Avatar
danhosek
Člen
Avatar
danhosek:26.3.2016 10:16

asi jsem už našel, kde mám chybu, ale nevím jak to upravit.
v RouteFactory mám routy se stejným předpisem a splní ho oboje stejně, tak to načte tu první.
Jak mám upravit routy, tak aby to odlišilo akce? místo:
$router[] = new Route('[<acti­on>/][<url>]', array(
dám:
$router[] = new Route('[referen­ce/][<url>]', array(
a to samé u článků?
Děkuji.

public static function createRouter()
        {
                $router = new RouteList();
                $router[] = new Route('kontakt/', 'Core:Contact:default');
                $router[] = new Route('<action>/', array(
                        'presenter' => 'Core:Administration',
                        'action' => array(
                                // řetězec v URL => akce presenteru
                                Route::FILTER_TABLE => array(
                                        'administrace' => 'default',
                                        'prihlaseni' => 'login',
                                        'odhlasit' => 'logout',
                                        'registrace' => 'register'
                                ),
                                Route::FILTER_STRICT => true
                        )
                ));
        $router[] = new Route('[<action>/][<url>]', array(
            'presenter' => 'Core:Article',
            'action' => array(
                Route::VALUE => 'default',
                Route::FILTER_TABLE => array(
                    // řetězec v URL => akce presenteru
                    'seznam-clanku' => 'list',
                    'editor' => 'editor',
                    'odstranit' => 'remove'
                ),
                Route::FILTER_STRICT => true
            ),
            'url' => null,
        ));
        $router[] = new Route('[<url>]', 'Core:Article:default');


        $router[] = new Route('[<action>/][<url>]', array(
            'presenter' => 'Core:Reference',
            'action' => array(
                Route::VALUE => 'default',
                Route::FILTER_TABLE => array(
                    // řetězec v URL => akce presenteru
                    'reference' => 'list',
                    'editor' => 'editor',
                    'odstranit' => 'remove'
                ),
                Route::FILTER_STRICT => true
            ),
            'url' => null,
        ));
        $router[] = new Route('[<url>]', 'Core:Reference:default');
        return $router;

    }
 
Odpovědět
26.3.2016 10:16
Avatar
danhosek
Člen
Avatar
danhosek:9.10.2016 20:35

Ahoj, mám problém nejspíše s routy v applikaci.
Administrace článků bezchybně funguje.
Úplně stejným způsobem chci udělat administraci referencí.
Udělal jsem stejně presenter, model i šablony, ale mám problém s napsáním routy.
Přidal zdroje i oprávnění.
RouteFactory vypadá takto (VIZ NÍŽE):
po spuštění mi to vytvoří odkazy

<li><a n:href=":Core:Ar­ticle:list">Sez­nam článků</li>
<li><a n:href=":Core:Re­ference:list">Sez­nam referencí</li>
odkazy:
http://localhost/…znam-clanku/
http://localhost/…m-referenci/

po kliknutí na Seznam referencí se mi stránka přesměruje na chybovou stránku s textem stránka nebyla nalezena, na kterou je applikace přesměrována, když je odkazneexistující.

Podle tracy neexistuje url pro seznam referencí

.Myslím si, že problém je v těch routách, ale nevim, jak je mám upravit.
Podle všeho se to přesměruje na výpis článků, kde hledá v databázi stránku výpis referencí.

  • Může to být tím, že prezenter i model je duplikován jen přejmenován a upraven na reference?

I funkce se jmenujou stejně.

Prosím o radu, jak tuto applikaci opravit a zprovoznit

class RouterFactory
{
        /**
         * Vytváří router pro aplikaci.
         * @return RouteList výsledný router pro aplikaci
         */
        public static function createRouter()
        {
                $router = new RouteList();
                $router[] = new Route('kontakt/', 'Core:Contact:default');
                $router[] = new Route('<action>/', array(
                        'presenter' => 'Core:Administration',
                        'action' => array(
                                // řetězec v URL => akce presenteru
                                Route::FILTER_TABLE => array(
                                        'administrace' => 'default',
                                        'prihlaseni' => 'login',
                                        'odhlasit' => 'logout',
                                        'registrace' => 'register'
                                ),
                                Route::FILTER_STRICT => true
                        )
                ));
                $router[] = new Route('[<action>/][<url>]', array(
                        'presenter' => 'Core:Article',
                        'action' => array(
                                Route::VALUE => 'default',
                                Route::FILTER_TABLE => array(
                                        // řetězec v URL => akce presenteru
                                        'seznam-clanku' => 'list',
                                        'editor' => 'editor',
                                        'odstranit' => 'remove'
                                ),
                                Route::FILTER_STRICT => true
                        ),
                        'url' => null,
                ));
                $router[] = new Route('[<url>]', 'Core:Article:default');

        $router[] = new Route('[<action>/][<url>]', array(
            'presenter' => 'Core:Reference',
            'action' => array(
                Route::FILTER_TABLE => array(
                    // řetězec v URL => akce presenteru
                    'seznam-referenci' => 'list',
                    'editor' => 'editor',
                    'odstranit' => 'remove'
                ),
                Route::FILTER_STRICT => true
            ),
            'url' => null,
        ));
        return $router;
    }
}

Děkuji za jakoukoli pomoc, jelikož jsem z toho už zoufalý. Pročítal jsem dokumentace i příklady a známí co mají app v nette routy niak neupravují a aplikace jim běží.

 
Odpovědět
9.10.2016 20:35
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na danhosek
Jindřich Máca:9.10.2016 22:47

Zdravím,

v uvedeném routeru rozhodně vidím chybu, která s největší pravděpodobností způsobuje popsané chování. Jedná se o řádek

$router[] = new Route('[<url>]', 'Core:Article:default');

, který musí rozhodně být až na konci routeru, neboť "spolkne" jakoukoliv URL.

Pro bližší vysvětlení, router funguje tak, že testuje danou URL vůči vzoru a je použita první odpovídající routa v pořadí. Jelikož ale vzor [<url>] odpovídá jakékoliv URL, router se vždy zastaví zde a spustí vyhledávání článku s danou URL. To ale v tomto případě nebyl záměr, čili takový článek neexistuje, a proto nastává již zmíněná chyba.

Z předchozího již logicky vyplývá, že jakákoliv následující routa po tomto vzoru nikdy nemůže být použita. Řešení je tedy přesunout tento nejobecnější vzor na konec routeru.

Doufám, že jsem to dostatečně objasnil, případně očekávám další dotazy nebo doporučuji přečíst komentáře u tohoto článku od začátku, protože zrovna routování se zde již jednou řešilo...

 
Odpovědět
9.10.2016 22:47
Avatar
danhosek
Člen
Avatar
Odpovídá na Jindřich Máca
danhosek:10.10.2016 14:40

Díky moc. Je to logické a hloupé si toho nevšimnout.
Nyní mi nastal problém, stím, že reference nelze editovat, odstraňovat ani vytvářet po kluknutí na odkazy

<h2><a n:href=":Core:Re­ference:editor">No­vá reference</h2>
<a n:href=":Core:Re­ference:editor $reference->url">Editovat
<a n:href=":Core:Re­ference:remove $reference->url">Odstranit referenci

jsem přesměrován na administraci článků.
Odzkoušel jsem, že záleží na pořadí rout v RouterFactory, který momentálně vypadá takto:

public static function createRouter()
        {
                $router = new RouteList();
                $router[] = new Route('kontakt/', 'Core:Contact:default');
                $router[] = new Route('<action>/', array(
                        'presenter' => 'Core:Administration',
                        'action' => array(
                                // řetězec v URL => akce presenteru
                                Route::FILTER_TABLE => array(
                                        'administrace' => 'default',
                                        'prihlaseni' => 'login',
                                        'odhlasit' => 'logout',
                                        'registrace' => 'register'
                                ),
                                Route::FILTER_STRICT => true
                        )
                ));
                $router[] = new Route('[<action>/][<url>]', array(
                        'presenter' => 'Core:Article',
                        'action' => array(
                                Route::VALUE => 'default',
                                Route::FILTER_TABLE => array(
                                        // řetězec v URL => akce presenteru
                                        'seznam-clanku' => 'list',
                                        'editor' => 'editor',
                                        'odstranit' => 'remove'
                                ),
                                Route::FILTER_STRICT => true
                        ),
                        'url' => null,
                ));
        $router[] = new Route('[<action>/][<url>]', array(
            'presenter' => 'Core:Reference',
            'action' => array(
                Route::VALUE => 'default',
                Route::FILTER_TABLE => array(
                    // řetězec v URL => akce presenteru
                    'seznam-referenci' => 'list',
                    'editor' => 'editor',
                    'odstranit' => 'remove'
                ),
                Route::FILTER_STRICT => true
            ),
            'url' => null,
        ));
                $router[] = new Route('[<url>]', 'Core:Reference:default');
        $router[] = new Route('[<url>]', 'Core:Reference:default');
                return $router;
        }

Jak to mám odlišit?
Napadlo mě řešení, že pro article zůstane editor a pro reference např: editor_ref
ale nevím, kde všude to bude potřeba upravit. (routa,funkce v referencepresenter, název šablony v templates/refe­rence)

 
Odpovědět
10.10.2016 14:40
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na danhosek
Jindřich Máca:10.10.2016 17:17

Není zač. :)

V aktuálním kódu routeru máš na konci další chybu:

$router[] = new Route('[<url>]', 'Core:Reference:default');
$router[] = new Route('[<url>]', 'Core:Reference:default');

Tohle je přeci to samé, jedno mělo pravděpodobně být:

$router[] = new Route('[<url>]', 'Core:Article:default');

Pozn.: To je naneštěstí taky špatně, viz. dále.

To ale není ten problém. Hlavní chyba je v tom, uvědomit si, že routování je dvousměrná záležitost. Zase se to pokusím trochu objasnit:

  • V první fázi, při generování stránky, se Ti odkaz :Core:Referen­ce:editor překládá na URL. Předpokládejme, že je to např. http://localhost/…ette/editor/. Zde vše proběhne v pořádku a podle očekávání.
  • V dalším kroku, klikneme na odkaz a router má rozhodnout, co se vykoná podle dané URL. Zde ale nastává onen problém. V návaznosti na můj předchozí komentář bude první shoda v pořadí na následující akci, která se pak také provede:
$router[] = new Route('[<action>/][<url>]', array(
        'presenter' => 'Core:Article',
        'action' => array(
                Route::VALUE => 'default',
                Route::FILTER_TABLE => array(
                        // řetězec v URL => akce presenteru
                        'seznam-clanku' => 'list',
                        'editor' => 'editor',
                        'odstranit' => 'remove'
                ),
                Route::FILTER_STRICT => true
        ),
        'url' => null,
));

Z předchozího jasně vyplývá, že je potřeba generování URL explicitně rozlišit. Přeci jen webová adresa má být unikátní identifikátor dané akce. Tohoto se dá poměrně jednoduše docílit pouhou úpravou pravidel v routeru. Klidně můžeš aplikovat svoje řešení a editor referencí odlišit pomocí např. editor_ref.

Nesmíš ale zapomenout na to, že takhle je potřeba odlišit všechny adresy, které mají duplicitní výstupy s akcemi článků. ;)

 
Odpovědět
10.10.2016 17:17
Avatar
danhosek
Člen
Avatar
Odpovídá na Jindřich Máca
danhosek:10.10.2016 22:32

Upravil jsem odkazy na editor_ref

<a n:href=":Core:Reference:editor_ref $reference->url">Editovat</a>
<a n:href=":Core:Reference:remove_ref $reference->url">Odstranit referenci</a>

a routy:

public static function createRouter()
        {
                $router = new RouteList();
                $router[] = new Route('kontakt/', 'Core:Contact:default');
                $router[] = new Route('<action>/', array(
                        'presenter' => 'Core:Administration',
                        'action' => array(
                                // řetězec v URL => akce presenteru
                                Route::FILTER_TABLE => array(
                                        'administrace' => 'default',
                                        'prihlaseni' => 'login',
                                        'odhlasit' => 'logout',
                                        'registrace' => 'register'
                                ),
                                Route::FILTER_STRICT => true
                        )
                ));
                $router[] = new Route('[<action>/][<url>]', array(
                        'presenter' => 'Core:Article',
                        'action' => array(
                                Route::VALUE => 'default',
                                Route::FILTER_TABLE => array(
                                        // řetězec v URL => akce presenteru
                                        'seznam-clanku' => 'list',
                                        'editor' => 'editor',
                                        'odstranit' => 'remove'
                                ),
                                Route::FILTER_STRICT => true
                        ),
                        'url' => null,
                ));
        $router[] = new Route('[<action>/][<url>]', array(
            'presenter' => 'Core:Reference',
            'action' => array(
                Route::VALUE => 'default',
                Route::FILTER_TABLE => array(
                    // řetězec v URL => akce presenteru
                    'seznam-referenci' => 'list',
                    'editor_ref' => 'editor',
                    'odstranit_ref' => 'remove'
                ),
                Route::FILTER_STRICT => true
            ),
            'url' => null,
        ));
        $router[] = new Route('[<url>]', 'Core:Reference:default');
        $router[] = new Route('[<url>]', 'Core:Article:default');
                return $router;
        }

ale nyní výpis referencí hlásí:
Invalid link: Unable to pass parameters to action 'Core:Referen­ce:editor_ref', missing corresponding method.

stačí pozměnit pouze routu, nebo musím přejmenovat celou funkci editor?
A dále ještě musím odlišit poslední nejobecnější routy, ale nemám žádný nápad. dal bych před nebo za url reference např. _ , ale nedaří se mi to applikovat.

 
Odpovědět
10.10.2016 22:32
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na danhosek
Jindřich Máca:10.10.2016 22:52

Špatně jsi mě pochopil... Já jsem to myslel tak, že přímo do toho vzoru doplníš to _ref, aby se to tak automaticky překládalo. Asi nějak takto:

$router[] = new Route('<action>_ref/[<url>]', array(
        'presenter' => 'Core:Reference',
        'action' => array(
                Route::FILTER_TABLE => array(
                        // řetězec v URL => akce presenteru
                        'seznam-clanku' => 'list',
                        'editor' => 'editor',
                        'odstranit' => 'remove'
                ),
                Route::FILTER_STRICT => true
        ),
        'url' => null,
));

Tohle řešení by mělo fungovat právě jenom s touto drobnou změnou v routeru. ;)

P.S.: U toho Tvého by jsi musel opravdu přejmenovat i ty funkce.

 
Odpovědět
10.10.2016 22:52
Avatar
danhosek
Člen
Avatar
Odpovídá na Jindřich Máca
danhosek:11.10.2016 0:21

upravil jsem na

$router[] = new Route('<action>_ref/[<url>]', array(
            'presenter' => 'Core:Reference',
            'action' => array(
                Route::VALUE => 'default',
                Route::FILTER_TABLE => array(
                    // řetězec v URL => akce presenteru
                    'editor' => 'editor',
                    'odstranit' => 'remove'
                ),
                Route::FILTER_STRICT => true
            ),
            'url' => null,
        ));

ale nevím, jak udělat ten odkaz správně. Odzkoušel jsem spoustu možností.
mapř
<a n:href=":Core:Re­ference:editor _ref $reference->url">Editovat

Pro vypis-referenci jsem udělal routu zvlast a po uspěšném vyzkoušení bych je sloučil.
Ale mam problem s tím odkazem na editor z administrace vytvoří to odkaz /ediror_ref/
ale asi to neveme ten _ref jako zvlast,aby to mohlo splnit tuto podmínku
$router[] = new Route('<action>_ref/[<ur­l>]', array(

 
Odpovědět
11.10.2016 0:21
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na danhosek
Jindřich Máca:11.10.2016 15:02

Opět jsi to špatně pochopil... Takže ještě jednou polopatě. Když máš toto původní pravidlo:

$router[] = new Route('[<action>/][<url>]', array(
        'presenter' => 'Core:Reference',
        'action' => array(
                Route::VALUE => 'default',
                Route::FILTER_TABLE => array(
                        // řetězec v URL => akce presenteru
                        'seznam-clanku' => 'list',
                        'editor' => 'editor',
                        'odstranit' => 'remove'
                ),
                Route::FILTER_STRICT => true
        ),
        'url' => null,
));

, tak se odkazy interpretují takto:

:Core:Reference:editor -> http://localhost/eshop-nette/editor/

Když změníš pravidlo na:

$router[] = new Route('<action>_ref/[<url>]', array(
        'presenter' => 'Core:Reference',
        'action' => array(
                Route::FILTER_TABLE => array(
                        // řetězec v URL => akce presenteru
                        'seznam-clanku' => 'list',
                        'editor' => 'editor',
                        'odstranit' => 'remove'
                ),
                Route::FILTER_STRICT => true
        ),
        'url' => null,
));

, tak se odkazy automaticky začnou interpretovat takto:

:Core:Reference:editor -> http://localhost/eshop-nette/editor_ref/

Není potřeba měnit nic dalšího. ;)

Už je to jasné?

 
Odpovědět
11.10.2016 15:02
Avatar
danhosek
Člen
Avatar
Odpovídá na Jindřich Máca
danhosek:11.10.2016 15:24

mysli, že jsem přesně toto zkoušel, ale po kliknutí najakýkoliv odkaz mimo úvod , kontakt a výpis článků je nefunkční včetně editace článků a referencí :
Stránka localhost nefunguje

Web localhost vás přesměroval příliš mnohokrát.
Zkuste vymazat soubory cookie.
ERR_TOO_MANY_RE­DIRECTS

zkusil jsem i upravit na
$router[] = new Route('[<acti­on>]_ref/[<ur­l>]', array(
a všechny odkazy referencí jsou směrovány na stránka nebyla nalezena

$router[] = new Route('[<action>/][<url>]', array(
                        'presenter' => 'Core:Article',
                        'action' => array(
                                Route::VALUE => 'default',
                                Route::FILTER_TABLE => array(
                                        // řetězec v URL => akce presenteru
                                        'seznam-clanku' => 'list',
                                        'editor' => 'editor',
                                        'odstranit' => 'remove'
                                ),
                                Route::FILTER_STRICT => true
                        ),
                        'url' => null,
                ));
        $router[] = new Route('<action>_ref/[<url>]', array(
            'presenter' => 'Core:Reference',
            'action' => array(
                Route::VALUE => 'default',
                Route::FILTER_TABLE => array(
                    // řetězec v URL => akce presenteru
                    'seznam-referenci' => 'list',
                    'editor' => 'editor',
                    'odstranit' => 'remove'
                ),
                Route::FILTER_STRICT => true
            ),
            'url' => null,
        ));
 
Odpovědět
11.10.2016 15:24
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na danhosek
Jindřich Máca:11.10.2016 16:49

Já jsem si to taky zkoušel napsat lokálně a funguje mi to. :)

Každopádně v tom kousku kódu, co jsi teď poslal, vidím minimálně dvě chyby:

1. Pokud sis nevšiml, tak jsem ve svým příkladech odstranil:

Route::VALUE => 'default'

2. Opět by ty routovací pravidla měli jít v opačném pořadí, protože [<action>/][<ur­l>] je rozhodně obecnější než <action>_ref/[<ur­l>].

Doporučoval bych začít poctivě používat Nette Laděnku a dobře se koukat, jaká routovací pravidla se vlastně kde aplikují. ;)

Už jsem to tady jednou psal do komentářů, konkrétně http://www.itnetwork.cz/…ypis-clanku/?…, ale radši to ještě zopakuji. Routování je relativně složitější záležitost a chce to mu nejdříve porozumět, než zběsile zkoušet všechny kombinace. :-P

 
Odpovědět
11.10.2016 16:49
Avatar
danhosek
Člen
Avatar
Odpovídá na Jindřich Máca
danhosek:11.10.2016 19:35

já vím, máš zcela pravdu, ale moc toto chci dotahnout. Úpravy zabraly a vše nyní funguje!
Obecné routy jsem odlišil a upravil na
$router[] = new Route('referen­ce/[<url>]', 'Core:Referen­ce:default');
$router[] = new Route('[<url>]', 'Core:Article:de­fault');
return $router;
}
a už to jede. Mockrát děkuji za trpělivost a ochotu, vím že to semnou není lehké. děkuji!

 
Odpovědět
11.10.2016 19:35
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na danhosek
Jindřich Máca:11.10.2016 21:14

Přesně takhle by to mělo vypadat, dobrá práce! :)

 
Odpovědět
11.10.2016 21:14
Avatar
danhosek
Člen
Avatar
danhosek:12.10.2016 22:48

Ještě mám jeden dotaz, nevím, jestli se to přesně vztahuje k routám, ale myslím že ano.
Když chci odlišit úvodní stránku od ostatních článků. Aby úvodní stránka obsahovala něaké tagy navíc.
Udělám si např.: uvod.latte ale nevim, jak mám přesměrovat úvod(není zadaná url) na jinou šablonu.
Mapadlo mě i řešení podmínky v latte, jako je řešený výpis v editaci, ale u tohoto mi to přijde jako nevhodné řešení a nevím jak udělat podmínku ve tvaru {if {$article->url}='uvod'}
spíše bych to řešil přesměrování na jenou latte šablonu, ale jak toto nejlépe provést?
Děkuju.

 
Odpovědět
12.10.2016 22:48
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na danhosek
Jindřich Máca:13.10.2016 14:11

Určitě bych to neřešil v rámci samotné Latte šablony. O to, co se má vykreslit se má starat pro konkrétní URL router a pro konkrétní případ při obecnějším routovacím pravidlu, samotná akce routerem zvoleného presenteru. :)

Zkusím opět uvést příklad. U článků je to tak, že pro zobrazení článku máme obecnou routu:

$router[] = new Route('[<url>]', 'Core:Article:default');

Ta vybere akci "default" ve třídě ArticlePresenter a předá jí do parametru konkrétní URL, chtěného článku, nebo null, pokud se jedná o úvodní stránku. Takhle je to prostě v tomto seriálu naprogramované.

Takže, abych odpověděl na Tvojí otázku. Výběr šablony by se v ideálním případě měl provádět před samotným renderováním, ale na druhou stranu, pokud se změní až na začátku renderování, tak se taky nic neděje. :) Takže kód zvolené metody renderDefault() vypadá tedy následovně:

public function renderDefault($url)
{
        if (!$url) $url = self::DEFAULT_ARTICLE_URL; // Pokud není zadaná URL, vykreslí se výchozí článek.
        // Pokusí se načíst článek s danou URL a pokud nebude nalezen, vyhodí chybu 404.
        if (!($article = $this->articleManager->getArticle($url))) throw new BadRequestException();
        $this->template->article = $article; // Předá článek do šablony.
}

Tady je vidět, že pokud není zadaná žádná URL, automaticky se vybírá úvodní článek. Teď už stačí jenom tuhle podmínku předělat, aby se místo toho použila úplně jiná šablona s jiným obsahem. ;)

Může se zde aplikovat třeba stejný postup jako u komponent a vypadat to může např. takto:

public function renderDefault($url)
{
        if (!$url or $url == self::DEFAULT_ARTICLE_URL) {
                // Nastavení jiné šablony.
                $this->template->setFile(__DIR__ . "/../templates/Article/uvod.latte");
                // Předávání dat do šablony funguje standardním způsobem.
                // $this->template->...
        } else {
                // Pokusí se načíst článek s danou URL a pokud nebude nalezen, vyhodí chybu 404.
                if (!($article = $this->articleManager->getArticle($url))) throw new BadRequestException();
                $this->template->article = $article; // Předá článek do šablony.
        }
}

Doufám, že takhle už je vše jasné. :)

 
Odpovědět
13.10.2016 14:11
Avatar
danhosek
Člen
Avatar
danhosek:13.10.2016 14:49

trochu jsem metodu render default upravil, a už je to funkční. Děkuji za podrobné vysvětlení. Hlavně by mě nenapadlo $this->template->setFile. Něco takového jsem měl namysli, ale nevěděl jsem jak na to. Děkuji.

public function renderDefault($url)
{
if (!$url or $url == self::DEFAULT_ARTICLE_URL){
    $url = self::DEFAULT_ARTICLE_URL;
    $this->template->setFile(__DIR__ . "/../templates/Article/uvod.latte");
} // Pokud není zadaná URL, vykreslí se výchozí článek.
        // Pokusí se načíst článek s danou URL a pokud nebude nalezen, vyhodí chybu 404.
        if (!($article = $this->articleManager->getArticle($url))) throw new BadRequestException();

        $this->template->article = $article; // Předá článek do šablony.
}
 
Odpovědět
13.10.2016 14:49
Avatar
danhosek
Člen
Avatar
danhosek:16.10.2016 0:03

Ahoj, na localhostu projekt perfektně funguje, ale nejde mi vložit na webhosting od wedos. Pročetl jsem diskuzi a vím, že jsem to kdysi řešil a poučil jsem se a opravil některé chybky, ale dnes je to nefunkční a server error 500.
config.loval.neon:

database:
dsn: 'mysql:host=wm87.wedos.net;port=3306;dbname=XXXX'
user: 'XXXXX'
password: 'XXXXX'
options:
lazy: yes

LOG:
exception:

Found sections 'dsn', 'user', 'password', 'options', 'lazy' in configuration, but
corresponding extensions are missing.

Source file

Call stack

.../vendor/nette/di/src/DI/Compiler.php:139     source  Nette\DI\Compiler->     processExtensions ()

.../vendor/nette/bootstrap/src/Bootstrap/Configurator.php:268   source  Nette\DI\Compiler->     compile ()

inner-code      Nette\Configurator->    generateContainer (arguments)

.../vendor/nette/di/src/DI/ContainerLoader.php:113      source  call_user_func_array (arguments)

.../vendor/nette/di/src/DI/ContainerLoader.php:78       source  Nette\DI\ContainerLoader->      generate (arguments)

.../vendor/nette/di/src/DI/ContainerLoader.php:43       source  Nette\DI\ContainerLoader->      loadFile (arguments)

.../vendor/nette/bootstrap/src/Bootstrap/Configurator.php:222   source  Nette\DI\ContainerLoader->      load (arguments)

.../app/bootstrap.php:19        source  Nette\Configurator->    createContainer ()

 9:
10:    $configurator->setTempDirectory(__DIR__ . '/../temp');
11:
12:    $configurator->createRobotLoader()
13:        ->addDirectory(__DIR__)
14:        ->register();
15:
16:    $configurator->addConfig(__DIR__ . '/config/config.neon');
17:    $configurator->addConfig(__DIR__ . '/config/config.local.neon');
18:
19:    $container = $configurator->createContainer();
20:
21:    return $container;
22:
.../www/index.php:6     source  require (arguments)

po vyhledání chyby na google mi vyskočilo, že byl přechod na nové připojování na db, ale když je sandbox z tohoto projektu, tak by mělo být nastavení dle starých parametrů že?
Děkuji za pomoc a zkušenosti.

Editováno 16.10.2016 0:05
 
Odpovědět
16.10.2016 0:03
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na danhosek
Jindřich Máca:16.10.2016 0:24

To proto, že Ti chybí správné odsazení v config.local.ne­on... Na první pohled je to vidět i tady, že ty parametry 'dsn', 'user', 'password', 'options', 'lazy' nemáš odsazené. :D

 
Odpovědět
16.10.2016 0:24
Avatar
danhosek
Člen
Avatar
Odpovídá na Jindřich Máca
danhosek:16.10.2016 1:26

správné odsazení? jak má vypadat správné odsazení?
odentrování mezi parametry?

parameters:

    dbname: 'XXXXX' # název databáze

# Konfigurace databázové služby dále přístupné pomocí DI v rámci celé aplikace.
database:

dsn: 'mysql:host=wm87.wedos.net; port=3306; dbname=XXXX'

user: 'XXXXX'

password: 'XXXX'

options:

lazy: yes

takto to také nefunguje a vypisuje stejnou exception (Found sections 'dsn', 'user', 'password', 'options', 'lazy' in configuration, but corresponding extensions are missing.)
jakou rozšířenou konfiguraci to chce? nebo kde je tam konkrétně chyba?
děkuji.

Editováno 16.10.2016 1:27
 
Odpovědět
16.10.2016 1:26
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na danhosek
Jindřich Máca:16.10.2016 1:40

Tak teď jsem se upřímně zasmál... :D Takhle jsem to odsazení myslel:

parameters:
    dbname: 'XXXXX' # název databáze

# Konfigurace databázové služby dále přístupné pomocí DI v rámci celé aplikace.
database:
        dsn: 'mysql:host=wm87.wedos.net;dbname=%dbname%'
        user: 'XXXXX'
        password: 'XXXX'
        options:
                lazy: yes

Žádnou další konfiguraci to nechce. Jde o to, že NEON je prostě citlivý na odsazení a pokud tam úplně chybí, jako v tomto případě, bere parametr dsn atd. jako část globálního nastavení, podobně jako např. services. Samozřejmě taková položka v globální nastavení není, takže to hází onu chybu. ;)

 
Odpovědět
16.10.2016 1:40
Avatar
danhosek
Člen
Avatar
Odpovídá na Jindřich Máca
danhosek:16.10.2016 12:40

:-D mno...:-D
tedy jsem snad správně odsadil ale stále je problem:

Found sections 'options', 'lazy' in configuration, but corresponding extensions are missing.

parameters:

    dbname: 'XXXXX' # název databáze

# Konfigurace databázové služby dále přístupné pomocí DI v rámci celé aplikace.
database:
    dsn: 'mysql:host=wm87.wedos.net; port=3306; XXXXX'
    user: 'XXXX'
    password: 'XXXX'

options:
lazy: yes

options a lazy jsem zkusil odsazené i neodsazené (vím, zběsilé zkjoušení všeliakých možností :-D)
je to problem odsazení, nebo muže to být třeba špatným portem? nevim, kde ho zjistit, tak tento port mi dala podpora, stím že si není jistý :-D

 
Odpovědět
16.10.2016 12:40
Avatar
danhosek
Člen
Avatar
Odpovídá na danhosek
danhosek:16.10.2016 12:46

už to mám, jen pozdě a příspěvek již nešel odstranit:-D mno jen správně odsadit, děkuji moc, a doufám, že jsi se alespon dobře pobavil na večer :o)

 
Odpovědět
16.10.2016 12:46
Avatar
danhosek
Člen
Avatar
danhosek:30.10.2016 16:51

Ahoj, když chci přidat funkci, která podle url článku vrátí ID článku, bude vypadat takto:
ale nevím, jak má vypadat ten požadavek do db

public function getArticleId($url)
    {
        return $this->database->table(self::TABLE_NAME)->get(article_id)->where(self::COLUMN_URL, $url);
    }

Může to být takto?
a pro jistotu volání této funkce v modelu, a vrátí číslo id vypadá takto:

$this->getReferenceId($url)

děkuji.

 
Odpovědět
30.10.2016 16:51
Avatar
danhosek
Člen
Avatar
Odpovídá na danhosek
danhosek:30.10.2016 17:25

mySQL dotaz by vypadal takto :

SELECT `article_id` FROM `article` WHERE `url`=$url
 
Odpovědět
30.10.2016 17:25
Avatar
danhosek
Člen
Avatar
Odpovídá na danhosek
danhosek:30.10.2016 18:53

tak můj finální výsledek je toto:

return $this->database->table('article')->where('url', $url)->get("article_id");

ale nemůžu to odzkoušet, protože to mám rozdělaný a ted to nepujde spustit.

 
Odpovědět
30.10.2016 18:53
Avatar
danhosek
Člen
Avatar
danhosek:30.10.2016 19:31

Ahoj, ještě bych chtěl poradit, s funkcí

public function saveArticle($article)
        {
                if (!$article[self::COLUMN_ID])
                        $this->database->table(self::TABLE_NAME)->insert($article);
                else
                        $this->database->table(self::TABLE_NAME)->where(self::COLUMN_ID, $article[self::COLUMN_ID])->update($article);
        }

a chci přidat return, který vrací article_id nově uloženého článku.
Děkuji.

 
Odpovědět
30.10.2016 19:31
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na danhosek
Jindřich Máca:31.10.2016 18:45

Ahoj, tak to vezmu zase postupně, protože je opět vidět, že děláš něco, čemu úplně nerozumíš. :(

  1. Máš chybu hned v názvu metody. Zase nějaká nepozornost? Funkci máš pojmenovanou getArticleId() a voláš metodu getReferenceId().
  2. Úplně špatně jsi pochopil chování metody get(). Dokumentace říká

Returns row specified by primary key.

To znamená, že vrátí celý záznam (všechny sloupečky) podle konkrétního zadaného primárního klíče (nebo false, pokud záznam s takovým primárním klíčem neexistuje).

Každopádně tu metodu jako takovou nemáš úplně špatně. Vypadat by měla nějak takto:

/* Měl by se vykonat přesně ten databázový dotaz, který jsi poslal, který ale může vrátit pole
záznamů v případě, že sloupeček s URL není unikátní, takže pro jistotu vytáhneme první shodu. */

// Načte první záznam článku s danou URL z databáze, pokud existuje.
if (!($article = $this->database->table('article')->select('article_id')->where('url', $url)->fetch())) {
        // Co se má udělat pokud článek se zadanou URL neexistuje.
} else {

        /* V proměnné $article jsou teď uloženy všechny sloupečky daného záznamu vyžádané
        v SELECT, takže zde je to pouze sloupeček 'article_id'. Z principu je to ale pole, takže samotné
        ID z něj musíme ještě vytáhnout. */

        return $article['article_id']; // Vrací ID článku.
}

Pozn.: Nezkoušel jsem to.

  1. Ta druhá funkce, na kterou jsi se ptal a měla by vracet ID vloženého článku, se upraví asi nějak takto:
if (!$article[self::COLUMN_ID]) {
        $row = $this->database->table(self::TABLE_NAME)->insert($article);
        return $row[self::COLUMN_ID];
} else {
        $this->database->table(self::TABLE_NAME)->where(self::COLUMN_ID, $article[self::COLUMN_ID])->update($article);
        return $article[self::COLUMN_ID];
}

Pozn.1: Opět jsem to nezkoušel.
Pozn.2: Nedělal jsem tady kontrolu toho, jestli se článek skutečně podaří vložit, či editovat.

  1. To, že to máš rozpracované by nemělo vadit, pokud používáš např. verzovací systém jako je Git , či jenom verzování v rámci IDE, nebo si na to jednoduše napiš Unit test. :)

Doufám, že už je to všechno jasnější. ;)

P.S.: Neber si to špatně, ale čím víc dotazů pokládáš, tím mám větší pocit, že ještě úplně neovládáš programování v PHP a principy OOP jako takové. Možná bych nejdříve doporučil zaměřit se na ně, místo toho, aby ses rovnou vhrnul na celý e-shop ve frameworku. Navíc, pokud to neděláš jenom jako cvičení a plánuješ komerční použití, tak je potřeba myslet ještě na spoustu dalšího zabezpečení a neudělat v kódu amatérské chyby, jinak hrozí potenciální katastrofa v podobě např. úniku uživatelských dat apod.

 
Odpovědět
31.10.2016 18:45
Avatar
danhosek
Člen
Avatar
Odpovídá na Jindřich Máca
danhosek:31.10.2016 19:06

děkuju, to je přesně to co jsem potřeboval. Neboj se, nechci použít eshop komerčně, vím kolik je tam dalších aspektů, kterým plně nerozimim, ale zde mi jde čistě jen o tu administraci obrázků "Widget".
Jinak ty chyby, že místo Article je reference, je že to dělám pro obrázky do referencí a chtěl jsem to přizpusobit do seriálu na article, ale někde mi to uniklo a nepřepsal jsem to.
Děkuji.

 
Odpovědět
31.10.2016 19:06
Avatar
Daniel Vašek:20.2.2017 17:44

Jen taková poznámka k čistčímu kódu, kdyby jsi nahradil $this->database->table(self::TAB­LE_NAME) novou funkcí např. getAll(), nemusel by se ten dlouhý kus kódu pokaždé opisovat. Pokud se mýlím, vyveď mě z omylu :)

 
Odpovědět
20.2.2017 17:44
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Daniel Vašek
Jindřich Máca:20.2.2017 18:08

Určitě souhlasím, já jsem dokonce šel ještě trochu dál a mám vlastní knihovnu, kde pokud podědíš z dané třídy, automaticky tam tu metodu getAll() i nějaké další máš. ;)

 
Odpovědět
20.2.2017 18:08
Avatar
Roman Červeňan:29.6.2017 14:04

Ahoj všichni, zkouším začít s Nette, některé, především "automatické" činnosti frameworku mi nejsou zcela jasné, jak fungují, jednou z nich je třeba i vytvoření SQL dotazů. A právě tady jsem také narazil a nevím, jak dál.
Standardně jsem vytvořil na lokále DB dle scriptu, tedy včetně autoincrement polí. Při pokusu o uložení nového článku přes admin sekci mi debugger nahlásí "Chybu Serveru" a já v debuggeru vidím, že aplikace vytvořila dotaz, který podle mne nemůže do DB projít: INSERT INTO article (article_id, title, url, description, content) VALUES ('', ?, 'url-dalsiho-clanku', ?, ?)
Pole jsem vyplnil následovně:
Titulek: Titulek dalšího článku
URL: url-dalsiho-clanku
Popisek: popisek dalšího článku
Obsah: Obsah dalšího článku.

Mám divný pocit, že si to jednak nějak neporadí s češtinou, jednak je zajímavá položka article_id, která má ve Values hodnotu '', což pro INT(11) NOT NULL AUTO_INCREMENT není přípustná hodnota, pokud se nepletu, lepší je položku úplně vynechat.
Celý insert je automaticky vytvořen tímto řádkem: $this->database->table(self::TAB­LE_NAME)->insert($article);

Poradíte, co nastavit? Je chyba v nastavení DB (Debugger mi ukazuje, že před insertem se ještě volá SET NAMES 'utf8mb4', má to na něco vliv - třeba na ty chybějící české řetězce?) ? Nebo mám chybu v nastavení Nette?

Ani nevím, co všechno potřebujete vědět, tak jen pro začátek: mám Nette 2.4, Apache/2.4.25 (Win32) OpenSSL/1.0.2j PHP/5.6.30.

 
Odpovědět
29.6.2017 14:04
Avatar
Matyáš Herman:17.11.2017 10:40

Ahoj, postupoval jsem podle postupu, a hází mi to error. Když jsem stáhnul zdroják odsud, tak mi to stále hlásí stejnou chybu:

Nette\Database\Con­nectionExcepti­on #HY000

SQLSTATE[HY000] [2002] Connection refused

.../app/CoreMo­dule/model/Ar­ticleManager.php:58 source Nette\Database\Con­text-> table (arguments)

S tím, že řádka 58 je červená..

48:            return $this->database->table(self::TABLE_NAME)->order(self::COLUMN_ID . ' DESC');
49:        }
50:
51:        /**
52:         * Vrátí článek z databáze podle jeho URL.
53:         * @param string $url URl článku
54:         * @return bool|mixed|IRow první článek, který odpovídá URL nebo false při neúspěchu
55:         */
56:        public function getArticle($url)
57:        {
58:            return $this->database->table(self::TABLE_NAME)->where(self::COLUMN_URL, $url)->fetch();
59:        }
60:
61:        /**
62:         * Uloží článek do systému. Pokud není nastaveno ID, vloží nový, jinak provede editaci.
Editováno 17.11.2017 10:41
 
Odpovědět
17.11.2017 10:40
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Matyáš Herman
Jindřich Máca:17.11.2017 17:30

Ahoj, to bude nejspíš proto, že máš špatně nastavené přihlašovací údaje k databázi v configu. ;)

 
Odpovědět
17.11.2017 17:30
Avatar
Michal Dvořáček:15.2.2018 10:16

Zdravím,
chtěl bych se zeptat na BaseManager, konkrétně na Object.
Nějak jsem pochopil, že už je Nette\Object zastaralé a místo ní se udělalo Nette\SmartObject.
Co ale neumím určit, je jak se třeba konkrétně v tomto příkladu využije, respektive o co mám pak BaseManager rozšířit. Zkoušel jsem právě o SmartObject, ale nefunguje.

use Nette\SmartObject;
abstract class BaseManager extends SmartObject
{...}

Děkuji za každou radu jak tuto komplikaci vyřešit.

Editováno 15.2.2018 10:18
 
Odpovědět
15.2.2018 10:16
Avatar
dez1nd
Člen
Avatar
Odpovídá na Michal Dvořáček
dez1nd:15.2.2018 10:21

Dědit nic nemusíš, máš to v use

potom stačí jen

$objekt = new SmartObject;

kdyby jsi to neměl v use tak bys musel

$objekt = new Nette\SmartObject;
Editováno 15.2.2018 10:23
 
Odpovědět
15.2.2018 10:21
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Michal Dvořáček
Jindřich Máca:15.2.2018 14:04

Ahoj, problém je v tom, že SmartObject není třída, ale PHP trait, což už mluví za vše. Příklady jejího použití pak najdeš přímo v oficiální dokumentaci - https://doc.nette.org/…/smartobject.

 
Odpovědět
15.2.2018 14:04
Avatar
David Čápka
Tým ITnetwork
Avatar
David Čápka:6.8.2018 13:24

Aktualizováno pro Nette 2.4.

Odpovědět
6.8.2018 13:24
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
Fero Mikulic
Člen
Avatar
Fero Mikulic:14. března 17:20

Ahoj. Udelal sem vsechno podle postupu a haze mi to chybu

"Nette\DI\Ser­viceCreationEx­ception

Service 'routing.router': Method App\Router\Rou­terFactory::cre­ateRouter() is not callable."

 
Odpovědět
14. března 17:20
Avatar
Milan Turyna
Redaktor
Avatar
Milan Turyna:14. března 18:25

Nekoukal jsem na serial, ale myslim si že to muze byt zpusobeno ze vyuzivas novou verzi a serial je pro starsi ale nevim. Ja kdyz jsem postupoval pri tvorbe cmska pres nette jen podle dokumentace tak mi to vzdy slo. Takze mozna ta verze.

 
Odpovědět
14. března 18:25
Avatar
Milan Turyna
Redaktor
Avatar
Milan Turyna:14. března 18:26

Jeste sem muzes poslat config

 
Odpovědět
14. března 18:26
Avatar
Fero Mikulic
Člen
Avatar
Fero Mikulic:23. března 13:53

Skousel sem to i na 2.4 a stejnej error.
Tady je GitHub repo
https://github.com/…ob/nette-cms

 
Odpovědět
23. března 13:53
Avatar
Daniel Vítek
Tým ITnetwork
Avatar
Odpovídá na Fero Mikulic
Daniel Vítek:23. března 16:02

https://github.com/…rFactory.php

Máš zde špatný namespace - jen App. Uprav jej na App\Router.

Odpovědět
23. března 16:02
Na síti působím už pěknou řádku let. Pokud budeš něco potřebovat, písni mi, pokusím se ti poradit :)
Avatar
Fero Mikulic
Člen
Avatar
Odpovídá na Daniel Vítek
Fero Mikulic:24. března 15:54

Dekuji. Pomohlo to

 
Odpovědět
24. března 15:54
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 103 zpráv z 103.