Začínáme se Zend Framework 1.0

Aktualizovaná verze pro Zend Framework 1.5 využívají nových komponent Zend_Layout a Zend_Form je od 2.6.2008 k dispozici na http://blog.pari.cz/…framework-15 !!!

Tento dokument se v anglickém originále nachází na stránkách Akra's DevNotes – Getting Started with the Zend Framework. Sepsal ho Rob Allen. Překlad byl sepsán krátce po vyjití Zend Framework verze 1.0 (25.8.2008). V současné době je na světě Zend Framework 1.5 a Rob Allen aktualizoval jeho článek Getting Started with the Zend Framework 1.5.

Verze Zend Framework Poslední aktualizace
1.4.4 1.0 a novější 6.4.2008

Tento tutoriál byl vytvořen proto, aby vám poskytl základní představu o použití Zend Framework. Jeho využití si budeme demonstrovat na základní aplikaci využívající databázi.

Tento tutoriál byl vytvořen a otestován na Zend Frameworku ve verzi 1.0.0. Je pravděpodobné, že bude fungovat i na novějších verzích. Je ale nepravděpodobné, že bude fungovat na verzi nižší.

MVC (Model-View-Controller) architektura aplikace

Tradiční způsob tvorby PHP aplikací je asi takový:
<?php
include "common-libs.php";
include "config.php";
mysql_connect($hostname, $username, $password);
mysql_select_db($database);
?>

<?php include "header.php"; ?>
<h1>Home Page</h1>

<?php
$sql = "SELECT * FROM news";
$result = mysql_query($sql);
?>
<table>
<?php
while ($row = mysql_fetch_assoc($result)) {
?>
<tr>
 <td><?php echo $row['date_created']; ?></td>
 <td><?php echo $row['title']; ?></td>
</tr>
<?php
}
?>
</table>
<?php include "footer.php"; ?>

Během vývoje aplikace ale dojdeme k závěru, že tento postup je neefektivní, pokud vytváříme nějaké změny. Tyto změny navíc musí být provedeny v různých dokumentech.

Jednou z možností, jak si vývoj aplikace usnadnit je rozdělit kód na stránce do 3 různých částí (a většinou i samostatných souborů):

Model Model je část aplikace, která je zodpovědná za výběr dat, která budou zobrazena. Na příkladu uvedeném o pář řádku výše by se jednalo o výběr novinek z databáze a jejich uložení do pole.
View View se stará o způsob, jakým jsou data prezentována uživateli. Nejčastěji se tedy jedná o HTML.
Controller Controller se stará o vytvoření modelu a zároveň volá správný view.

Zend Framework využívá MVC (Model-View-Controller) architekturu. Ta se používá pro oddělení rozdílných částí aplikace a tím také snažší vývoj a údržbu.

Požadavky

Zend Framework požaduje:
  • PHP 5.1.4 (a novější)
  • Webový server podporující mod_rewrite. V tomto tutoriálu je použit Apache.

Začínáme se Zend Framework

Zend Framework si můžete stáhnout ze stránek http://framework.zend.com/download ve formátu .zip nebo .tar.gz.

Adresářová struktura

Zend Framework vám nenařizuje striktně používat jednotnou strukturu aplikace, ale je doporučené držet se navrhované struktury v manuálu. Ta počítá s tím, že máte plnou kontrolu nad konfigurací webového serveru (Apache). Nicméně pro náš tutoriál si strukturu trochu zjednodušíme.

Začneme vytvořením adresáře zf-tutorial v kořenovém adresáři webového serveru (Apache). To znamená, že URL námi vytvořené aplikace bude dostupné na adrese http://localhost/zf-tutorial.

Vytvořte následující podadresáře:

zf-tutorial/
   /application
      /controllers
      /models
      /views
         /filters
         /helpers
         /scripts
   /library
   /public
      /images
      /scripts
      /styles
 

Jak vidíte, vytvořili jsme rozdílné adresáře pro model, view a controller soubory naší aplikace. Podporované obrázky, skripty a CSS soubory jsou uloženy ve zvláštních adresářích ve složce public. Soubory Zend Framework budou uloženy v adresáři library. Pokud budeme potřebovat nějaké další knihovny, je vhodné umístit je zde.

Rozbalte soubory z archivu ZendFramework-1.0.0.zip do dočasné složky. Všechny soubory jsou umístěny v podadresáři ZendFramework-1.0.0. Zkopírujte obsah adresáře library/Zend do zf-tutorial/library/. V adresáři zf-tutorial/library/ tedy budete mít podadresář Zend.

Bootstrap

Zend Framework a jeho controller Zend_Controller byl vytvořen tak, aby podporoval hezká URL. Pokud tohoto chcete dosáhnout, musí jít veškeré požadavky na aplikaci přes soubor index.php, kterému se říká bootstrap soubor. Veškeré požadavky tedy budou přesměrovány na tento soubor pomocí souboru .htaccess v adresáři zf-tutorial:

zf-tutorial/.htaccess

RewriteEngine on
RewriteRule .* index.php

php_flag magic_quotes_gpc off
php_flag register_globals off

Pravidlo RewriteRule je velmi jednoduché a slovně ho lze vyjádřit „vezmi jakoukoliv URL a přesměruj na index.php“.

Také definujeme několik PHP ini nastavení kvůli bezpečnosti. Tyto parametry jsou pravděpodobně již nastaveny, ale my se potřebujeme ujistit, že tomu skutečně tak je. Poznámka: php_flag nastavení v souboru .htaccess funguje pouze pokud používáte mod_php. Pokud používáte CGI/FastCGI, budete muset nastavení provést v konfiguračním souboru php.ini.

Nesmíme opomenout, že obrázky, skripty a CSS soubory nemohou být přesměrovány na bootstrap soubor. Proto všechny tyto soubory musíme umístit do příslušných podadresářů ve složce public. Webovému serveru (Apache) jednoduše nařídíme v .htaccess souboru:

zf-tutorial/public/.htaccess

RewriteEngine off

Není to nezbytné, ale z bezpečnostních důvodů můžeme přidat ještě několik .htaccess souborů, aby jsme se ujistili, že naše aplikace a její knihovny jsou chráněny:

zf-tutorial/application/.htaccess

deny from all

zf-tutorial/library/.htaccess

deny from all

Nezapomínejte, že soubory .htaccess používá webový server Apache a v nastavení serveru (soubor httpd.conf) musí být direktivita AllowOverride nastavena na all. Původní nápad s použítím více .htaccess souborů pochází z článku od Jaysona Minarda – Blueprint for PHP Applications: Bootstrapping (Part 2). Doporučuji Vám přečíst si i první část.

Bootstrap soubor: index.php

zf-tutorial/index.php je náš bootstrap soubor a my nyní začneme s následujícím kódem:

zf-tutorial/index.php

<?php
error_reporting(E_ALL|E_STRICT);
date_default_timezone_set('Europe/London');

set_include_path('.' . PATH_SEPARATOR . './library'
 . PATH_SEPARATOR . './application/models/'
     . PATH_SEPARATOR . get_include_path());
include "Zend/Loader.php";

Zend_Loader::loadClass('Zend_Controller_Front');

// setup controller
$frontController = Zend_Controller_Front::getInstance();
$frontController->throwExceptions(true);
$frontController->setControllerDirectory('./application/controllers');

// run!
$frontController->dispatch();

Určitě jste si všimli, že na konci souboru chybí ?>. Uzavření není potřeba a dokážeme jejím vynecháním předejít mnoha složitě odhalitelných chyb pokud používáme přesměrování přes header() a na konci souboru se vyskytuje „prázdné místo“.

Pojďme si projít soubor index.php

error_reporting(E_ALL|E_STRICT);
date_default_timezone_set('Europe/London');

Tyto řádky slouží k tomu, že budeme informováni o všech chybách, které ať už úmyslně nebo neúmyslně vytvoříme (direktivita display_errors musí být nastavena na on v souboru php.ini). Také zvolíme naše časové pásmo, jak požaduje specifikace PHP 5.1+.

set_include_path('.' . PATH_SEPARATOR . './library' . PATH_SEPARATOR .
'./application/models/' . PATH_SEPARATOR . get_include_path());
include "Zend/Loader.php";

Zend Framework je koncipován tak, že cesty k jeho souborům musí být definovány v include_path. Pro usnadnění si do include_path přidáme i cestu k model, takže budou naše třídy později snadno dostupné. Jako první připojíme soubor Zend/Loader.php, který nám spřístupní třídu Zend_Loader. Ta obsahuje nezbytné statické funkce pro nahrání dalších Zend Framework tříd.

Zend_Loader::loadClass('Zend_Controller_Front');

Zend_Loader::loadClass nahraje zadanou třídu. Toho je dosaženo tím, že název třídy obsahuje cestu k dané třídě. Podtržítko symbolizuje podadresář a na konec je přidána přípona .php. Z názvu třídy Zend_Controller_Front dostaneme následující cestu k třídě Zend/Controller/Front.php. Pokud budete dodržovat doporučený postup pojmenování, můžete vaše třídy také nahrávat přes Zend_Loader::loadClass. První třída, kterou potřebujeme, je front controller.

Front controller používá třídu router pro analýzu URL a vytvoření cesty k funkci, která zobrazí správnou stránku. Aby mohla třída router správně analyzovat URL, musí vědět, která část URL vede k index.php a od tohoto místa začít. Za normálních okolností by měl Request object zjistit umístění souboru index.php sám. V některých případech je ale potřeba tuto cestu manuálně nastavit $frontController->setBaseUrl().

Nyní musíme nakonfigurovat front controller tak, aby věděl, kde máme umístěny naše controllers.

$frontController = Zend_Controller_Front::getInstance();
$frontController->setControllerDirectory('./application/controllers');
$frontController->throwExceptions(true);

Protože se jedná pouze o ukázkovou aplikaci, nastavíme front controller tak, aby se zobrazovaly veškeré vyjímky. Defaultně front controller vyjímky zachytí a uloží v objektu „Response“ a proměnné _exceptions. Objekt dále uloží informace o okolnostech, které k vyjímce vedly jako je HTTP hlavička, obsah stránky a vyjímky. Front controller pošle hlavičku a obsah stránky až nakonec, takže se veškeré vyjímky zobrazí hned nahoře stránky. Nicméně na produkčním serveru by uživatel nikdy neměl žádnou vyjímku spatřit!

Nakonec se dostaneme k tomu hlavnímu – aplikaci spustíme:

// run!
$frontController->dispatch();

Pokud nyní načtete stránku http://localhost/zf-tutorial pravděpodobně se vám zobrazí podobná chyba: Fatal error: Uncaught exception ‚Zend_Controller_Dispatcher_Exception‘ with message ‚Invalid controller specified (index)‘ in…

Tato chyba se nám zobrazuje z důvodu toho, že jsme ještě neprovedli veškeré potřebné nastavení aplikace. Nejdříve si ale popíšeme to, co bude naše aplikace vlastně dělat.

Webová stránka

Naše aplikace bude fungovat jako organizér naší sbírky CD. Na hlavní stránce bude zobrazen obsah naší sbírky, a také možnost přidání, editace nebo smazání jednotlivých položek. Pro uložení dat o naší sbírce využijeme databázi, která bude obsahovat tabulku album s následující strukturou:
Sloupec Typ Nulový Poznámka
id Integer Ne Primary key, Autoincrement
artist Varchar(100) Ne  
title Varchar (100) Ne  

Jednotlivé stránky

Home page Na hlavní stránce se zobrazí obsah naší sbírky spolu s odkazy na přidání, editaci nebo smazání jednotlivých položek.
Add New Album Tato stránka bude obsahovat formulář pro přidání nového alba.
Edit Album Tato stránka bude obsahovat formulář pro editaci alba.
Delete Album Na této stránce potvrdíte, jestli opravdu chcete album smazat.

Umístění jednotlivých stránek

Ještě předtím než začneme vytvářet jednotlivé soubory, je důležité, aby jste pochopili, kde framework bude hledat vaše soubory a proč. Každá stránka se nazývá „action“ a actions jsou sdruženy do „controllers“. Když tedy budeme chtít zobrazit stránku http://localhost/…al/news/view tak pro nás controller bude news a action view. To nám umožňuje sdružovat podobné actions. Například controller news může mít action current, archived a view. Zend Framework a jeho MVC struktura také podporuje moduly, které nám zase umožňují sdružovat controllers dohromady. Tato aplikace ale pro toto použítí není dostatečně rozsáhlá.

Zend Framework a jeho controller obsahuje speciální action nazvanou index která je použita jako výchozí. To znamená, že pro URL http://localhost/…torial/news/ je controller news a action index. Jak už možná tušíte, Zend Framework obsahuje i výchozí controller, který je opět nazvaný index. Pokud tedy zadáte URL http://localhost/zf-tutorial/ jako controller se použije index a jako action také index.

Protože se jedná o základní tutoriál, nebudeme u aplikace zacházet do takových detailů, jako je přihlašování a odhlašování uživatelů.

Máme tedy čtyři stránky, které pracují s naší aplikací pro organizování CD. Bude tedy vhodné sdružit je do jediného controlleru a čtyř action. Použijeme výchozí controller index a následující actions:

Stránka Controller Action
Home page Index Index
Add New Album Index Add
Edit Album Index Edit
Delete Album Index Delete

Nastavujeme Controller

V Zend Frameworku je controller třída a musí být nazvána {název Controlleru}Controller. {název Controlleru} musí začínat velkým písmenem. Tento controller musí být uložen v souboru nazvaném {název Controlleru}Controller.php uvnitř adresáře určeného pro controllery. Nezapomeňte na to, že první písmeno musí být velké a ostatní malá! Každá action je public function, kterou obsahuje třída controller. Akce musí být pojmenována {název action}Action. Pro název action používáme hned od začátku malá písmena.

Nyní již máme vytvořenou třídu IndexController, která je uložena v souboru zf-tutorial/application/controllers/IndexController.php:

zf-tutorial/application/controllers/IndexController.php

<?php

class IndexController extends Zend_Controller_Action
{
    function indexAction()
    {
    }

    function addAction()
    {
    }

    function editAction()
    {
    }

    function deleteAction()
    {
    }
}

Nyní jsme vytvořili čtyři akce, které zatím nebudou fungovat. Musíme jim definovat views.

URL pro jednotlivé akce jsou:

URL * Action
http://localhost/zf-tutorial/ IndexController::indexAction()
http://localhost/…al/index/add IndexController::addAction()
http://localhost/…l/index/edit IndexController::editAction()
http://localhost/…index/delete IndexController::deleteAction()

Nyní je ten správný čas, pro vytvoření views.

Nastavujeme Views

Komponenta view Zend Frameworku je nazvána vcelku logicky Zend_View. Ta nám umožňuje oddělit kód, který se stará o zobrazení stránky (nejčastěji HTML) od kódu v příslušné action a tím aplikaci spřehlednit.

Základní použití Zend_View je následující:

$view = new Zend_View();
$view->setScriptPath('/path/to/view_files');
echo $view->render('view.php');

Tento kód bychom jednoduše mohli umístit do každé action, bylo by to ale zbytečné. Mnohem lepší je inicializovat třídu view někde jinde a v action jen přistupovat na objekt třídy view. Vývojáři Zend Framework to vyřešili tím, že vytvořili tzv. „action helper“. Zend_Controller_Action_Helper_ViewRenderer se nám tedy postárá o inicializaci objektu view($this->view) a zároveň vygeneruje view skript. Dále nastaví objektu Zend_View cestu k view skriptu views/scripts/{controller name}. Tento se ve výchozím nastavení nachází views/scripts/{controller name}/{action_name}.phtml. Výsledný obsah stránky je přidán do objektu Response. Objekt Response sdružuje všechny HTTP hlavičky, obsah body a vyjímky vzniklé použítím MVC. Front Controller poté automaticky pošle hlavičku a obsah body na konci dispatchingu.

Nejprve si naplníme actions:

zf-tutorial/application/controllers/IndexController.php

<?php

class IndexController extends Zend_Controller_Action
{
    function indexAction()
    {
        $this->view->title = "My Albums";
    }

    function addAction()
    {
        $this->view->title = "Add New Album";
    }

    function editAction()
    {
        $this->view->title = "Edit Album";
    }

    function deleteAction()
    {
        $this->view->title = "Delete Album";
    }
}

V každé funkci jsme přiřadili proměnnou title objektu view. Nezapomínejte na to, že tento text se zobrazí teprve až projde přes Front Controller na konci procesu nazvaném dispatching, který se volá až na úplném konci běhu aplikace.

Nyní potřebujeme vytvořit view soubory pro naší aplikaci. Tyto soubory můžeme také nazvat šablony. Metoda render() očekává, že šablony jsou pojmenovány podle přidružených akcí s koncovkou .phtml. Soubory musí být umístěny v podadresáři, který je pojmenován podle controlleru.

zf-tutorial/application/views/scripts/index/index.phtml

<html>
<head>
 <title><?php echo $this->escape($this->title); ?></title>
</head>
<body>
 <h1><?php echo $this->escape($this->title); ?></h1>
</body>
</html>

zf-tutorial/application/views/scripts/index/add.phtml

<html>
<head>
 <title><?php echo $this->escape($this->title); ?></title>
</head>
<body>
 <h1><?php echo $this->escape($this->title); ?></h1>
</body>
</html>

zf-tutorial/application/views/scripts/index/edit.phtml

<html>
<head>
 <title><?php echo $this->escape($this->title); ?></title>
</head>
<body>
 <h1><?php echo $this->escape($this->title); ?></h1>
</body>
</html>

zf-tutorial/application/views/scripts/index/delete.phtml

<html>
<head>
 <title><?php echo $this->escape($this->title); ?></title>
</head>
<body>
 <h1><?php echo $this->escape($this->title); ?></h1>
</body>
</html>

Pokud nyní otestujete jednotlivé controller/action (jednotlivá URL v tabulce o fous výše), měli by zobrazit title definované v controlleru a přidružené action.

Obyčejný HTML kód

Jednotlivé views obsahují především HTML kód. Protože ale nechceme psát některé jeho části stále dokola v každém souboru zvlášt, vytvoříme si dva soubory ve složce scripts nazvané header.phtml a footer.phtml. Tyto soubory potom připojíme v jednotlivých šablonách.

zf-tutorial/application/views/scripts/header.phtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
 <title><?php echo $this->escape($this->title); ?></title>
</head>
<body>
<div id="content">

zf-tutorial/application/views/scripts/footer.phtml

</div>
</body>
</html>

Naše view soubory potřebují drobnou úpravu:

zf-tutorial/application/views/scripts/index/index.phtml

<?php echo $this->render('header.phtml'); ?>
<h1><?php echo $this->escape($this->title); ?></h1>
<?php echo $this->render('footer.phtml'); ?>

zf-tutorial/application/views/scripts/index/add.phtml

<?php echo $this->render('header.phtml'); ?>
<h1><?php echo $this->escape($this->title); ?></h1>
<?php echo $this->render('footer.phtml'); ?>

zf-tutorial/application/views/scripts/index/edit.phtml

<?php echo $this->render('header.phtml'); ?>
<h1><?php echo $this->escape($this->title); ?></h1>
<?php echo $this->render('footer.phtml'); ?>

zf-tutorial/application/views/scripts/index/delete.phtml

<?php echo $this->render('header.phtml'); ?>
<h1><?php echo $this->escape($this->title); ?></h1>
<?php echo $this->render('footer.phtml'); ?>

Stylování

Sice se jedná pouze o tutoriál, ale neodpoustil jsem si malé grafické vylepšení aplikace pomocí css. Na tomto příkladu si můžeme zároveň ukázat, jak odkazovat na externí soubory. Využijeme funkce getBaseUrl().

Použijeme funkci IndexController::init(). Tato funkce je zvláštní tím, že je volána přímo construktorem, a tak je jsou její objekty přístupné ve všech actions.

zf-tutorial/application/controllers/IndexController.php

...
class IndexController extends Zend_Controller_Action
{
    function init()
    {
        $this->view->baseUrl = $this->_request->getBaseUrl();
    }

    function indexAction()
    {
...
CSS soubor musíme připojit v header.phtml:

zf-tutorial/application/views/scripts/header.phtml

...
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
    <title><?php echo $this->escape($this->title); ?></title>
    <link rel="stylesheet" type="text/css" media="screen" href="<?php echo $this->baseUrl;?>/public/styles/site.css" />
</head>
...

A nakonec zbývá pár CSS stylů:

zf-tutorial/public/styles/site.css

body,html {
 font-size:100%;
 margin: 0;
 font-family: Verdana,Arial,Helvetica,sans-serif;
 color: #000;
 background-color: #fff;
}

h1 {
 font-size:1.4em;
 color: #800000;
 background-color: transparent;
}

#content {
 width: 770px;
 margin: 0 auto;
}

label {
 width: 100px;
 display: block;
 float: left;
}

#formbutton {
 margin-left: 100px;
}

a {
 color: #800000;
}

No nevypadá to mnohem lépe?

Databáze

Nyní, když jsme oddělili ovládání aplikace a zobrazení použitím views se vrhneme na model. Opakování je matka moudrosti, takže model ja ta část aplikace, která má na starost data. Je to objekt(kolekce objektů), který je volán ve view. V naší aplikaci bude tedy pracovat s databází. K tomu použijeme třídu Zend_Db_Table, která má v Zend Framework na starost práci s databází.

Nastavení

Nyní provedeme konfiguraci třídy Zend_Db_Table. Třídě musíme nastavit typ databáze, který použijeme(MySQL) a přihlašovací údaje do databáze. Na tomto příkladu si ukážeme použití další třídy přímo ze Zend Framework – Zend_Config. Ta nám rychle objektově spřístupní veškeré konfigurační soubory. Konfigurační soubor může být buď INI nebo XML. My použijeme INI.

zf-tutorial/application/config.ini

[general]
db.adapter = PDO_MYSQL
db.config.host = localhost

db.config.username = rob
db.config.password = 123456
db.config.dbname = zftest

Nezapomeňte použít vaše vlastní přihlašovací údaje do databáze!

Použítí Zend_Config je následně velmi jednoduché:

$config = new Zend_Config_Ini('config.ini', 'section');

V této konfiguraci Zend_Config_Ini načte pouze jednu sekci s názvem section(naše sekce má název general). Dále je také podporováno použití poznámky u jména section, pomocí které můžeme načíst další section. Pro oddělení hiearchické struktury se používá tečka, což znamená že podobné direktivity můžeme sdružit. V našem příkladě bude host, username, password a dbname sdruženo pod objekt $config->db->config.

A kam umístit načtení třídy Zend_Config? No přece do bootstrap souboru(index.php):

zf-tutorial/index.php

...
Zend_Loader::loadClass('Zend_Controller_Front');
Zend_Loader::loadClass('Zend_Config_Ini');
Zend_Loader::loadClass('Zend_Registry');

// load configuration
$config = new Zend_Config_Ini('./application/config.ini', 'general');
$registry = Zend_Registry::getInstance();
$registry->set('config', $config);

// setup controller
...

Nejprve načteme třídy, které budeme potřebovat – Zend_Registry a Zend_Config_Ini. Jako parametr pro třídu Zend_Config_Ini použijeme cestu k souboru config.ini a jako název section general čímž vše načteme do objektu $config. Nakonec objekt $config přiřadíme do objektu $registry s pomocí třídy Zend_Registry a to z důvodu toho, že nyní budeme mít ke konfiguraci přístup v celé aplikaci.

Poznámka: V této ukázkové aplikaci je zbytečné, aby přihlašovací údaje do databáze byly globálně přístupné. Můžeme si tak ale demonstrovat případ, kdy bude konfigurační soubor obsah mnohem více nastavení, ke kterému budeme potřebovat přístupovat v celé aplikaci.

Nastavujeme Zend_Db_Table

Pro použití Zend_Db_Table potřebujeme nejdříve předat konfigurační údaje, které jsme právě načetli do registry. Nejdříve vytvoříme instanci Zend_Db a pak vše přiřadíme statickou funkcí Zend_Db_Table:: setDefaultAdapter(). Tohle všechno opět provedeme v boostrap souboru(index.php):

zf-tutorial/index.php

...
Zend_Loader::loadClass('Zend_Controller_Front');
Zend_Loader::loadClass('Zend_Config_Ini');
Zend_Loader::loadClass('Zend_Registry');
Zend_Loader::loadClass('Zend_Db');
Zend_Loader::loadClass('Zend_Db_Table');

// load configuration
$config = new Zend_Config_Ini('./application/config.ini', 'general');
$registry = Zend_Registry::getInstance();
$registry->set('config', $config);

// setup database
$db = Zend_Db::factory($config->db->adapter,
$config->db->config->toArray());
Zend_Db_Table::setDefaultAdapter($db);

// setup controller
...

Vytvoříme tabulku

Nejdříve vytvoříme, pokud jste ještě tak neučinili, databázi zftest. Pak v ní tabulku album například pomocí aplikace PhpMyAdmin.
CREATE TABLE album (
  id int(11) NOT NULL auto_increment,
  artist varchar(100) NOT NULL,
  title varchar(100) NOT NULL,
  PRIMARY KEY (id)
);

Naplníme tabulku

Do tabulky si vložíme několik položek. Můžeme třeba použít první dvě z Hot 100” CDs from Amazon.co.uk.
INSERT INTO album (artist, title)
VALUES
('James Morrison', 'Undiscovered'),
('Snow Patrol', 'Eyes Open');

Model

Zend_Db_Table je abstraktní třída, musíme ji tedy rozšířit tak, aby pracovala s naší vzorovou aplikací. Vytvoříme si tedy třídu pojmenovanou Album podle názvu tabulky v databázi. Třídě Zend_Db_Table nastavíme protected proměnnou $_name, která bude obsahovat název tabulky. Zend_Db_Table počítá s tím, že primární klíč je pojmenován id a má hodnotu auto increment. Sloupec s primárním klíčem si ale můžete pojmenovat i podle sebe, jen to název musíte předat tříde Zend_Db_Table.

Naši třídu Album tedy uložíme v adresáři určeném pro models:

zf-tutorial/application/models/Album.php

<?php

class Album extends Zend_Db_Table
{
    protected $_name = 'album';
}

Nebylo to moc težké viďte. Pro naši jednoduchou aplikaci nepotřebujeme třídu více rozšiřovat. Pokud budete mít nějaké další plány s modelem, je tohle to pravé místo, kde tak učinit.

Výpis alb

Nyní se konečně dostáváme k cíli naší aplikace a zobrazíme si výpis alb. To provedeme v třídě IndexController.

Každá akce pracující s třídou IndexController bude pracovat s tabulkou album pomocí třídy Album. Nejefektivnější bude tedy tuto třídu načíst při incializaci controlleru což provedeme ve funkci init():

zf-tutorial/application/controllers /IndexController.php

...
    function init()
    {
        $this->view->baseUrl = $this->_request->getBaseUrl();
        Zend_Loader::loadClass('Album');
    }
...

Poznámka: Tohle je příklad použití Zend_Loader::loadClass() pro načtení vlastních tříd. Funguje díky tomu, že cestu k models jsme přidali do include_path v souboru index.php.

Nastavíme výpis alb v action indexAction():

zf-tutorial/application/controllers/IndexController.php

...
function indexAction()
{
    $this->view->title = "My Albums";
    $album = new Album();
    $this->view->albums = $album->fetchAll();
}
...

Funkce Zend_Db_Table::fetchAll() vrací Zend_Db_Table_Rowset, která nám umožňuje vypsat všechny alba pomocí foreach cyklu.

zf-tutorial/application/views/scripts/index/index.phtml

<?php echo $this->render('header.phtml'); ?>
<h1><?php echo $this->escape($this->title); ?></h1>
<p><a href="<?php echo $this->baseUrl; ?>/index/add">Add new album</a></p>
<table>
<tr>
 <th>Title</th>
 <th>Artist</th>
 <th>&nbsp;</th>
</tr>

<?php foreach($this->albums as $album) : ?>
<tr>
 <td><?php echo $this->escape($album->title);?></td>
 <td><?php echo $this->escape($album->artist);?></td>
 <td>
   <a href="<?php echo $this->baseUrl; ?>/index/edit/id/<?php
      echo $album->id;?>">Edit</a>
  <a href="<?php echo $this->baseUrl; ?>/index/delete/id/<?php
      echo $album->id;?>">Delete</a>
 </td>
</tr>
<?php endforeach; ?>
</table>
<?php echo $this->render('footer.phtml'); ?>

Pokud jste udělali všechno přesně podle tutoriálu, na stránce http://localhost/zf-tutorial/ se vypíšou 2 alba.

Přidáváme nové album

Nyní se vrhneme na tvorbu obslužné části pro přidání nového alba. Ta má dvě části:
  • Vypíše se jednoduchý formulář pro přidání alba
  • Data od uživatele se uloží do databáze

Začneme úpravou addAction() v controlleru:

zf-tutorial/application/controllers/IndexController.php

...
function addAction()
{
    $this->view->title = "Add New Album";

    if ($this->_request->isPost()) {
        Zend_Loader::loadClass('Zend_Filter_StripTags');
        $filter = new Zend_Filter_StripTags();

        $artist = $filter->filter($this->_request->getPost('artist'));
        $artist = trim($artist);
        $title = trim($filter->filter($this->_request->getPost('title')));

        if ($artist != '' && $title != '') {
            $data = array(
       'artist' => $artist,
       'title'  => $title,
   );
   $album = new Album();
   $album->insert($data);

            $this->_redirect('/');
            return;
        }
    }

    // set up an "empty" album
    $album = new Album();
    $this->view->album = $album->createRow();

    // additional view fields required by form
    $this->view->action = 'add';
    $this->view->buttonText = 'Add';
}
...

Pro zjistění, zda-li byl formulář odeslán jsme použili metodu isPost(). Pokud ano, získáme z pole post potřebné údaje, které prověříme třídou Zend_Filter_StripTags, jestli neobsahuje nedovolené HTML. Jednoduchou podmínkou dále ověříme, jestli vůbec byly předány nějaká data. Pokud ano, inicializujeme naši třídu Album() a vložíme data do databáze.

Nakonec provedeme přesměrování na hlavní stránku pomocí metody _redirect() z controlleru.

Nejlehčí část jsme si nechali nakonec. Vytvoříme potřebné views. Formulář vložíme do zvláštního view, protože se nám bude později hodit pro editaci alba. Filisofie aplikace je taková, že nic nepíšeme zbytečně 2× či vícekrát.

Šablona pro přidání nového alba:

zf-tutorial/application/views/scripts/index/add.phtml

<?php echo $this->render('header.phtml'); ?>
<h1><?php echo $this->escape($this->title); ?></h1>
<?php echo $this->render('index/_form.phtml'); ?>
<?php echo $this->render('footer.phtml'); ?>

zf-tutorial/application/views/scripts/index/_form.phtml

<form action="<?php echo $this->baseUrl ?>/index/<?php
    echo $this->action; ?>" method="post">
<div>
    <label for="artist">Artist</label>
    <input type="text" name="artist"
        value="<?php echo $this->escape(trim($this->album->artist));?>"/>
</div>
<div>
    <label for="title">Title</label>
    <input type="text" name="title"
        value="<?php echo $this->escape($this->album->title);?>"/>
</div>

<div id="formbutton">
<input type="hidden" name="id" value="<?php echo $this->album->id; ?>" />
<input type="submit" name="add"
    value="<?php echo $this->escape($this->buttonText); ?>" />
</div>
</form>

Veškeré texty jsou dynamicky generované, takže není problém použít šablonu _form.phtml znovu pro editaci alba.

Editujeme album

Editování alba je velmi pobodné, takže ho nemusíme rozebírat:

zf-tutorial/application/controllers/IndexController.php

...
function editAction()
{
    $this->view->title = "Edit Album";
    $album = new Album();

    if ($this->_request->isPost()) {
        Zend_Loader::loadClass('Zend_Filter_StripTags');
        $filter = new Zend_Filter_StripTags();

        $id = (int)$this->_request->getPost('id');
        $artist = $filter->filter($this->_request->getPost('artist'));
        $artist = trim($artist);
        $title = trim($filter->filter($this->_request->getPost('title')));

        if ($id !== false) {
            if ($artist != '' && $title != '') {
                $data = array(
                    'artist' => $artist,
                    'title'  => $title,
                );
                $where = 'id = ' . $id;
                $album->update($data, $where);
                $this->_redirect('/');
                return;
            } else {
                $this->view->album = $album->fetchRow('id='.$id);
            }
        }
    } else {
        // album id should be $params['id']
        $id = (int)$this->_request->getParam('id', 0);
     if ($id > 0) {
         $this->view->album = $album->fetchRow('id='.$id);
     }
    }

    // additional view fields required by form
    $this->view->action = 'edit';
    $this->view->buttonText = 'Update';
}
...

Jen pro doplnění, pokud nejsme v post mode, tak se id získá přes objekt $this->_request->getParam().

Šablona pro editaci je následující:

zf-tutorial/application/views/scripts/index/edit.phtml

<?php echo $this->render('header.phtml'); ?>
<h1><?php echo $this->escape($this->title); ?></h1>
<?php echo $this->render('index/_form.phtml'); ?>
<?php echo $this->render('footer.phtml'); ?>

Zamyšlení

Nešlo by aplikaci napsat efektivněji? Podívejte se na addAction() a editAction(), spousta věcí je stejných. Zkuste to zjednodušit.

Mazání alb

Aby naše aplikace byla kompletní, musíme uživatelům umožnit alba smazat. Vedle výpisu každého alba se zobrazuje odkaz na editaci a smazání každé položky. Po kliknutí na tlačítko smazat se nejprve objeví potvrzovací stránka a až poté se položka definitivně smaže z databáze.

Kód deleteAction() vypadá zase obdobně jako u addAction() a editAction():

zf-tutorial/application/controllers/IndexController.php

...
function deleteAction()
{
    $this->view->title = "Delete Album";

    $album = new Album();
    if ($this->_request->isPost()) {
        Zend_Loader::loadClass('Zend_Filter_Alpha');
        $filter = new Zend_Filter_Alpha();
        $id = (int)$this->_request->getPost('id');
        $del = $filter->filter($this->_request->getPost('del'));

        if ($del == 'Yes' && $id > 0) {
            $where = 'id = ' . $id;
            $rows_affected = $album->delete($where);
        }
    } else {
        $id = (int)$this->_request->getParam('id');
        if ($id > 0) {
            // only render if we have an id and can find the album.
            $this->view->album = $album->fetchRow('id='.$id);

            if ($this->view->album->id > 0) {
                // render template automatically
                return;
            }
        }
    }

    // redirect back to the album list unless we have rendered the view
    $this->_redirect('/');
}
...

Zase použijeme stejný způsob ověření, zda-li byl formulář odeslán metodou isPost()a jestli máme zobrazit potvrzovací formulář nebo již položku definitivně smazat přes třídu Album(). Smazání položky, stejně jako vložení a editace probíhá přes třídu Zend_Db_Table::delete().

Šablona je jednoduchý formulář:

zf-tutorial/application/views/scripts/index/delete.phtml

<?php echo $this->render('header.phtml'); ?>
<h1><?php echo $this->escape($this->title); ?></h1>
<?php if ($this->album) :?>
<form action="<?php echo $this->baseUrl ?>/index/delete" method="post">
<p>Are you sure that you want to delete
  '<?php echo $this->escape($this->album->title); ?>' by
  '<?php echo $this->escape($this->album->artist); ?>'?
</p>
<div>
  <input type="hidden" name="id" value="<?php echo $this->album->id; ?>" />
  <input type="submit" name="del" value="Yes" />
  <input type="submit" name="del" value="No" />
</div>
</form>
<?php else: ?>
<p>Cannot find album.</p>
<?php endif;?>
<?php echo $this->render('footer.phtml'); ?>

Řešení problémů

Pokud máte problém s tím, že fungují všechny stránky kromě hlavní (index/index) je pravděpodobné, že router není schopen určit ve kterém podadresáři se nachází vaše aplikace. Trochu jsem pátral, proč tomu tak je a zjistil jsem, že se to stává, když URL na vaše stránky se liší od kořenového adresáře, kde je aplikace umístěna. Mělo by pomoct nastavit $baseUrl.

zf-tutorial/index.php

...
// setup controller
$frontController = Zend_Controller_Front::getInstance();
$frontController->throwExceptions(true);
$frontController->setBaseUrl('/mysubdir/zf-tutorial');
$frontController->setControllerDirectory('./application/controllers');
...

Nahraďte ‚/mysubdir/zf-tutorial/‘ správnou URL k index.php. Pokud je index.php dostupný na adrese http://localhost/…al/index.php ,pak správná hodnota $baseUrl je ‚/~ralle/zf-tutorial/‘.

Závěr

Tak a jsme na konci. Vytvořili jsme plně funkční jednoduchou aplikaci na správu alb založenou na MVC(model-view-controller) přístupu a Zend Framework. Doufám, že byl tento tutoriál pro vás užitečný. Pokud naleznete jakukoliv chybu v mém překladu, budu rád, když mi o tom dáte vědět, abych ji mohl opravit. Zároveň doporučuji, pokud umíte anglicky, přečíst si originál, protože můj překlad nemusí být zcela přesný. Je to můj první překlad takového rozsahu, tak mě hned neukamenujte.

Komentáře

  1. martin 03.10.07 13:41

    Comment Arrow

    Clanek je peknej, v sekci vypis alb akorat nemas zformatovany zdrojovy kod:

    zf-tutorial/application/controllers/IndexController.php /code--- php … function indexAction() { $this->view->title = „My Albums“; $album = new Album(); $this->view->albums = $album->fetchAll(); } … \---


  2. Pari 03.10.07 16:03

    Comment Arrow

    martin: opraveno, děkuji za připomínku.


  3. MilanK 04.10.07 08:57

    Comment Arrow

    Pěkně, pěkně… Jsem úplný začátečník, tak jsem něco podobného hledal. Co tady chybí oproti anglické verzi je samotný skript formuláře ‚_form.phtml‘

    <form action=„baseUrl ?>/index/action; ?>“ method=„post“>

    Artist
    <input type=„text“ name=„artist“
    value=„escape(trim($this->album->artist));?>“/>

    Title
    <input type=„text“ name=„title“
    value=„escape($this->album->title);?>“/>

    <input type=„hidden“ name=„id“ value=„album->id; ?>“ />
    <input type=„submit“ name=„add“
    value=„escape($this->buttonText); ?>“ />

    jinak dík moc dobré

    M.


  4. Moss 17.10.07 23:56

    Comment Arrow

    Brý večer, nemohl byste pls někdo rozvést „Poznámka: php_flag nastavení v souboru .htaccess funguje pouze pokud používáte mod_php. Pokud používáte CGI/FastCGI, budete muset nastavení provést v konfiguračním souboru php.ini.“
    Instalace Zendcore a Zendplatformy mi v httpd.conf udělala trochu bordel, zakomentovalo se mi automaticky #LoadModule php5_module „c:\dev\prog2\php5apache2_2.dll“
    A jede mi to ted celý na :
    LoadModule zend_enabler_module „C:/Program Files/Zend/Core/modules/apache2.2/zend_fcgi.dll“

    FastCgiConfig „C:/Program Files/Zend/Core/etc/fastcgi.conf“
    AddHandler fastcgi-script .php .php3 .phtml .inc
    AddType application/x-httpd-php .php .php3 .phtml .inc

    Order deny,allow
    Allow from all

    Alias /ZendCore „C:/Program Files/Zend/Core/GUI“

    Tim pádem mi nefungujou ty includy, zřejmě díky .htaccess
    Tzn. ze dřív jsem jel na mod_php a díky tomu zendu na fastCGI ?


  5. Moss 18.10.07 01:21

    Comment Arrow

    Debug Warning: C:\dev\www\zf-tutorial\index.php line 8 – include() [function.include]: Failed opening ‚Zend/Loader.php‘ for inclusion (include_path=‚.;./library;./application/models/;.;C:\Program Files\Zend\Core\ZendFramework-0.8.0‘)

    Debug Error: C:\dev\www\zf-tutorial\index.php line 10 – Class ‚Zend_Loader‘ not found

    Please help, sorry za amateřinu :) ale nejak nedokazu odstranit z include_path tu nesmyslnou cestu do Core, nebo nevim:)


  6. Moss 19.10.07 00:16

    Comment Arrow

    Jenom doplnim, ten ZendFramework-0.8.0 je ve skutečnosti 1.0.2, jen jsem tam nechal puvodni nazev adresare. Poslední větu beru z5 :)
    Loader už se mi includovat povedlo…ae ted mam to samy v Loaderu na řádce 158 " require_once ‚Zend/Exception.php‘; " zase nelze otevřít, failed opening…nechapu, cesta je tam nastavena dobře, php a apache jsem prošel 3× aby bylo všechno OK.


  7. Moss 19.10.07 00:39

    Comment Arrow

    O M G omg
    $Moss = ‚dement‘;
    echo „jsem $Moss“;
    Všechno OK, nebral to jenom debugger :-D
    Sranda musí bejt…


  8. Pari 19.10.07 08:09

    Comment Arrow

    Moss: Tak můžes zkusit cestu nastavit absolutně a pak z toho vycházet, kde se stala chyba. Jinak už „brzy“ vyjde knížka celá věnovaná Zend Frameworku(Zend Framework v akci href=„http://weblog.pari.cz/207/kniha-zend-framework-v-akci“ rel=„nofollow“>http://weblog.pari.cz/207/kniha-zend-framework-v-akci), konečně nějaký ucelený zdroj vědomostí.


  9. jooka 16.01.08 01:31

    Comment Arrow

    Díky za tutoriál. Ráno jsem nevěděl co to je Zend Framework a je a měl jsem něco předělávat. Tohle mi dost pomohlo.


  10. roast 18.02.08 00:51

    Comment Arrow

    Díky, perfektní překlad, moc mi to pomohlo.


  11. Radek 14.03.08 16:55

    Comment Arrow

    Ahoj, taky diky za bezva preklad.
    Napadlo me, co pouzit misto Zend_Loader::loadClass autoload ?
    A v autoloadu klidne pouzit Zend_Loader::loadClass :D ?
    Jenom se mi nechce vzdavat autoload funkcionality, kdyz mam pekne nastavenou include_path :)


  12. Besir 27.03.08 23:22

    Comment Arrow

    Zdravim všechny, sem asi hlupak ale mě to nefunguje. Chtěl bych Vás tedy někoho požádat jestli by se mi na to nepodíval, došel sem zatim ke kroku stylování, resp. před ním sem skončil, ale pořád mi to hází tu chybu error: Uncaught exception ‚Zend_Controller_Dispatcher_Exception‘ with message ‚Invalid controller specified (index)‘ in… takže sem asi někde něco nastavil špatně, dovolil sem si vytvořit zvláštní ftp přístup pro toho kdo by byl ochoten se na to podívat.
    host: http://ftp.savana.cz
    login: zf_tutorial
    pass: tutorial

    Byl bych Vám velmi vděčný. Případný kontakt na mě je:
    E-mail: besir@newdimensions.cz
    ICQ: 195–593–661


  13. suky 30.03.08 14:47

    Comment Arrow

    to Radek: taky jsem o tom premyslel, ale asi neni problem to trochu poupravit :D
    obecne: clanek se mi libil, zacal jsem hledat po vecim zdroji informaci okolo ZF a v cestine nic neni, myslim tim knizku, v anglictine bude az ZF in actin ale nechce se mi cekat =o( takze jsem nasel dalsi reseni, viz. http://www.galileocomputing.de/…titelID-1540 az si ji objednam, dam vedet, jestli za to stoji, ale co jsem koukal do obsahu, myslim, ze by se mela hodit…


  14. Mischa 31.03.08 08:00

    Comment Arrow

    Zdravim,
    mam maly problem … ja kdyz pouziju scripty a trochu je poupravim na svuj web … tak mi tam nefunfuje vubec $_POST … kdyz poslu formularem cokoliv … tak isPost() mi zareaguje ze POST byt z formulare odeslan … ale neobsahuje zadna tada … coz je velky problem. GET funguje bez problemu a vsechny promenne z nej vytahnu. Je nekdo schopen mi pomoci? Asi jsem blbej, ale proste obcas takovych par lidi taky existuje :o)

    ve view mam :
    <form action=„baseUrl ?>/whitelist/del/“ method=„POST“ enctype=„application/x-www-form-urlencoded“>
    Opravdu smazat ?

    <input type=„hidden“ name=„id“ value="">

    a v controllers:
    if ($this->_request->isPost()) {

    Zend_Loader::loadClass(‚Zend_Filter_Alpha‘);
    $filter = new Zend_Filter_Alpha();
    $id = (int)$this->_request->getPost(‚id‘);
    $del = $filter->filter($this->_request->getPost(‚del‘));
    if ($del == ‚Ano‘ && $id > 0) {

    $db->query(„DELETE FROM whitelist WHERE id = ?“, $_GET[„id“]);
    $this->_redirect(‚/whitelist‘);
    return;

    } else if ($del == ‚Ne‘) {
    $this->_redirect(‚/whitelist‘);
    return;
     }

    } else {
    $id = (int)$this->_request->getQuery(‚id‘);

    if ($id > 0) {
    $dotaz = $db->query(„SELECT * FROM whitelist WHERE id=?“, $id);
    $this->view->whitelist = $dotaz->fetchAll();
    }
     }

    Dekuju
    Mischa


  15. Pari 31.03.08 08:45

    Comment Arrow

    Pokud potrebujete radu, bude lepsi vas dotaz smerovat do fora http://forum.zendframework.cz/ , kde se pohybuje více kompetentních lidí, kteri vam dokazi odpovedet.


  16. snop 04.04.08 20:15

    Comment Arrow

    chybi ti tam zdrojak pro zf-tutorial/application/views/scripts/footer.phtml


  17. snop 04.04.08 20:21

    Comment Arrow

    v Adresářové strukture chyby odradkovani


  18. snop 04.04.08 20:26

    Comment Arrow

    escape($this->title); ?>
    Page 9 of 18

    <link rel=„stylesheet“ type=„text/css“ media=„screen“
    href=„baseUrl;?>/public/styles/site.css“ />

    nefim co tam dela Page 9 of 18


  19. snop 04.04.08 21:13

    Comment Arrow

    v configu uprav

    [general]
    db.adapter = PDO_MYSQL

    na

    [general]
    db.adapter = MYSQLi


  20. snop 04.04.08 21:27

    Comment Arrow

    v zdrojaku pod tymto textem mas chybu, je tam vlozeny form na jednem miste no vsak uvidis

    Nejlehčí část jsme si nechali nakonec. Vytvoříme potřebné views. Formulář vložíme do zvláštního view, protože se nám bude později hodit pro editaci alba. Filisofie aplikace je taková, že nic nepíšeme zbytečně 2× či vícekrát.

    Šablona pro přidání nového alba:

    zf-tutorial/application/views/scripts/index/add.phtml


  21. Pari 06.04.08 20:02

    Comment Arrow

    Klobouk dolů, jsem rád že se najdou takto pozorní čtenáři. Za chyby se omlouvám, občas se člověk diví, co všechno přehlédne. Díky moc, ale můžeš mi vysvětlit komentář #19? Podle originálu je to správně…


  22. snop 11.04.08 21:12

    Comment Arrow

    j, je to spravne, ale ja mam osobne radsi mysqli :), neni tam taka rezie jak u PDO, ale to je jedno fachat tak ci tak, ale treba mnet v php.ini PDO povolene


  23. snop 11.04.08 21:20

    Comment Arrow

    Jeste kdybyze prelozis http://akrabat.com/…th-tutorial/ a http://devzone.zend.com/…view/id/1665 tak by to nemnelo chybu, jinak koukal sem nato a jeto samej zdrojak, ani zdaaaaleka to neni tak casovo narocne na preklad jak tento navod. Jako ja eng. rozumim, ale pro neanglicky mluvici lidi by to byl prinos, lebo na cz nebo sk webu je pramaalo info o zendu.


  24. Pari 12.04.08 19:15

    Comment Arrow

    Aha, takhle to bylo myšleno, ale ja jsem se chtěl striktně držet originálu, protože se jedná o překlad. Zkušenější uživatel už bude vědět co je pro něj lepší a začátečníkovi je to šumák, pokud má PDO povolené.

    Tak mohu slíbit, že překlad minimálně zmíněného článku od Rob Allen se tu určitě objeví. Momentálně jsem ale docela zaneprázdněn prací a školou, takže spíše až začátkem května. Díky za tip, článek znám, ale dosud jsem ho neměl v plánu přeložit, protože to nikdo nechtěl.


  25. snop 13.04.08 09:25

    Comment Arrow

    Vis jak to je nidko te o preklad nepozada, ale kdyz ho udelas tak nastevnost take stranky se pocita v tisicoch.

    A o tem zaneprazdneni, praci a skolou :D to je asi kazdy, kdyz ma nekdo neco udelat tak nema cas lebo uz ma moc prace, to je klasika, tak isto u mne takze to chapu i kdyz ten clanek muze byt prelozeny za1–2hodky max.


  26. Pari 13.04.08 11:43

    Comment Arrow

    Tak kdysi jsem slyšel dobrou věc, nemáš čas, protože si ho nechceš udělat.. Tak nějak to asi bude, pokud si nedáš konkrétní termín, tak to furt oddaluješ a oddaluješ… Nicméně začátkem května to tu bude, to je můj veřejný deadline ;-)


  27. snop 13.04.08 13:36

    Comment Arrow

    tak to je super uz se tesim a sem zvedavi ;-)


  28. Sik 14.04.08 09:13

    Comment Arrow

    Musím říct, že tohle je prostě skvělá práce. Z tutoriálů co se dají na webu najít je tento asi nejlépe přístupný všem co se zend framework neznají. Prostě Good Work !!


  29. snop 10.05.08 21:48

    Comment Arrow

    hledaj
    set_include_path(‚.‘ . PATH_SEPARATOR . ‚./library‘ . PATH_SEPARATOR . ‚./application/models/‘ . PATH_SEPARATOR

    mas tam nezalomeny radek


  30. snop 10.05.08 21:58

    Comment Arrow

    Vývojáři Zend Framework to vyřešili tím, že vytvořili tzn. „action helper“.

    ne tzn. ale tzv.


  31. Pari 11.05.08 08:56

    Comment Arrow

    SNOP: Diky za tvé neustálé poznámky, slíbil jsem překlad článku Getting Started with Zend_Auth, mám dotaz jestli daný tutoriál funguje i na Zend Framework 1.5? Díval jsem se, že tento tutoriál byl pro Zend Framework 1.5 také aktualizovaný, je tam hodně změn nebo stačí aktualizovat pár drobností zde v tom článku?


  32. dracek 28.05.08 08:43

    Comment Arrow

    Me to nechtelo fungovat, nez jsem si vzpomel ze nemam povolene PDO_MYSQL. Myslim, ze lepci je to pouzivat na MYSQLi


  33. Visitor 11.06.08 13:36

    Comment Arrow

    Dik za clanek. Jen obcas narazim na male chyby a jedna je pro me neresitelna…

    1/ v ROOTu je soubor .htaccess aby mi fungoval musim na nekterych hostinzich pridat na druhy radek „RewriteBase /“
    2/ v kapitole MODEL mas „… z naší vzorovou aplikací …“. samozrejme tam ma byt „… s …“ (jen kosmetika)
    3/ pri vypisu dat z tabulky se na pipni.cz nemohu dobrat vysledku :(. Tak me napada zda neinterpretuje chybne ZF uzivatelske jmeno ve kterem jsou tecky „neco.nekde.cz“ (db.config.username = neco.nekde.cz) – coz je u pipni.cz povinnost.
    4/ Ty tu uvadis mi zahadny format se stredniky: „<a href=“baseUrl; ?>/index/add">Add new album". Nikde nepopisujes proc a jak, ale pak to u me vypada nasledovne: „Add new album Title Artist Undiscovered James Morrison Edit Delete“ takze tam ten strednikovy „balast“ zustava. Pokud ten balast odstranim tak uz to funguje OK. Ted jsem jeste jukl do originalu a tam to je bez toho „balastu“. Takze tim to je vyreseno…

    Zatim jdu pokracovat. Budu rad pokud nekdo mi osvetli proc to na tom pipni.cz nejede (PDO tam funguje kdyby mi to chtel nekdo napsat ;-) ).


  34. Pari 11.06.08 14:49

    Comment Arrow

    1/ JJ tento problem se u nekterych hostingu vyskytuje, vetsinou o ne/potrebe definování v .htaccess pisou primo na strankach webhostingů. S tutoriálem to přímo nesouvisí, ale dobře že si to zmínil, ostatním může pomoci.
    2/ Ano preklep, omlouvám se ;-) V tutoriálu pro Zend Framework 1.5 href=„http://weblog.pari.cz/293/zaciname-se-zend-framework-15“ rel=„nofollow“>http://weblog.pari.cz/293/zaciname-se-zend-framework-15 jsem se snad polepšil.
    3/ S Pipni a ZF zkusenost nemam, v tom ale problem nebude viz oficiální manuál: http://framework.zend.com/…ers.ini.html
    4/ Samozrejme chyba, opraveno.

    Ad. Pipni a PDO – Jestli se ti chce, muzes zkusit pouzit misto PDO MySQLi adaptér. http://framework.zend.com/…zend.db.html#…


  35. sedla 23.06.08 17:59

    Comment Arrow

    Dobrý den, děkuji za pěkný článek k vysvětlení ZF, ale narazil jsem na problém, se kterým si nevím rady.
    Zasekl jsem se v úseku, kde jsou vypsané action a url. Vytvořil jsem jsi vše podle předešlého návodu. Když zadám adresu : http://localhost/zf-tutorial/ vše funguje správně, ale když za tuto adresu dopišu index/add (edit, delete, apod.) tak se mi vypíše chybová stránka Not Found(The requested URL /zf-tutorial/public/index/edit was not found on this server.) . Nevíte čím by to mohlo být způsobeno, případně jak vyřešit tento problém? Mám Wamp5 a ZF 1.5 . Zkoušel jsem i videotutoriál na framework.zend.com, se stejným výsledkem. Děkuji


  36. sedla 24.06.08 07:31

    Comment Arrow

    vyřešeno , omlouvám se, že jsem Vás otravoval. Problém byl v tom, že jsem neměl povolen mod_rewrite v httpd.conf. Stydím se.


  37. Hanka 26.09.08 15:17

    Comment Arrow

    Díky moc za fajnový tutoriál. Angličtinu neovládám, takže mi opravdu hodně pomohl. :-)


  38. Flavier 22.10.08 22:32

    Comment Arrow

    Nazdar ľudia.Prosím Vás poraďte mi. Išiel som krok po kroku, všetko nastavoval podľa tutoriálu , ale v bode kedy mi malo už vypísať interpretov som mal akurát tento veľký eror:
    Fatal error: Uncaught exception ‚Zend_Db_Adapter_Exception‘ with message ‚SQLSTATE[28000] [1045] Access denied for user 'root‘@‚localhost‘ (using password: YES)' in C:\wamp\www\zf-tutorial\library\Zend\Db\Adapter\Pdo\Abstract.php:131 Stack trace: #0 C:\wamp\www\zf-tutorial\library\Zend\Db\Adapter\Abstract.php(380): Zend_Db_Adapter_Pdo_Abstract->_connect() #1 C:\wamp\www\zf-tutorial\library\Zend\Db\Adapter\Pdo\Abstract.php(206): Zend_Db_Adapter_Abstract->query(‚DESCRIBE `album…‘, Array) #2 C:\wamp\www\zf-tutorial\library\Zend\Db\Adapter\Pdo\Mysql.php(138): Zend_Db_Adapter_Pdo_Abstract->query(‚DESCRIBE `album…‘) #3 C:\wamp\www\zf-tutorial\library\Zend\Db\Table\Abstract.php(595): Zend_Db_Adapter_Pdo_Mysql->describeTable(‚album‘, NULL) #4 C:\wamp\www\zf-tutorial\library\Zend\Db\Table\Abstract.php(528): Zend_Db_Table_Abstract->_setupMetadata() #5 C:\wamp\www\zf-tutorial\library\Zend\Db\Table\Abstract.php(264): Zend_Db_Table_Abstract->_setup() #6 C:\wamp\www\zf-tutorial\application\controllers\IndexController.php(13): Zend_ in C:\wamp\www\zf-tutorial\library\Zend\Db\Adapter\Pdo\Abstract.php on line 131

    Kde je chyba?
    Dík


  39. Cavalier 04.03.09 10:32

    Comment Arrow

    Diky za clanek, v cestine toho moc o ZF neni. Je to pekny demonstrativni priklad.


  40. w3q 23.06.09 06:37

    Comment Arrow

    Internal Server Error

    The server encountered an internal error or misconfiguration and was unable to complete your request.

    Please contact the server administrator, admin@ocalhost and inform them of the time the error occurred, and anything you might have done that may have caused the error.

    More information about this error may be available in the server error log.
    Apache/2.0.55 (Win32) DAV/2 SVN/1.3.2 PHP/5.1.1 Server at localhost Port 80

    Viem že je chyba niekde v nastavení serveru, netuším však kde by to mohlo byť.


  41. DAF 27.11.09 14:33

    Comment Arrow

    Pekny článek, jen ma jeden problem, nevidim v sedych rameccich ani jeden zdrojovy kod, jen slovo „code“. Da se to nejak napravit? Diky




O autorovi

Pari

Vítejte na mém blogu, rád bych se v krátkosti představil. Je mi 26 let. Momentálně nejvíce času věnuji projektu Lepime.cz - obchod se samolepkami na zeď a tvorbě webů postavených na redakčním systému Drupal pod značkou MEPA.CZ.