V tomto díle seriálu si, jak jsem minule slíbil, nastavíme prostředí pro práci, rozjedeme Nette a Dibi a pozdravíme svět.

Seriál Webová aplikace v Nette pro začátečníky

Seriál provází tvorbou webové aplikace v Nette Frameworku, od prvotní konfigurace prostředí, až po hotový produkt. Napíšeme si aplikaci, která bude umět registrovat, přihlásit a spravovat uživatele.

PHP a MySQL

Budeme samozřejmě pracovat v lokálním vývojovém prostředí, takže budeme potřebovat rozjet lokální server s PHP a MySQL.

Uděláme to tím nejjednodušším způsobem – pro windows existuje několik instalačních „balíků“, které řeší většinu toho, co Běžný Franta Vývojář potřebuje.

Jsou to například:

V tomto seriálu použiju poslední jmenovaný – ze stránek EasyPHP si stáhněte instalační soubor a spusťte jej. Proklikejte se instalací, není v ní nic záludného. Po úspěšném skončení instalace byste měli v prohlížeči na adrese http://127.0.0.1/ vidět rozhraní EasyPHP se seznamem projektů.

EasyPHP si ve výchozím nastavení pro tyto projekty sahá do umístění <disk>/Program Files/EasyPHP-<verze>/www, zde vytvořte soubor info.php s obsahem

<?php
phpinfo();

V rozhraní EasyPHP v prohlížeči by se měl soubor info.php objevit – klinkěte na něj a v případě, že všechno funguje, se pokochejte konfigurací PHP.

Pro správu MySQL databáze použijeme Adminer, který si stáhněte a stažený soubor umístěte na stejnou úroveň vedle souboru info.php. Klikněte na něj v rozhraní EasyPHP, jako uživatele zadejte root a přihlaste se. Uvidíte seznam databází, ty nás ale nezajímají, vytvoříme si pro náš projekt databázi novou :

CREATE DATABASE `users` COLLATE 'utf8_bin';

V této fázi, pokud vše proběhlo bez problému, máme nainstalové PHP a MySQL a vytvořenou prázdnou databázi. Pojďme na Nette a Dibi.

Nette Framework

Stáhněte si Nette. V seriálu budu používat Nette pro PHP 5.3 a vyšší, bez prefixů, verzi 2.0.6. Po stažení rozbalte zip a najděte v adresáři tools nástroj zvaný Requirements-Checker, který nakopírujte do EasyPHP www adresáře a spusťte v prohlížeči. Tento nástroj zkontroluje, zda je náš vývojový server způsobilý pro fungování s Nette, což je, takže můžeme směle pokračovat.

Vedle adresáře tools v Nette balíku se nachází adresář sandbox, což je taková (skoro) minimální fungující předpřipravená Nette webová stránka. Nakopírujte celý sandbox do EasyPHP adresáře a spusťte v prohlížeči. Uvidíte uvítací projekt Nette, na kterém postavíme naši aplikaci.

Pro další informace o instalaci a struktuře Nette vřele doporučuji Stažení a instalace v dokumentaci

Netbeans

Přicházíme do fáze, ve které budeme potřebovat nějaký editor. Ten je vždy otázkou osobní volby, já budu v tomto seriálu budu používat Netbeans. Stáhněte si Netbeans pro PHP, nainstalujte a spusťte. Vytvoříme si nový projekt Users a to importem adresáře sandbox. Nejdříve si na disku přejmenujte adresář sandbox na Users a potom v Netbeans proveďte File → New Project → PHP / PHP Application with existing sources → Vyberte <adresar_projek­tu_na_disku> a Finish.

Do Netbeans si ještě nastavíme Xdebug na krokování programem, ale to až někdy příště.

Dibi a databáze

Dibi je knihovna pro práci s databází. Stáhněte si verzi 2.0.1, rozbalte a vnitřní adresář dibi (obsahuje adresáře drivers, libs, Nette a soubour dibi.php) nakopírujte do našeho projektu do adresáře libs. Smažte obsah adresáře temp/cache a refreshněte projekt v prohlížeči – Nette loader se tak postará o „natáhnutí“ Dibi do projektu.

Konfigurace Nette projektu probíhá v <projekt>/app/con­fig/config.ne­on a v <projekt>/app/bo­otstrap.php. V těchto místech si teď nastavíme Dibi.

Otevřete si soubor a do config.neon pod řádek development < common vložte

development < common:
    dibi:
        host: localhost
        username: root
        password:
        database: users
        lazy: TRUE

Co jsme právě udělali – do „sekce“ development která je podmnožinou sekce common, jsme zapsali konfiguraci připojení k databázi pro vývojové prostředí. Pro nasazení na ostrý server bychom zadali konfiguraci do sekce production < common . Nette pak automaticky rozliší v jakém prostředí se nachází. Jak je zřejmé, konfigurace platící pro všechna prostředí umístíme do sekce common

Při zapisování konfigurace si dávejte dobrý pozor, abyste odsazovali buď pomocí mezer, nebo skutečných tabulátorů, nikdy ne obojí zároveň – více o konfiguraci v config.neon Nette v dokumentaci.

Pokračujeme v souboru bootstrap.php, kde Dibi zaregistrujeme pomocí rozšíření, které ve verzi 2 obsahuje. Před vytvořením DI kontejneru pomocí

$container = $configurator->createContainer();

řekneme, že

$configurator->onCompile[] = function ($configurator, $compiler) {
    $compiler->addExtension('dibi', new DibiNetteExtension);
};

Tím jsme s konfigurací Dibi hotovi. Nebo ne? Zkusíme to ověřit.

Model a práce s daty

Jak je v MVC kraji zvykem, do databáze se podíváme skrze model. V adresáři app/model vytvořte soubor Users.php s obsahem

class Users extends \Nette\Object {

    /** @var \DibiConnection */
    private $db;
    private $table = "users";

    public function __construct(\DibiConnection $connection) {
        $this->db = $connection;
    }

    public function findAll() {
        return $this->db->select('*')->from($this->table);
    }
}

Zde myslím vše jasné – v konstruktoru jsme si dodali Dibi připojení a napsali si metodu findAll, která vrátí obsah tabulky users. Pokračujeme do další vrsty a to app/presenter­s/HomepagePre­senter.php

class HomepagePresenter extends BasePresenter {

    /** @var Users */
    private $users;

    protected function startup() {
        parent::startup();
        $this->users = $this->context->users;
    }

    public function renderDefault() {
        $this->template->anyVariable = 'any value';
    }

}

Zde se naopak děje cosi na první pohled trochu zvláštního – kde se vzalo a co to je $this->context->users v metodě startup? Uložte všechny změny a zkuste reload projektu v prohlížeči. To co vidíte je váš přítel – ladící výpis Nette, neboli takzvaná „Laděnka“.

Podstatné je sdělení Service ‚users‘ not found. To je to users, které požadujeme v startup metodě. Pojďme do config.neon dodělat, co jsme začali – do common sekce pod definice services zadejte

services:
    users:
        class: \Users(@dibi.connection)

Tím by měla být konfigurace Dibi a profouknutí Modelu hotova. Ověříme to výpisem dat.

Výpis dat

V databázi vytvořte tabulku users

CREATE TABLE `users` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `email` varchar(50) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`email`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;

INSERT INTO `users` (`id`, `email`) VALUES
(1,     'hello@world.cz'),
(2,     'lojza@lojza.cz'),
(3,     'mala@tonicka.cz'),
(4,     'gerda@zapasnikova.cz'),
(5,     'anna@k.cz'),
(6,     'barca@bramburka.cz'),
(7,     'hilda@zelena.cz'),
(8,     'hajdy@zhor.cz'),
(9,     'johanka@vplutu.com');

Blížíme se do finále, vypíšeme si naše skvostné uživatele a dáme si čaj.

HomepagePre­senter.php změňte metodu renderDefault, která obsluhuje domácí stránku, takto

public function renderDefault() {
    $all_users = $this->users->findAll()->orderBy('id')->fetchAll();
    $this->template->all_users = $all_users;
}

Zde je vše jasné – do šablony jsme si poslali všechny uživatele seřazené podle jejich id.

V šabloně domácí stránky je jednoduše vypíšeme – obsah app/templates/Ho­mepage/default­.latte změňte na

{block content}

<ul>
    {foreach $all_users as $user}
        <li>{$user->email}</li>
    {/foreach}
</ul>

a pokochejte se výsledkem v prohlížeči.

Shrnutí

Pro začátek máme hotovo – máme nastaveny základní nástroje pro další práci, umíme si vypsat obsah MySQL tabulky do šablony. Mnoho věcí jsem v zájmu kompaktnosti článku vynechal/nazna­čil/zestručnil – případné nejasnosti doporučuji zatím buď neřešit, nebo vyhledat v dokumentaci Nette, nebo na fóru Nette.

Samozřejmě, pokud je v článku něco nesrozumitelného, nebo je tam vyložená chyba, komentáře jsou vám k dispozici.

Příště

V příštím díle si do aplikace napíšeme obsluhu pro registraci a přihlašování uživatelů. Což bude brnkačka.

Komentáře

Ivo před 4 lety

No zatím mi to připadá jen jako další kopie http://doc.nette.org/cs/quickstart (upravený pro dibi). Myslím, že daleko přínosnější by bylo rozšiřovat samotný quickstart (multijazyčnost, acl), ale možná se k tomu v nějakém z dalších dílů dostaneš, tak držím palce.

reagovat

Peter Láng před 4 lety

Ano, tenhle díl v podstatě je quickstart, to máš pravdu. Quickstart je ale detailnější v popisování a některé věci co budou v seriálu v něm nejsou a naopak.

Jako rozšíření quickstartu můžeme brát „napojení“ datatables v jednom z dalších dílů seriálu.

Plus, po skončení seriálu by skutečně mohly vznikat články o vylepšování a rozšiřování aplikace, ale to se ještě uvidí.

reagovat

enumag před 4 lety

Předávat @dibi.connection do služby Users ručně není potřeba, o to se stará autowiring. Rovněž v neonu můžeš vynechat \ na začátku názvu třídy.

Další námět do budoucna: instalace nette (a dalších knihoven) pomocí composeru.

Otázka: budeš se pouštět i do nějakých základů testování pomocí PHPUnit (jak testovat Nette aplikaci respektive presentery, komponenty a modely)?

reagovat

Peter Láng před 4 lety

Jo, tak s neonem máš pravdu, dík za doplnění.

Na composer se podívám (ještě jsem nezkoušel), o testování s PHPUnit vážně přemýšlím, uvidíme jak to vyjde.

reagovat

enumag před 4 lety

Ok. Zatím tvé články moc nečtu, jednak nepoužívám dibi a druhak by mi asi už nepřinesly nic nového. Kdyby ses ale pustil do PHPUnit, bylo by to něco úplně jiného. :-) Řekl bych že hodně lidí by rádo testovalo, obecných návodů na PHPUnit je spousta, ale co a jak testovat v reálné aplikaci by pár příkladů určitě zasloužilo.

reagovat

Wyatte před 3 lety

Zdravím,.. koukám, že poslední příspěvek je tady starý 4 měsíce, tak nevím, zdali je to ještě stále sledované téma. Mám problém při registraci tříd v config.neon, zkoušel jsem více možných zápisů, ale ať se snažím jakkoliv, tak mi to blbne. Laďenka mi píše

Class Users used in service ‚users‘ has not been found or is not instantiable.

Je vše napsané dle tutoriálů, zkoušel jsem i oficiální tutoriál z dokumentace o Nette, ale ani tam mi to nešlo a dělalo mi to podobné věci. Zkouším to přímo na internetu na endoře, localhost málokdy používám.

Použité verze.

PHP 5.4.14 | Server Apache/2.2.15 (CentOS) | Nette Framework 2.0.10

reagovat

Peter Láng před 3 lety

Ahoj, jestliže máš všechno přesně podle návodu (nejlepší je to ověřit clonem z https://github.com/…s/tree/part2) a ani oficiální tutoriál z Nette webu ti nejede, hledal bych chybu někde mimo kód.

Třeba Nette requirements checker ti hlásí zelenou? Nebo bych hledal třeba http://jdem.cz/2z597.

reagovat

Wyatte před 3 lety

Ano, Nette requirements checker byl zelený. Mimochodem, stáhnu jsem si zdrojové kódy z toho „github.com“ pro tento projekt a nyní mi registrace třídy pomocí services i spojení s DB funguje, sice nějak kostrbatě, jelikož jsem mimo přihlášení do MySQL v dibi v config.neon musel zadávat údaje také do normálního připojení a trošku mi blbne přihlašování (login) v projektu. Ale samotná komunikace s MySQL naštěstí už funguje.

Jenomže, nechápu kde byla chyba, to je na tom nejhorší. Přísahal bych, že jsem dělal krok po kroku a mělo by to být správně, i logicky mi vše sedělo, ale prostě když jsem to dělal sám, tak mi to psalo chybu v té registracei třídy. Nemůže být čistě náhodou nějaká chybička v té verzi Nette, co je aktuálně ke stažení? Protože Nette, co je použito na tento projekt je o něco málo starší, nemýlím-li se.

Mimochodem, v PHP již nějakou dobu dělám, bohužel mi Nette přijde relativně těžké, asi je to nezvyk používat frameworky, mimo jQuery jsem nic moc nepoužíval. Mohl by jsi mi nějak v krátkosti vysvětlit jak fungují ty „vlastní třídy“ které si vytvořím do Modules a později registruji v config.neon? Není lepší psát přímo do jednotlivých presenterů, než si vytvářet další třídy?

Děkuji mnohokrát za pomoct a za trpělivost,.. :)

reagovat

Peter Láng před 3 lety

Verzí Nette by to být nemělo, to jsem zkusil jako první – s aktuální verzí 2.0.10 to funguje beze změny.

Kde byla chyba těžko říct, musel bych vidět zdrojáky, když to někam hodíš, klidně třeba třeba na ten github, ze zvědavosti na to mrknu. Nebo se zeptej na Nette fóru.

Jinak Nette mi těžký nepřijde, je to určitě jen nezvyk a necvik. Chce si to udělat tři čtyři cvičný projekty a ono to sepne. „Vlastní třídy“ do Modelu (ne Modules), si píšeš mimojiné proto, abys je měl na jednom místě, když to budeš psát do presenterů, bude časem určitě stejná, nebo hodně podobná, funkcionalita na víc místech a zcvokneš z toho ;-)

reagovat

Wyatte před 3 lety

Ahoj, tak snad problémy jsem vyřešil, netuším přesně kde, jelikož jsem to zkoušel znovu a šlo mi to, možná jsem někde udělal nějakou chybičku v syntaxi, nebo nevím. Každopádně bych měl ještě jeden dotaz.

V současnosti se zkouším ještě učit přímo z dokumentace Nette, kde je příklad na komunikaci s DB (nevím, zdali jsi se tam na to díval), jsou tam 3 tabulky, user, task, list. V tabulce task jsou věci jako text, datum, atd. a je tam ještě user_id, což je cizí klíč, cizí ID pro tabulku user. A Nette by prý mělo v těhle případech vědět o tom, že je to cizí klíč a mělo by se to provázat. Takže ve výpisu v šabloně je tohle:

{foreach $tasks as $task} <tr>
<td>{$task->created|date:‚j. n. Y‘}</td>
<td>{$task->text}</td>
<td>{$task->user->name}</td> </tr>
{/foreach}

Created a text jsou přímo názvy sloupečků v tabulce task. No a {$task->user->name} by mělo přímo vstoupit do tabulky user a zvolit si ID a jeho atribut name. Tak je to i psáno v dokumentaci, ale prostě mi to nefunguje. Laděnka mi píše: Cannot read an undeclared column „user“. Vím, co ta chyba znamená, ale dle toho, co tam psali by to Nette mělo řešit nějak samo,.. ten vstup do jiných tabulek přes cizí klíče.

Díky

reagovat

Peter Láng před 3 lety

Takhle z hlavy mě napadá jestli máš v databázi nadefinovaný ty cizí klíče? Jinak tam je myslím použitá Nette\Database\ což v podstatě neznám.

reagovat

Wyatte před 3 lety

Ano, používá se tam Nette\Database\, ty používáš jenom dibi? Já jsem právně nad tím přemýšlel,.. a proč používat jiný,.. „framework“ nebo jak to nazvat, pro práci s MySQL, když Nette má rovnou integrovaný?

Každopádně ono se dá v PhpMyAdmin nějak přímo v MySQL nadefinovat že daný klíč je cizí? ^-^ v praxi jsem to tedy přímo takhle nikdy nepoužil, tak nevím. Vždy označuji pouze primární.

reagovat

Peter Láng před 3 lety

Používám dibi z už dlouho, celkem mi vyhovuje, Nette\Database\ byl ještě nedávno ve vývoji, teprve nedávno se, pokud se nepletu, usadilo, takže na to nespěchám.

Cizí klíče v PhpMyAdminu určitě půjdou nadefinovat, ale to už si dohledáš ;-)

reagovat

Wyatte před 3 lety

Tak jsem to odhalil,.. x)) Cizí klíče jsem psal dobře, ale problém byl v tom, že na endoře je defaultní MylSAM db a na cizí klíče (se kterými nette pracuje docela často) je třeba InnoDB, to mě nedošlo. A k tomu, abych si to na endoře vytvořil je třeba placený účet,..:) Skvělé,.. :) Prosím Tě nemohl by jsi mi poradit nějaký localhostový server? Já používal Vertrigo, ale slyšel jsem, že je to zlehounka zastaralé a už se moc nepoužívá.

Ještě jednu otázečku, když už píšu. K čemu je přesně metoda, většinou typu protected, startup(), ve které se po té volá parent::startup();

To startup tuším je prostě metoda, která se zavolá hned při startu dané třídy, nebo jak to mám chápat? Tím pádem by ale měla podobnou funkci jako konstruktor, nebo ne? A k čemu je tedy ten příkaz parent::startup()? Něco ve s tylu, použít rodičovskou třídu a její metodu startup(),…?? x))

Děkuji Ti moc.

reagovat

Jarek před 3 lety

Nevíte proč mi to píše Class ‚DibiNetteExten­sion‘ not found?

NEON:

common:
parameters:

php:
date.timezone: Europe/Prague
# zlib.output_com­pression: yes

nette:
application:
errorPresenter: Error

database:
dsn: ‚mysql:host=lo­calhost;dbname=tes­t‘
user:
password:

session:
expiration: 14 days

services:
users:
class: \Users(@dibi.con­nection)
factories:

production < common:

development < common:
dibi:
host: localhost
username: root
password:
database: users
lazy: TRUE

BOOTSTRAP:

<?php

/**
 * My Application bootstrap file.
 */
use Nette\Application\Routers\Route;


// Load Nette Framework or autoloader generated by Composer
require LIBS_DIR . '/autoload.php';


// Configure application
$configurator = new Nette\Config\Configurator;

// Enable Nette Debugger for error visualisation &amp; logging
//$configurator->setDebugMode($configurator::AUTO);
$configurator->enableDebugger(__DIR__ . '/../log');

// Enable RobotLoader - this will load all classes automatically
$configurator->setTempDirectory(__DIR__ . '/../temp');
$configurator->createRobotLoader()
        ->addDirectory(APP_DIR)
        ->addDirectory(LIBS_DIR)
        ->register();

// Create Dependency Injection container from config.neon file
$configurator->addConfig(__DIR__ . '/config/config.neon');



$configurator->onCompile[] = function ($configurator, $compiler) {
    $compiler->addExtension('dibi', new DibiNetteExtension);
};

$container = $configurator->createContainer();

// Setup router
$container->router[] = new Route('index.php', 'Homepage:default', Route::ONE_WAY);
$container->router[] = new Route('<presenter>/<action>[/<id>]', 'Homepage:default');


// Configure and run the application!
$container->application->run();
reagovat

Peter Láng před 3 lety

Takhle z hlavy mě napadá:

  • zkontrolovat jestli se v /libs nachází dibi, případně vyzkoušet různé verze dibi
  • smazat obsah /temp a refresh
  • zkontrolovat index.php a bootstrap oproti skutečným cestám, jestli to sedí
reagovat

Peter Láng před 3 lety

Ještě jsem na to koukl a možná bude problém, že nemáš v /libs/dibi „extension“ pro Nette. Mělo by to být součástí stažené distribuce dibi – aktuálně v dibi/bridges/Net­te.

Ten adresář šoupni do /libs/dibi/, smaž cache, refresh a dej vědět jestli pomohlo ;-)

Jenom bacha na to, že se to nemusí jmenovat DibiNetteExtension ale koukám že aktuálně je to DibiNette20Ex­tension. Tak to je potřeba upravit v bootstrapu samozřejmě.

reagovat

BUSINESS GOLDEN GROUP Ltd. před 2 lety

Hledáme touto cestou správce serveru, který je v programu NETTE. Pokud možno Zlínský kraj, není podmínkou.Stálá spolupráce. kontakt na 777315470 nebo na email :autoinzerent@gmail.com

reagovat

Přidat komentář

  • Můžete použít Texy syntaxi, HTML není povoleno
  • Například: *kurzíva*, **tučně**, "text odkazu":adresa