MVC w praktyce – tworzymy system artykułów. cz. 3

W ostatniej części artykułu o wzorcu MVC stworzymy pozostałe elementy prostego systemu artykułów.

Uwaga. Pojawił się zaktualizowany cykl o MVC – przejdź


Dobrą praktyką przy budowaniu aplikacji z użyciem wzorca MVC jest „rozbicie” całego kodu na poszczególne, mniejsze moduły. W poprzedniej części stworzyliśmy fragmenty kodu do obsługi kategorii, teraz zajmiemy się artykułami.

Tworzymy kontroler artykułów

Na początek tworzymy kontroler controllers/articles.php:

<?php
/**
 * @author Łukasz Socha <kontakt@lukasz-socha.pl>
 * @version: 1.0
 * @license http://www.gnu.org/copyleft/lesser.html
 */

include 'controller/controller.php';

class ArticlesController extends Controller{

    public function index() {
        $view=$this->loadView('articles');
        $view->index();
    }
    public function one() {
        $view=$this->loadView('articles');
        $view->one();
    }
    public function add() {
        $view=$this->loadView('articles');
        $view->add();
    }
    public function insert() {
        $model=$this->loadModel('articles');
        $model->insert($_POST);
        $this->redirect('?task=articles&action=index');
    }
    public function delete() {
        $model=$this->loadModel('articles');
        $model->delete($_GET['id']);
        $this->redirect('?task=articles&action=index');
    }
}

I tu także przeanalizujmy reakcje dla następujących adresów URL:

  • ?task=articles&action=index – zostanie wywołana metoda index(), która inicjuje obiekt widoku articles, następnie zostaje wywołana metoda index()
  • ?task=articles&action=one – zostanie wywołana metoda one(), która inicjuje obiekt widoku articles, następnie zostaje wywołana metoda one()
  • ?task=articles&action=add – zostanie wywołana metoda add(), która inicjuje obiekt widoku articles, następnie zostaje wywołana metoda add()
  • ?task=articles&action=insert – zostanie wywołana metoda insert(), która inicjuje obiekt modelu articles, następnie zostaje wywołana metoda insert()
  • ?task=articles&action=delete – zostanie wywołana metoda delete(), która inicjuje obiekt modelu articles, następnie zostaje wywołana metoda delete()

Musimy jeszcze zmodyfikować plik index.php, by skrypt wywoływał kontroler Articles:

<?php

if($_GET['task']=='categories') {
    include 'controller/categories.php';
    $ob = new CategoriesController();
    $ob->$_GET['action']();
} else if($_GET['task']=='articles') {
    include 'controller/articles.php';
    $ob = new ArticlesController();
    $ob->$_GET['action']();
} else {
    include 'controller/articles.php';
    $ob = new ArticlesController();
    $ob->index();
}

Mamy już kontroler. Teraz przejdźmy do modelu.

Tworzymy model artykułów

model/articles.php:

<?php
/**
 * @author Łukasz Socha <kontakt@lukasz-socha.pl>
 * @version: 1.0
 * @license http://www.gnu.org/copyleft/lesser.html
 */

include 'model/model.php';

class ArticlesModel extends Model{

    public function getAll() {
        $query="SELECT a.id, a.title, a.date_add, a.autor, c.name FROM articles AS a LEFT JOIN categories AS c ON a.id_categories=c.id";
        $select=$this->pdo->query($query);
        foreach ($select as $row) {
            $data[]=$row;
        }
        $select->closeCursor();

        return $data;
    }
    public function getOne($id) {
        $query="SELECT a.id, a.title, a.date_add, a.autor, c.name, a.content FROM articles AS a LEFT JOIN categories AS c ON a.id_categories=c.id where a.id=".$id;
        $select=$this->pdo->query($query);
        foreach ($select as $row) {
            $data[]=$row;
        }
        $select->closeCursor();

        return $data;
    }
    public function insert($data) {
        $ins=$this->pdo->prepare('INSERT INTO articles (title, content, date_add, autor, id_categories) VALUES (
            :title, :content, :date_add, :autor, :id_categories)');
        $ins->bindValue(':title', $data['title'], PDO::PARAM_STR);
        $ins->bindValue(':content', $data['content'], PDO::PARAM_STR);
        $ins->bindValue(':date_add', $data['date_add'], PDO::PARAM_STR);
        $ins->bindValue(':autor', $data['author'], PDO::PARAM_STR);
        $ins->bindValue(':id_categories', $data['cat'], PDO::PARAM_INT);
        $ins->execute();
    }
    public function delete($id) {
        $del=$this->pdo->prepare('DELETE FROM articles where id=:id');
        $del->bindValue(':id', $id, PDO::PARAM_INT);
        $del->execute();
    }
}

Tak jak w przypadku kategorii, metody w ArticlesModel dodają, usuwają oraz poobierają dane z bazy danych.

Tworzymy widok artykułów

Pozostaje nam jeszcze stworzenie widoku. Plik view/articles.php:

<?php
/**
 * @author Łukasz Socha <kontakt@lukasz-socha.pl>
 * @version: 1.0
 * @license http://www.gnu.org/copyleft/lesser.html
 */

include 'view/view.php';

class ArticlesView extends View{
    public function  index() {
        $art=$this->loadModel('articles');
        $this->set('articles', $art->getAll());
        $this->render('indexArticle');
    }
    public function  one() {
        $art=$this->loadModel('articles');
        $this->set('articles', $art->getOne($_GET['id']));
        $this->render('oneArticle');
    }
    public function add() {
        $cat=$this->loadModel('categories');
        $this->set('catsData', $cat->getAll());
        $this->render('addArticle');
    }
}

Metoda index() generuje szablon HTML z listą wszystkich artykułów. Metoda one() wyświetla tylko jeden artykuł. Z kolei add() ma za zadanie wygenerować formularz dodawania artykułu. Warto zauważyć, że metoda ta pobiera listę kategorii z modelu CategoriesModel.

A wiec poszczególne warstwy aplikacji mogą wykorzystywać instancje wielu modeli. W dobrze zaprojektowanej aplikacji manipulacja danymi jest bardzo prosta – wystarczy załadować odpowiedni model i wykorzystywać jego publiczne metody.

Do pełni działającego skryptu brakuje nam jeszcze tylko plików szablonu.

Aktualizujemy plik templates/header.html.php:

<html>
    <head>
        <title>System newsów</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <link href="css/style.css" rel="stylesheet" type="text/css" />
    </head>
    <body>
        <ul>
            <li><a href="?task=categories&amp;action=add">Dodaj kategorię</a></li>
            <li><a href="?task=categories&amp;action=index">Lista kategorii</a></li>
            <li><a href="?task=articles&amp;action=add">Dodaj artykuł</a>
            <li><a href="?task=articles&amp;action=index">Lista artykułów</a>
        </ul>

templates/addArticle.html.php:

<? include 'templates/header.html.php'; ?>

<h1>Dodaj artykuł</h1>
<form action="?task=articles&amp;action=insert" method="post">
    Tytuł: <input type="text" name="title" /><br />
    Autor: <input type="text" name="author" /><br />
    Data dodania: <input type="text" name="date_add" value="<?= date("Y:m:d"); ?>" /><br />
    Treść:<br />
    <textarea name="content"></textarea><br />
    Kategoria: <select name="cat" size="0">
        <? foreach($this->get('catsData') as $cats) { ?>
            <option value="<?= $cats['id'] ;?>"><?= $cats['name']; ?></option>
        <? } ?>
    </select><br />
    <input type="submit" value="Dodaj" />
</form>

<? include 'templates/footer.html.php'; ?>

templates/indexArticle.html.php:

<? include 'templates/header.html.php'; ?>

<h1>Lista artykułów</h1>
<table>
    <tr>
        <td>Tytuł</td>
        <td>Data dodania</td>
        <td>Autor</td>
        <td>Kategoria</td>
        <td>&nbsp;</td>
    </tr>
    <? foreach($this->get('articles') as $articles) { ?>
    <tr>
        <td><a href="?task=articles&amp;action=one&amp;id=<?= $articles['id']; ?>"><?= $articles['title']; ?></a></td>
        <td><?= $articles['date_add']; ?></td>
        <td><?= $articles['autor']; ?></td>
        <td><?= $articles['name']; ?></td>
        <td><a href="?task=articles&amp;action=delete&amp;id=<?= $articles['id']; ?>">usuń</a></td>
    </tr>
    <? } ?>
</table>

<? include 'templates/footer.html.php'; ?>

templates/oneArticles.php:

<? include 'templates/header.html.php'; ?>

    <? foreach($this->get('articles') as $articles) { ?>
<h1><?= $articles['title']; ?></h1>
autor: <?= $articles['autor']; ?>, data dodania: <?= $articles['date_add']; ?><br />
Kategoria: <?= $articles['name']; ?>

<p><?= $articles['content']; ?></p>
    <? } ?>

<? include 'templates/footer.html.php'; ?>

Zakończenie

Tak stworzyliśmy działający skrypt oparty na wzorcu MVC. Dzięki rozdzieleniu warstwy logiki od formy prezentacji dalsza rozbudowa staje się znacznie prostsza. Możemy teraz dodać szablon HTML, bez potrzeby zaglądania w kontrolery oraz modele. Jest to szczególnie przydatne przy pracy nad większymi aplikacjami – osoby odpowiedzialne za wygląd mogą pracować praktycznie bez pomocy programistów.

Cały kod można pobrać stąd.

Powiązane tematy

Print Friendly, PDF & Email