IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

Evidencia kníh v PHP / MySQL s využitím MVC

V súťaži Machr na PHP bolo za úlohu vytvoriť webové rozhranie pre evidenciu kníh. V jednom z výherných webov som využil architektúry MVC (možno by sa dalo povedať MVP). Návrh aplikácie vyzeral nasledovne:

  • Model sa stará o aplikačné dáta. Vyberá / modifikuje dáta uložené v databáze (MySQL).
  • Controller získava dáta z modelového vrstvy a odovzdáva ich vrstve zobrazovacie. Tiež sa stará o udalosti, ako sú akcie a spracovanie formulárov.
  • View je vo forme šablóny Smarty.

Application

Celý životný cyklus som obalil triedou Application, vďaka ktorej stačilo mať v indexe iba pár riadkov:

require "loader.php";

$app = new Application($_POST, $_GET);
$app->setControllers(array(
    "user" => "User",
    "homepage" => "Homepage",
    "book" => "Book"
));
$app->setDefaultController("book");
$app->run();

V loader.php je potom trocha základného nastavenia, spoločného pre celú aplikáciu (spustenie sessions, nastavenie kódovania, vytvorenie class Autoloader a zaregistrovaní Smarty helper).

Základná myšlienka použitia triedy Application je, aby sa o životný cyklus aplikácie postarala sama. Preto potrebuje mať prístup k parametrom z URL a POST, ktoré sa odovzdajú cez konštruktor. Zároveň musí mať zoznam controllerov, ktoré sa postarajú o vykreslenie jednotlivých stránok a spracovanie rôznych akcií.

Zoznam odovzdáme pomocou metódy setControllers vo forme asocativního poľa (názov stránky => názov triedy). Tiež je možnosť určiť defaultný controller, ktorý sa použije na domovskú stránku. Ak neexistuje žiadny controller k danej stránke, automaticky sa použije tzv. Error controller, ktorý vykreslí stránku podľa šablóny 404.tpl.

Metóda run () potom vyhľadá controller k príslušnej stránke. K tomu jej pomôže pomocná metóda getController ():

/**
 * @return Controller
 */
public function getController()
{
    if (!isset($this->get["page"])) {
        if ($this->defaultController === NULL) {
            throw new ControllerException("No default controller set.");
        }

        $controller = ucFirst($this->defaultController) . "Controller";

        return new $controller($this->post, $this->get, $this->session);
    } else {
        if (!isset($this->controllers[$this->get["page"]])) {
            throw new ControllerException("Controller for this page doesn't exist.");
        }
    }

    $controller = $this->controllers[$this->get["page"]] . "Controller";

    return new $controller($this->post, $this->get, $this->session);
}

Metóda sa pokúsi zostaviť názov Controlleru podľa parametra "page" v URL adrese. Napr. ak nastavíme, že pre stránku "book" bude controller "Book", potom metóda vráti inštanciu BookController. V prípade zlyhania sa vyhodí výnimka ControllerExcep­tion. Keďže je táto výnimka vyhodená v prípade, ktorý by nemal nastať v ostrej verzii, nie je defaultne nikde zachytená. Nič ale vývojári nebráni výnimku zachytiť v indexe a chybu zalogovať.

V metóde run () potom stačí len vykonať pár základných udalostí:

  • Controller :: init () - nastavenie premenných, kontrola prihlásenie užívateľa atp.
  • Controller :: processForm () - spracovanie formulára (prebehne len v prípade, že pole $ _POST nie je prázdne).
  • Controller :: processAction () - spracovanie neformulářové akcie.
  • Controller :: processRender () - tá sa postará o vykreslenie stránky.

V prípade neexistujúce stránky sa použije error controller, ktorý vykreslí chybovú stránku.

Ešte než si popíšeme samotnú controller vrstvu, pozrieme sa na pár pomocných tried.

Template

Template je miniatúrny trieda, ktorá len spríjemňuje priraďovanie premenných šablóne. Namiesto Smarty zápisu $smarty->assign("proměnná", "hodnota") možno využiť magické metódy __set () a premenné priraďovať kratším spôsobom $template->promenna = "hodnota".

Config

Statická trieda, ktorá sa stará o načítanie konfiguračných dát z primitívneho .ini súboru. Tie je nutné ukladať do zložky config (tú nesmie byť možnosť zobraziť v prehliadači). Pokiaľ sa jedná o vývojársky režim, použije dáta zo súboru "config.local.ini". V produkčnom serveri sa potom dekóduje súbor "config.ini".

Database

Uľahčuje písanie metód PDO. Namiesto volania PDO :: prepare () a PDOStatement :: execute () možno volať metódy query (), fetch () atp. rovno tak, že prvým parametrom je SQL dotaz a ostatné parametre sa odovzdajú metóde PDO :: execute ().

Paginator

Slúži pre zobrazenie odkazov smerujúce na stránky výpisu dát.

Session

Malé rozhranie pre prácu so sessions. Umožňuje ukladať, získavať, mazať a kontrolovať hodnoty. Pri získavaní hodnoty je možné uviesť defaultný hodnotu (ak sa nenájde podľa kľúča) a prípadne vyhodiť výnimku (ak by bolo nevyhnutné hodnotu získať).

ModelFactory

Návrhom sa veľmi blíži DI Container. Ako ale z názvu vyplýva, vytvára iba inštancie modelov. Názvy metód sú vo formáte create <názov modelu> Model. Ako parametre väčšinou prijímajú ID (napr. ID užívateľa, knihy, ...). ModelFactory sa zároveň postará o to, aby dané modely získali spojenie s databázou. Keďže som nevytváral framework, celé DI by som prakticky moc nevyužil.

Controller

Teraz sa dostaneme k samotnej controller vrstve. Základom je abstraktná trieda Controller, ktorá sa stará o všetky udalosti (ktorých priame spracovanie určí potomkovia).

Init ()

Je volaná ako prvá a je vhodné ju využiť pre nastavenie premenných, kontrolu prihlásenie užívateľa a tak ďalej.

ProcessForm ()

Pokiaľ je v URL adrese parameter "form" (názov formulára) a pole $ _POST nie je prázdne, potom sa pomocou názvu formulára zostaví názov metódy. Tá je v tvare form <názov formulára> Submitted (). Pokiaľ taká metóda existuje, zavolá sa a odovzdá sa jej parameter "id" z URL (ak existuje).

final public function processForm()
{
    if (!isset($this->get->form) || !(array) $this->post) {
        return;
    }

    $method = "form" . ucFirst($this->get->form) . "Submitted";
    if (method_exists($this, $method)) {
        $id = !empty($this->get->id) ? (int) $this->get->id : NULL;
        $this->$method($id);
    }
}

ProcessAction ()

Robí prakticky to isté, čo metóda processForm (), len s tým rozdielom, že nevyžaduje dáta v POST. Metóda sa zostaví podľa parametra "action" v URL. Tvar metódy je potom action <názov akcie> ().

final public function processAction()
{
    if (!isset($this->get->action)) {
        return;
    }

    $method = "action" . ucFirst($this->get->action);
    if (method_exists($this, $method)) {
        $id = !empty($this->get->id) ? (int) $this->get->id : NULL;
        $this->$method($id);
    }
}

U oboch metód processForm () a processAction () je vhodné stránku presmerovať pomocou metódy redirect (). Jediný povinný parameter je názov stránky. Druhým, nepovinným parametrom je potom "sub" (napr. Page = book & sub = edit). Pomocou posledného parametra možno odovzdať ďalšie parametre v URL (napr. ID editovanej knihy).

ProcessRender ()

Spracovali sme formuláre a akcie a teraz je potreba vykresliť stránku. Najprv sa zostaví názov súboru v tvare application / templates / <názov stránky> / <sub stránka> .tpl. Pokiaľ nie je zadaná sub stránka, použije sa šablóna index.tpl.

Samotné vykreslenie potom prebieha nasledovne:

  • Zaregistrujú sa dôležité premenné pre všetky stránky (flash správa a zoznam formulárových chýb).
  • Zavolá sa metóda beforeRender ().
  • Zavolá sa metóda render <sub stránka> (). V tej sa nastaví premenné pre danú sub stránku.
  • Zavolá sa metóda Template :: render (), ktorá pomocou Smarty vygeneruje HTML.

Vytváranie vlastných stránok

Nové modely, controllery, šablóny, CSS a JS sa ukladá do zložky application.

Spracovanie formulárov

Chyby možno postupne ukladať pomocou metódy addFormError (). Potom pomocou vlastnosti formErrors dá zistiť, či bol formulár odoslaný úspešne alebo nie.

Ukážka spracovania prihlásenie:

public function formLoginSubmitted()
{
    $p = $this->post;

    if (empty($p->name)) {
        $this->addFormError("Nebylo vyplněno jméno.");
    }
    if (empty($p->password)) {
        $this->addFormError("Nebylo vyplněno heslo.");
    }

    if (!$this->formErrors) {
        try {
            $userId = $this->userModel->authenticate($p->name, $p->password);
            $this->session->set("userId", $userId);
            $this->setMessage("Byl jste úspěšně přihlášen.", "success");
            $this->redirect("user", "account");
        } catch (AuthenticationException $e) {
            $this->addFormError($e->getMessage());
        }
    }
}

Spracovanie akcií

Akciám možno odovzdať parameter ID. Samotný kód je potom podobný tomu v metóde processForm ().

Ukážka zmazanie knihy:

/**
 * @param int
 */
public function actionDelete($id)
{
    if (empty($id)) {
        $this->redirect("book");
    }
    if (!$this->userModel->isLogged()) {
        $this->redirect("user", "login");
    }

    $bookModel = $this->modelFactory->createBookModel($id);
    $deleted = $bookModel->delete();
    if ($deleted) {
        $this->setMessage("Kniha byla úspěšně smazána.", "success");
    } else {
        $this->setMessage("Tato kniha nemohla být smazána.", "error");
    }

    $this->redirect("book");
}

Renderovanie jednotlivých stránok

O to sa starajú metódy render <sub stránka> ().

Ukážka odovzdanie premenných šablóne book / index.tpl:

public function renderIndex()
{
    $limit = 10;
    $page = !empty($this->get->pageNum) ? (int) $this->get->pageNum : 0;
    $numItems = $this->bookModel->getBooksCount();
    $paginator = new Paginator($numItems, $page, $limit);

    $this->template->books = $this->bookModel->getAll($limit, $paginator->getOffset());
    $this->template->paginator = $paginator;
}

Správy

Správy sa posielajú cez sessions. Do šablóny sa dostanú vo forme inštancie stdClass, ktorá obsahuje dve vlastnosti (text, status - použije sa do atribútu class). Správa sa pri jej získaním ihneď zmaže.


Galéria


 

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 499x (269.07 kB)
Aplikácia je vrátane zdrojových kódov v jazyku PHP OOP

 

Všetky články v sekcii
Zdrojákoviště pre OOP v PHP
Program pre vás napísal Martin Konečný (pavelco1998)
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se o IT moc nezajímá, raději by se věnoval speciálním jednotkám jako jsou SEALs nebo SAS. Když už to ale musí být něco z IT, tak tvorba web. aplikací v PHP. Také vyvýjí novou českou prohlížečovou RPG hru a provozuje osobní web http://www.mkonecny.cz
Aktivity