Строим свою CMS на PHP и MySQL. Часть 7

В предыдущем уроке серии мы начали процесс добавления функционала категорий в нашу простую CMS. Рассмотрим, что нужно поменять в коде классов для реализации задуманных изменений.

Создание класса Category

Также как ранее мы создавали класс Article для управления хранением и выводом статей, нам нужно построить класс Category для решения таких же задач с категориями.

В папке cms имеется каталог classes. В каталоге classes создаем новый файл Category.php и копируем в него следующий код:

<?php
 
/**
 * Класс для обработки категорий статей
 */
 
class Category
{
  // Свойства
 
  /**
  * @var int ID категории из базы данных
  */
  public $id = null;
 
  /**
  * @var string Название категории
  */
  public $name = null;
 
  /**
  * @var string Короткое описание категории
  */
  public $description = null;
 
 
  /**
  * Устанавливаем свойства объекта с использованием значений в передаваемом массиве
  *
  * @param assoc Значения свойств
  */
 
  public function __construct( $data=array() ) {
    if ( isset( $data['id'] ) ) $this->id = (int) $data['id'];
    if ( isset( $data['name'] ) ) $this->name = preg_replace ( "/[^\.\,\-\_\'\"\@\?\!\:\$ a-zA-Z0-9()]/", "", $data['name'] );
    if ( isset( $data['description'] ) ) $this->description = preg_replace ( "/[^\.\,\-\_\'\"\@\?\!\:\$ a-zA-Z0-9()]/", "", $data['description'] );
  }
 
 
  /**
  * Устанавливаем свойства объекта с использованием значений из формы редактирования
  *
  * @param assoc Значения из формы редактирования
  */
 
  public function storeFormValues ( $params ) {
 
    // Store all the parameters
    $this->__construct( $params );
  }
 
 
  /**
  * Возвращаем объект Category, соответствующий заданному ID
  *
  * @param int ID категории
  * @return Category|false Объект Category object или false, если запись не была найдена или в случае другой ошибки
  */
 
  public static function getById( $id ) {
    $conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
    $sql = "SELECT * FROM categories WHERE id = :id";
    $st = $conn->prepare( $sql );
    $st->bindValue( ":id", $id, PDO::PARAM_INT );
    $st->execute();
    $row = $st->fetch();
    $conn = null;
    if ( $row ) return new Category( $row );
  }
 
 
  /**
  * Возвращаем все (или диапазон) объектов Category из базы данных
  *
  * @param int Optional Количество возвращаемых строк (по умолчаниюt = all)
  * @param string Optional Столбец, по которому сортируются категории(по умолчанию = "name ASC")
  * @return Array|false Двух элементный массив: results => массив с объектами Category; totalRows => общее количество категорий
  */
 
  public static function getList( $numRows=1000000, $order="name ASC" ) {
    $conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
    $sql = "SELECT SQL_CALC_FOUND_ROWS * FROM categories
            ORDER BY " . mysql_escape_string($order) . " LIMIT :numRows";
 
    $st = $conn->prepare( $sql );
    $st->bindValue( ":numRows", $numRows, PDO::PARAM_INT );
    $st->execute();
    $list = array();
 
    while ( $row = $st->fetch() ) {
      $category = new Category( $row );
      $list[] = $category;
    }
 
    // Получаем общее количество категорий, которые соответствуют критериям
    $sql = "SELECT FOUND_ROWS() AS totalRows";
    $totalRows = $conn->query( $sql )->fetch();
    $conn = null;
    return ( array ( "results" => $list, "totalRows" => $totalRows[0] ) );
  }
 
 
  /**
  * Вставляем текущий объект Category в базу данных и устанавливаем его свойство ID.
  */
 
  public function insert() {
 
    // У объекта Category уже есть ID?
    if ( !is_null( $this->id ) ) trigger_error ( "Category::insert(): Attempt to insert a Category object that already has its ID property set (to $this->id).", E_USER_ERROR );
 
    // Вставляем категорию
    $conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
    $sql = "INSERT INTO categories ( name, description ) VALUES ( :name, :description )";
    $st = $conn->prepare ( $sql );
    $st->bindValue( ":name", $this->name, PDO::PARAM_STR );
    $st->bindValue( ":description", $this->description, PDO::PARAM_STR );
    $st->execute();
    $this->id = $conn->lastInsertId();
    $conn = null;
  }
 
 
  /**
  * Обновляем текущий объект Category в базе данных.
  */
 
  public function update() {
 
    // У объекта Category  есть ID?
    if ( is_null( $this->id ) ) trigger_error ( "Category::update(): Attempt to update a Category object that does not have its ID property set.", E_USER_ERROR );
    
    // Обновляем категорию
    $conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
    $sql = "UPDATE categories SET name=:name, description=:description WHERE id = :id";
    $st = $conn->prepare ( $sql );
    $st->bindValue( ":name", $this->name, PDO::PARAM_STR );
    $st->bindValue( ":description", $this->description, PDO::PARAM_STR );
    $st->bindValue( ":id", $this->id, PDO::PARAM_INT );
    $st->execute();
    $conn = null;
  }
 
 
  /**
  * Удаляем текущий объект Category из базы данных.
  */
 
  public function delete() {
 
    // У объекта Category  есть ID?
    if ( is_null( $this->id ) ) trigger_error ( "Category::delete(): Attempt to delete a Category object that does not have its ID property set.", E_USER_ERROR );
 
    // Удаляем категорию
    $conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
    $st = $conn->prepare ( "DELETE FROM categories WHERE id = :id LIMIT 1" );
    $st->bindValue( ":id", $this->id, PDO::PARAM_INT );
    $st->execute();
    $conn = null;
  }
 
}
 
?>

Данный класс очень похож на класс Article и немного проще. Он содержит три свойства, которые соответствуют полям в таблице categoriesid, name и description, конструктор __construct(), который  создает новый объект Category. Также класс имеет метод storeFormValues() для сохранения данных из формы редактирования, методы для получения одной категории по ID и списка категорий, а также методов для вставки, обновления и удаления категории в базе данных.

Нам нужно включить новый класс Category в наши файлы кода, чтобы CMS могла получить доступ к нему. Поэтому включаем файл с классом в файл config.phpв папке cms, также как мы включали Article.php:

<?php
ini_set( "display_errors", true );
date_default_timezone_set( "Australia/Sydney" );  // http://www.php.net/manual/en/timezones.php
define( "DB_DSN", "mysql:host=localhost;dbname=cms" );
define( "DB_USERNAME", "username" );
define( "DB_PASSWORD", "password" );
define( "CLASS_PATH", "classes" );
define( "TEMPLATE_PATH", "templates" );
define( "HOMEPAGE_NUM_ARTICLES", 5 );
define( "ADMIN_USERNAME", "admin" );
define( "ADMIN_PASSWORD", "mypass" );
require( CLASS_PATH . "/Article.php" );
require( CLASS_PATH . "/Category.php" );
 
function handleException( $exception ) {
  echo "Sorry, a problem occurred. Please try later.";
  error_log( $exception->getMessage() );
}
 
set_exception_handler( 'handleException' );
?>

 

Модифицируем Article

Кроме создания  нового класса Category нужно также модифицировать класс  Article для работы с категориями. Ниже приводится код файла Article.php:

<?php
 
/**
 * Класс для управления статьями
 */
 
class Article
{
  // Свойства
 
  /**
  * @var int ID статьи из базы данных
  */
  public $id = null;
 
  /**
  * @var int Дата публикации статьи
  */
  public $publicationDate = null;
 
  /**
  * @var int ID категории статьи
  */
  public $categoryId = null;
 
  /**
  * @var string Полное название статьи
  */
  public $title = null;
 
  /**
  * @var string Резюме статьи
  */
  public $summary = null;
 
  /**
  * @var string Содержание HTML статьи
  */
  public $content = null;
 
 
  /**
  * Устанавливаем свойства объекта с использованием значений из массива
  *
  * @param assoc Значения свойств
  */
 
  public function __construct( $data=array() ) {
    if ( isset( $data['id'] ) ) $this->id = (int) $data['id'];
    if ( isset( $data['publicationDate'] ) ) $this->publicationDate = (int) $data['publicationDate'];
    if ( isset( $data['categoryId'] ) ) $this->categoryId = (int) $data['categoryId'];
    if ( isset( $data['title'] ) ) $this->title = preg_replace ( "/[^\.\,\-\_\'\"\@\?\!\:\$ a-zA-Z0-9()]/", "", $data['title'] );
    if ( isset( $data['summary'] ) ) $this->summary = preg_replace ( "/[^\.\,\-\_\'\"\@\?\!\:\$ a-zA-Z0-9()]/", "", $data['summary'] );
    if ( isset( $data['content'] ) ) $this->content = $data['content'];
  }
 
 
  /**
  * Устанавливаем свойства объекта с использованием значений из формы
  *
  * @param assoc Значения из формы
  */
 
  public function storeFormValues ( $params ) {
 
    // Сохраняем все параметры
    $this->__construct( $params );
 
    // Разбираем и сохраняем дату публикации
    if ( isset($params['publicationDate']) ) {
      $publicationDate = explode ( '-', $params['publicationDate'] );
 
      if ( count($publicationDate) == 3 ) {
        list ( $y, $m, $d ) = $publicationDate;
        $this->publicationDate = mktime ( 0, 0, 0, $m, $d, $y );
      }
    }
  }
 
 
  /**
  * Возвращаем объект Article соответствующий заданному ID
  *
  * @param int ID статьи
  * @return Article|false Объект Article или false, если запись не найдена или в случае другой ошибки
  */
 
  public static function getById( $id ) {
    $conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
    $sql = "SELECT *, UNIX_TIMESTAMP(publicationDate) AS publicationDate FROM articles WHERE id = :id";
    $st = $conn->prepare( $sql );
    $st->bindValue( ":id", $id, PDO::PARAM_INT );
    $st->execute();
    $row = $st->fetch();
    $conn = null;
    if ( $row ) return new Article( $row );
  }
 
 
  /**
  * Возвращает все (или диапазон) объекты Article из базы данных
  *
  * @param int Optional Количество возвращаемых строк (по умолчанию = all)
  * @param int Optional Вернуть статьи только из категории с указанным ID
  * @param string Optional Столбц, по которому выполняется сортировка статей (по умолчанию = "publicationDate DESC")
  * @return Array|false Двух элементный массив: results => массив объектов Article; totalRows => общее количество строк
  */
 
  public static function getList( $numRows=1000000, $categoryId=null, $order="publicationDate DESC" ) {
    $conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
    $categoryClause = $categoryId ? "WHERE categoryId = :categoryId" : "";
    $sql = "SELECT SQL_CALC_FOUND_ROWS *, UNIX_TIMESTAMP(publicationDate) AS publicationDate
            FROM articles $categoryClause
            ORDER BY " . mysql_escape_string($order) . " LIMIT :numRows";
 
    $st = $conn->prepare( $sql );
    $st->bindValue( ":numRows", $numRows, PDO::PARAM_INT );
    if ( $categoryId ) $st->bindValue( ":categoryId", $categoryId, PDO::PARAM_INT );
    $st->execute();
    $list = array();
 
    while ( $row = $st->fetch() ) {
      $article = new Article( $row );
      $list[] = $article;
    }
 
    // Получаем общее количество статей, которые соответствуют критерию
    $sql = "SELECT FOUND_ROWS() AS totalRows";
    $totalRows = $conn->query( $sql )->fetch();
    $conn = null;
    return ( array ( "results" => $list, "totalRows" => $totalRows[0] ) );
  }
 
 
  /**
  * Вставляем текущий объек Article в базу данных, устанавливаем его ID.
  */
 
  public function insert() {
 
    // Есть уже у объекта Article ID?
    if ( !is_null( $this->id ) ) trigger_error ( "Article::insert(): Attempt to insert an Article object that already has its ID property set (to $this->id).", E_USER_ERROR );
 
    // Вставляем статью
    $conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
    $sql = "INSERT INTO articles ( publicationDate, categoryId, title, summary, content ) VALUES ( FROM_UNIXTIME(:publicationDate), :categoryId, :title, :summary, :content )";
    $st = $conn->prepare ( $sql );
    $st->bindValue( ":publicationDate", $this->publicationDate, PDO::PARAM_INT );
    $st->bindValue( ":categoryId", $this->categoryId, PDO::PARAM_INT );
    $st->bindValue( ":title", $this->title, PDO::PARAM_STR );
    $st->bindValue( ":summary", $this->summary, PDO::PARAM_STR );
    $st->bindValue( ":content", $this->content, PDO::PARAM_STR );
    $st->execute();
    $this->id = $conn->lastInsertId();
    $conn = null;
  }
 
 
  /**
  * Обновляем текущий объект Article в базе данных.
  */
 
  public function update() {
 
    // У объекта Article есть ID?
    if ( is_null( $this->id ) ) trigger_error ( "Article::update(): Attempt to update an Article object that does not have its ID property set.", E_USER_ERROR );
    
    // Обновляем статью
    $conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
    $sql = "UPDATE articles SET publicationDate=FROM_UNIXTIME(:publicationDate), categoryId=:categoryId, title=:title, summary=:summary, content=:content WHERE id = :id";
    $st = $conn->prepare ( $sql );
    $st->bindValue( ":publicationDate", $this->publicationDate, PDO::PARAM_INT );
    $st->bindValue( ":categoryId", $this->categoryId, PDO::PARAM_INT );
    $st->bindValue( ":title", $this->title, PDO::PARAM_STR );
    $st->bindValue( ":summary", $this->summary, PDO::PARAM_STR );
    $st->bindValue( ":content", $this->content, PDO::PARAM_STR );
    $st->bindValue( ":id", $this->id, PDO::PARAM_INT );
    $st->execute();
    $conn = null;
  }
 
 
  /**
  * Удаляем текущий объект Article из базы данных
  */
 
  public function delete() {
 
    // У объекта Article есть ID?
    if ( is_null( $this->id ) ) trigger_error ( "Article::delete(): Attempt to delete an Article object that does not have its ID property set.", E_USER_ERROR );
 
    // Удаляем объект Article
    $conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
    $st = $conn->prepare ( "DELETE FROM articles WHERE id = :id LIMIT 1" );
    $st->bindValue( ":id", $this->id, PDO::PARAM_INT );
    $st->execute();
    $conn = null;
  }
 
}
 
?>

Рассмотрим изменения в классе Article подробно:

  • Новое свойство categoryId

    Чтобы установить соответствие статьи и категории мы добавили свойство categoryId для хранения ID категории, которой принадлежит статья. Также мы модифицировали конструктор __construct() для сохранения нового свойства categoryId в только что созданных объектах Article.

  • Изменение метода getList()

    Первоначальный вариант метода getList() возвращал все статьи в базе данных (или заданное количество записей). Так как нам нужно, чтобы CMS выводила список статей в определенной категории, модифицируем метод getList() для принятия опционального аргумента  $categoryId. Если он задан, то возвращаются статьи только из указанной категории.

    Если задан $categoryId, создаем строку $categoryClause для выражения WHERE, чтобы вернуть только те статьи, в которых значение поля categoryId соответствует значению categoryId. Затем модифицируем выражения SQL SELECT для включения переменной $categoryClause. Также добавляем новый вызов к $st->bindValue() для привязки заданного $categoryId.

  • Изменяем методы insert() и update()

    Также мы модифицировали методы класса Article  insert() и update() для работы с новым полем categoryId. Изменили запросы SQL INSERT и UPDATE в каждом методе, и добавили новые вызовы к bindValue() для передачи свойства $categoryId в выражения SQL.

 

В следующем уроке серии мы изменим шаблоны клиентской и серверной частей для работы с категориями.

Источник: http://feedproxy.google.com/~r/ruseller/CdHX/~3/m51GqK2z6a0/lessons.php

Читать комменты и комментировать

Добавить комментарий / отзыв



Защитный код
Обновить

Строим свою CMS на PHP и MySQL. Часть 7 | | 2012-12-13 06:51:23 | | Статьи Web-мастеру | | В предыдущем уроке серии мы начали процесс добавления функционала категорий в нашу простую CMS. Рассмотрим, что нужно поменять в коде классов для реализации задуманных изменений.Создание класса | РэдЛайн, создание сайта, заказать сайт, разработка сайтов, реклама в Интернете, продвижение, маркетинговые исследования, дизайн студия, веб дизайн, раскрутка сайта, создать сайт компании, сделать сайт, создание сайтов, изготовление сайта, обслуживание сайтов, изготовление сайтов, заказать интернет сайт, создать сайт, изготовить сайт, разработка сайта, web студия, создание веб сайта, поддержка сайта, сайт на заказ, сопровождение сайта, дизайн сайта, сайт под ключ, заказ сайта, реклама сайта, хостинг, регистрация доменов, хабаровск, краснодар, москва, комсомольск |
 
Поделиться с друзьями: