dr inż. Piotr Czapiewski
Overloading Znaczenie inne niż w większości języków obiektowych Metoda dynamicznego tworzenia pól i metod Magiczne metody __get(), __set(), __isset(), __unset() Wywoływane automatycznie przy próbie dostępu do nieistniejącego lub ukrytego pola ( private, protected )
Przekazywanie danych z kontrolera do widoku Przechowywanie danych w modelu Równocześnie dostęp obiektowy i łatwy zapis do bazy
Przykład – Kalkulator
zf create project Kalkulator cd Kalkulator zf create project Kalkulator cd Kalkulator
Konfiguracja serwera Apache Plik httpd.conf lub plik dołączany przez httpd.conf W przypadku pakietu XAMPP: c:\xampp\apache\conf\extra\httpd-vhosts.conf DocumentRoot "C:/xampp/htdocs/Kalkulator/public" ServerName kalkulator.localhost ErrorLog "logs/kalkulator.error.log" CustomLog "logs/kalkulator.access.log" combined DocumentRoot "C:/xampp/htdocs/Kalkulator/public" ServerName kalkulator.localhost ErrorLog "logs/kalkulator.error.log" CustomLog "logs/kalkulator.access.log" combined
Konfiguracja systemu Jaki adres IP ma host o nazwie kalkulator.localhost ? Plik hosts: c:\windows\system32\drivers\etc\hosts kalkulator.localhost
Witamy w Zendowym Kalkulatorze
zf create action dodaj Index Metoda dodajAction w IndexController.php Nowy plik widoku /views/scripts/index/dodaj.phtml
public function dodajAction() { $a = $this->getRequest()->getParam('a'); $b = $this->getRequest()->getParam('b'); $c = $a + $b; $this->view->wynik = $c; } public function dodajAction() { $a = $this->getRequest()->getParam('a'); $b = $this->getRequest()->getParam('b'); $c = $a + $b; $this->view->wynik = $c; }
Wynik dodawania: wynik; ?> Fajnie było, chcę jeszcze raz! Wynik dodawania: wynik; ?> Fajnie było, chcę jeszcze raz!
Zend_Layout, Zend_Db, Zend_Form
Implementacja wzorców projektowych: Two Step View i Composite View Wzorce projektowe Widok wygenerowany przez akcję jest wstrzykiwany do głównego szablonu Szablon strony Brak nagłówków, elementów nawigacyjnych, itd. Zawartość widoku ściśle związana z wykonywaną akcją Prosta konstrukcja widoków
zf enable layout [production] phpSettings.display_startup_errors = 0 phpSettings.display_errors = 0 includePaths.library = APPLICATION_PATH "/../library" bootstrap.path = APPLICATION_PATH "/Bootstrap.php" bootstrap.class = "Bootstrap" appnamespace = "Application" resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers" resources.frontController.params.displayExceptions = 0 resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/" [production] phpSettings.display_startup_errors = 0 phpSettings.display_errors = 0 includePaths.library = APPLICATION_PATH "/../library" bootstrap.path = APPLICATION_PATH "/Bootstrap.php" bootstrap.class = "Bootstrap" appnamespace = "Application" resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers" resources.frontController.params.displayExceptions = 0 resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/" Dodanie wpisu do application.iniUtworzenie katalogu layouts/scriptsUtworzenie domyślnego szablonu layout.phtml
Kalkulator layout()->content ?>
Witamy w Zendowym Kalkulatorze Kalkulator Witamy w Zendowym Kalkulatorze Szablon: layout.phtml Widok związany z akcją: index.phtml Kod wysłany do przeglądarki
class Application_Form_Kalkulator extends Zend_Form { public function init() { $this->setMethod('post'); $this->addElement('text', 'a'); $this->addElement('text', 'b'); $this->addElement('submit', 'Dodaj'); } } class Application_Form_Kalkulator extends Zend_Form { public function init() { $this->setMethod('post'); $this->addElement('text', 'a'); $this->addElement('text', 'b'); $this->addElement('submit', 'Dodaj'); } }
public function init() { $this->setMethod('post'); $a = $this->createElement('text', 'a'); $a->setRequired(true); $a->addValidator(new Zend_Validate_Int()); $a->setLabel('a = '); $this->addElement($a); $b = $this->createElement('text', 'b'); $b->setRequired(true); $b->addValidator(new Zend_Validate_Int()); $b->setLabel('b = '); $this->addElement($b); $this->addElement('submit', 'Dodaj'); }
public function init() { $this->setMethod('post'); $this->addElement('text', 'a', array( 'label' => 'a = ', 'required' => true, 'validators' => array('int') )); $this->addElement('text', 'b', array( 'label' => 'b = ', 'required' => true, 'validators' => array('int') )); $this->addElement('submit', 'Dodaj'); }
public function indexAction() { $form = new Application_Form_Kalkulator(); $form->setAction('/index/index'); $this->view->form = $form; } Witamy w Zendowym Kalkulatorze form; ?> Widok: index.phtml Kontroler: IndexController.php
public function indexAction() { $form = new Application_Form_Kalkulator(); $form->setAction('/index/index'); $this->view->form = $form; if($this->getRequest()->isPost()) { if($form->isValid($_POST)) { $this->_forward('dodaj'); } } }
[production] phpSettings.display_startup_errors = 0 phpSettings.display_errors = 0 includePaths.library = APPLICATION_PATH "/../library" bootstrap.path = APPLICATION_PATH "/Bootstrap.php" bootstrap.class = "Bootstrap" appnamespace = "Application" resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers" resources.frontController.params.displayExceptions = 0 resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/" resources.db.adapter = "pdo_mysql" resources.db.params.host = "localhost" resources.db.params.username = "student99" resources.db.params.password = "tajne_haslo" resources.db.params.dbname = "student99" resources.db.params.charset = utf8 [staging : production] [testing : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 [development : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 resources.frontController.params.displayExceptions = 1 [production] phpSettings.display_startup_errors = 0 phpSettings.display_errors = 0 includePaths.library = APPLICATION_PATH "/../library" bootstrap.path = APPLICATION_PATH "/Bootstrap.php" bootstrap.class = "Bootstrap" appnamespace = "Application" resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers" resources.frontController.params.displayExceptions = 0 resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/" resources.db.adapter = "pdo_mysql" resources.db.params.host = "localhost" resources.db.params.username = "student99" resources.db.params.password = "tajne_haslo" resources.db.params.dbname = "student99" resources.db.params.charset = utf8 [staging : production] [testing : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 [development : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 resources.frontController.params.displayExceptions = 1 resources.db.adapter = "pdo_mysql" resources.db.params.host = "localhost" resources.db.params.username = "student99" resources.db.params.password = "tajne_haslo" resources.db.params.dbname = "student99" resources.db.params.charset = utf8 resources.db.adapter = "pdo_mysql" resources.db.params.host = "localhost" resources.db.params.username = "student99" resources.db.params.password = "tajne_haslo" resources.db.params.dbname = "student99" resources.db.params.charset = utf8
Dostęp do adaptera bazy danych: $db = Zend_Db_Table::getDefaultAdapter(); Metody dostępu do danych: insert(), update(), delete(), query(), … fetchAll(), fetchAssoc(), fetchCol(), fetchOne(), …
$db = Zend_Db_Table::getDefaultAdapter(); $sql = 'select * from wpisy'; $result = $db->fetchAll($sql); foreach($result as $row) echo $row['id']. ' '. $row['tytul']. ' '; $sql = 'select * from wpisy where id = ?'; $row = $db->fetchRow($sql, array(1)); echo $row['id']. ' '. $row['tytul']. ' '; Zwraca tablicę
$sql = 'select id, tytul from wpisy'; $result = $db->fetchPairs($sql); foreach($result as $id => $tytul) echo $id. ' '. $tytul. ' '; $sql = 'select count(*) from wpisy'; $n = $db->fetchOne($sql);
Realizacja wzorca projektowego Table Data Gateway Tworzenie klasy pośredniczącej w dostępie do tabeli bazy danych Jedna tabela = jedna klasa pośrednicząca Proste operacje – bez użycia SQL Metody: fetchAll(), find(), save(), delete(), insert(), createRow()
<?php class Application_Model_Wpisy extends Zend_Db_Table_Abstract { protected $_name = 'wpisy'; } Tabela w bazie danych: wpisy Model: Wpisy.php
$model = new Application_Model_Wpisy(); $wpisy = $model->fetchAll(); foreach($wpisy as $wpis) echo $wpis->tytul. ' '; $res = $model->fetchAll('id < 7', 'tytul'); $wpis = $model->find(3)->current(); $res = $model->fetchAll('id < 7', 'tytul'); $wpis = $model->find(3)->current(); Zwraca obiekt klasy Zend_Db_Table_Rowset_Abstract
$dane = array( 'tytul' => 'Nowy wpis', 'tresc' => 'Ala ma kota...', 'skrot' => 'Ala...' ); $model->insert($dane); $dane = array( 'tytul' => 'Nowy wpis', 'tresc' => 'Ala ma kota...', 'skrot' => 'Ala...' ); $model->insert($dane); $wpis = $model->createRow(); $wpis->tytul = 'Nowy wpis'; $wpis->tresc = 'Ala ma kota...'; $wpis->skrot = 'Ala...'; $wpis->save(); Obiekt Zend_Db_Table_Row Metoda insert
$dane = array( 'tytul' => 'Zmieniony tytuł', 'tresc' => 'Całkiem nowa treść' ); $model->update($dane, 'id=26'); $dane = array( 'tytul' => 'Zmieniony tytuł', 'tresc' => 'Całkiem nowa treść' ); $model->update($dane, 'id=26'); $wpis = $model->find(26)->current(); $wpis->tytul = 'Zmieniony tytuł'; $wpis->tresc = 'Całkiem nowa treść'; $wpis->save(); Obiekt Zend_Db_Table_Row Metoda update
$select = $model->select(); $select->where('data_dodania >= ?', ' '); $select->where('data_dodania order('tytul'); $res = $model->fetchAll($select); $select = $model->select() ->where('data_dodania >= ?', ' ') ->where('data_dodania order('tytul'); $res = $model->fetchAll($select);
$select = $model->select(Zend_Db_Table::SELECT_WITH_FROM_PART); $select->where('data_dodania >= ?', ' '); $select->where('data_dodania order('tytul'); $select->setIntegrityCheck(false); $select->join('uzytkownicy', 'wpisy.autor=uzytkownicy.id'); $res = $model->fetchAll($select); $select = $model->select(Zend_Db_Table::SELECT_WITH_FROM_PART); $select->where('data_dodania >= ?', ' '); $select->where('data_dodania order('tytul'); $select->setIntegrityCheck(false); $select->join('uzytkownicy', 'wpisy.autor=uzytkownicy.id'); $res = $model->fetchAll($select);
Zend_Loader automatycznie ładuje definicje klas, o ile spełniają warunki określone w konfiguracji Klasa: Application_Model_Wpisy Plik: /application/models/Wpisy.php Klasa: Application_Form_Wpis Plik: /application/forms/Wpis.php
zf create project NaszBlog cd NaszBlog zf create project NaszBlog cd NaszBlog
zf enable layout
Domyślny szablon layout.phtml layout()->content; ?>
ZF Blog Strona główna | Dodaj wpis | Zaloguj layout()->content; ?>
Witamy w Naszym Blogu
Dostęp do bazy danych
[production] phpSettings.display_startup_errors = 0 phpSettings.display_errors = 0 includePaths.library = APPLICATION_PATH "/../library" bootstrap.path = APPLICATION_PATH "/Bootstrap.php" bootstrap.class = "Bootstrap" appnamespace = "Application" resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers" resources.frontController.params.displayExceptions = 0 resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/" resources.db.adapter = "pdo_mysql" resources.db.params.host = "localhost" resources.db.params.username = "zf_blog" resources.db.params.password = "zf_blog" resources.db.params.dbname = "zf_blog" resources.db.params.charset = utf8 [staging : production] [testing : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 [development : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 resources.frontController.params.displayExceptions = 1 [production] phpSettings.display_startup_errors = 0 phpSettings.display_errors = 0 includePaths.library = APPLICATION_PATH "/../library" bootstrap.path = APPLICATION_PATH "/Bootstrap.php" bootstrap.class = "Bootstrap" appnamespace = "Application" resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers" resources.frontController.params.displayExceptions = 0 resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/" resources.db.adapter = "pdo_mysql" resources.db.params.host = "localhost" resources.db.params.username = "zf_blog" resources.db.params.password = "zf_blog" resources.db.params.dbname = "zf_blog" resources.db.params.charset = utf8 [staging : production] [testing : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 [development : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 resources.frontController.params.displayExceptions = 1 resources.db.adapter = "pdo_mysql" resources.db.params.host = "localhost" resources.db.params.username = "zf_blog" resources.db.params.password = "zf_blog" resources.db.params.dbname = "zf_blog" resources.db.params.charset = utf8 resources.db.adapter = "pdo_mysql" resources.db.params.host = "localhost" resources.db.params.username = "zf_blog" resources.db.params.password = "zf_blog" resources.db.params.dbname = "zf_blog" resources.db.params.charset = utf8
application.ini Klasy z przedrostkiem Blog_ będą automatycznie ładowane (bez require) [production] phpSettings.display_startup_errors = 0 phpSettings.display_errors = 0 includePaths.library = APPLICATION_PATH "/../library" bootstrap.path = APPLICATION_PATH "/Bootstrap.php" bootstrap.class = "Bootstrap" appnamespace = "Blog"... [production] phpSettings.display_startup_errors = 0 phpSettings.display_errors = 0 includePaths.library = APPLICATION_PATH "/../library" bootstrap.path = APPLICATION_PATH "/Bootstrap.php" bootstrap.class = "Bootstrap" appnamespace = "Blog"...
Tworzymy model dla tabeli wpisy Klasa Blog_Model_Wpisy dziedzicząca z Zend_Db_Table_Abstract <?php class Blog_Model_Wpisy extends Zend_Db_Table_Abstract { protected $_name = 'wpisy'; }
Pobranie wszystkich wpisów: fetchAll() fetchAll($where, $order) Pobranie wpisu o konkretnym ID: find($id) $mdl = new Blog_Model_Wpisy(); $wpis = $mdl->find($id)->current(); $mdl = new Blog_Model_Wpisy(); $wpisy = $mdl->fetchAll();
Pobranie wszystkich wpisów i przekazanie do widoku: (application/controllers/IndexController.php) class IndexController extends Zend_Controller_Action { public function indexAction() { $mdl = new Blog_Model_Wpisy(); $wpisy = $mdl->fetchAll(); $this->view->wpisy=$wpisy; } } class IndexController extends Zend_Controller_Action { public function indexAction() { $mdl = new Blog_Model_Wpisy(); $wpisy = $mdl->fetchAll(); $this->view->wpisy=$wpisy; } }
Wyświetlenie wpisów w widoku: (application/views/scripts/index/index.phtml) ZF Blog wpisy as $wpis) { echo ' '; echo ' '. $wpis->tytul. ' '; echo ' '. $wpis->skrot. ' '; echo ' '; }
Implementacja wyświetlania treści całego wpisu Dodanie akcji /index/pokaz Dodanie na stronie głównej linku do akcji pokaz, przekazanie id wpisu W akcji pokaz: pobranie pojedynczego wpisu Wyświetlenie w widoku pokaz.phtml zf create action pokaz Index
public function pokazAction() { $id = $this->getRequest()->getParam('id'); $mdl = new Blog_Model_Wpisy(); $wpis = $mdl->find($id)->current(); $this->view->wpis = $wpis; } '. $this->wpis->tytul. ' '; echo ' '. $this->wpis->tresc. ' '; echo ' Powrót '; ?> Widok: pokaz.phtml Kontroler: IndexController.php
Implementacja dodawania wpisów Stworzenie formularza Blog_Form_Wpis Stworzenie akcji /index/dodaj W akcji dodaj: Stworzenie instancji formularza Przekazanie do widoku W widoku dodaj.phtml: Wyświetlenie formularza
class Blog_Form_Wpis extends Zend_Form { public function init() { $this->setMethod('post'); $this->addElement('text', 'tytul', array( 'label' => 'Tytuł:', 'required' => true, 'attribs' => array('size' => 60) )); $this->addElement('textarea', 'skrot', array( 'label' => 'Krótki opis:', 'attribs' => array('cols' => 60, 'rows' => 5), )); $this->addElement('textarea', 'tresc', array( 'label' => 'Pełna treść:', 'attribs' => array('cols' => 60, 'rows' => 25), )); $this->addElement('hidden', 'id'); $this->addElement('submit', 'Zapisz'); } } class Blog_Form_Wpis extends Zend_Form { public function init() { $this->setMethod('post'); $this->addElement('text', 'tytul', array( 'label' => 'Tytuł:', 'required' => true, 'attribs' => array('size' => 60) )); $this->addElement('textarea', 'skrot', array( 'label' => 'Krótki opis:', 'attribs' => array('cols' => 60, 'rows' => 5), )); $this->addElement('textarea', 'tresc', array( 'label' => 'Pełna treść:', 'attribs' => array('cols' => 60, 'rows' => 25), )); $this->addElement('hidden', 'id'); $this->addElement('submit', 'Zapisz'); } } $this->addElement('text', 'tytul', array( 'label' => 'Tytuł:', 'required' => true, 'attribs' => array('size' => 60) )); $this->addElement('textarea', 'skrot', array( 'label' => 'Krótki opis:', 'attribs' => array('cols' => 60, 'rows' => 5), )); $this->addElement('textarea', 'tresc', array( 'label' => 'Pełna treść:', 'attribs' => array('cols' => 60, 'rows' => 25), ));
$this->addElement('textarea', 'skrot', array( 'label' => 'Krótki opis:', 'attribs' => array('cols' => 60, 'rows' => 5), 'filters' => array( array( 'StripTags', array( array( 'allowTags' => array('b', 'i', 'img', 'h1', 'h2', 'h3, 'ol', 'ul', 'li', 'p'), 'allowAttribs' => array('src', 'class') ) ) ) ) )); $this->addElement('textarea', 'skrot', array( 'label' => 'Krótki opis:', 'attribs' => array('cols' => 60, 'rows' => 5), 'filters' => array( array( 'StripTags', array( array( 'allowTags' => array('b', 'i', 'img', 'h1', 'h2', 'h3, 'ol', 'ul', 'li', 'p'), 'allowAttribs' => array('src', 'class') ) ) ) ) ));
Kontroler Widok public function dodajAction() { $form = new Blog_Form_Wpis(); //... do uzupełnienia... $form->setAction('/index/dodaj'); $this->view->form = $form; } public function dodajAction() { $form = new Blog_Form_Wpis(); //... do uzupełnienia... $form->setAction('/index/dodaj'); $this->view->form = $form; } Dodaj wpis form; ?>
Obsługa przesłanego formularza Sprawdzenie poprawności danych Stworzenie instancji modelu Blog_Model_Wpisy Stworzenie nowego wiersza Zapisanie danych
public function dodajAction() { $form = new Blog_Form_Wpis(); if($this->getRequest()->isPost()) { if($form->isValid($_POST)) { $dane = $form->getValues(); unset($dane['id']); $mdl = new Blog_Model_Wpisy(); $mdl->insert($dane); $this->_redirect('index'); } } $form->setAction('/index/dodaj'); $this->view->form = $form; }
Analogicznie do dodawania Różnice Przed wyświetleniem formularza: Pobranie wpisu z bazy i wstępne wypełnienie formularza Po zatwierdzeniu formularza Modyfikacja wpisu zamiast tworzenia nowego
public function edytujAction() { $form = new Blog_Form_Wpis(); $mdl = new Blog_Model_Wpisy(); $id = $this->getRequest()->getParam('id'); $wpis = $mdl->find($id)->current(); if($this->getRequest()->isPost()) { if($form->isValid($_POST)) { // zapisz wpis... } } else { $form->populate($wpis->toArray()); } $form->setAction($this->_helper->url('edytuj')); $this->view->form = $form; } if($this->getRequest()->isPost()) { if($form->isValid($_POST)) { $dane = $form->getValues(); $wpis->tytul = $dane['tytul']; $wpis->skrot = $dane['skrot']; $wpis->tresc = $dane['tresc']; $wpis->save(); $this->_redirect('index'); } }