Строим свою 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
и немного проще. Он содержит три свойства, которые соответствуют полям в таблице categories
— id
, 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
. Затем модифицируем выражения SQLSELECT
для включения переменной$categoryClause
. Также добавляем новый вызов к$st->bindValue()
для привязки заданного$categoryId.
- Изменяем методы
insert()
иupdate()
Также мы модифицировали методы класса
Article
insert()
иupdate()
для работы с новым полемcategoryId
. Изменили запросы SQLINSERT
иUPDATE
в каждом методе, и добавили новые вызовы кbindValue()
для передачи свойства$categoryId
в выражения SQL.
В следующем уроке серии мы изменим шаблоны клиентской и серверной частей для работы с категориями.
Источник: http://feedproxy.google.com/~r/ruseller/CdHX/~3/m51GqK2z6a0/lessons.php
Дайджест новых статей по интернет-маркетингу на ваш email
Новые статьи и публикации
- 2024-11-26 » Капитан грузового судна, или Как начать использовать Docker в своих проектах
- 2024-11-26 » Обеспечение безопасности ваших веб-приложений с помощью PHP OOP и PDO
- 2024-11-22 » Ошибки в Яндекс Вебмастере: как найти и исправить
- 2024-11-22 » Ошибки в Яндекс Вебмастере: как найти и исправить
- 2024-11-15 » Перенос сайта на WordPress с одного домена на другой
- 2024-11-08 » OSPanel 6: быстрый старт
- 2024-11-08 » Как установить PhpMyAdmin в Open Server Panel
- 2024-09-30 » Как быстро запустить Laravel на Windows
- 2024-09-25 » Next.js
- 2024-09-05 » OpenAI рассказал, как запретить ChatGPT использовать содержимое сайта для обучения
- 2024-08-28 » Чек-лист: как увеличить конверсию интернет-магазина на примере спортпита
- 2024-08-01 » WebSocket
- 2024-07-26 » Интеграция с Яндекс Еда
- 2024-07-26 » Интеграция с Эквайринг
- 2024-07-26 » Интеграция с СДЕК
- 2024-07-26 » Интеграция с Битрикс-24
- 2024-07-26 » Интеграция с Travelline
- 2024-07-26 » Интеграция с Iiko
- 2024-07-26 » Интеграция с Delivery Club
- 2024-07-26 » Интеграция с CRM
- 2024-07-26 » Интеграция с 1C-Бухгалтерия
- 2024-07-24 » Что такое сторителлинг: техники и примеры
- 2024-07-17 » Ошибка 404: что это такое и как ее использовать для бизнеса
- 2024-07-03 » Размещайте прайс-листы на FarPost.ru и продавайте товары быстро и выгодно
- 2024-07-01 » Профилирование кода в PHP
- 2024-06-28 » Изучаем ABC/XYZ-анализ: что это такое и какие решения с помощью него принимают
- 2024-06-17 » Зачем вам знать потребности клиента
- 2024-06-11 » Что нового в работе Яндекс Метрики: полный обзор обновления
- 2024-06-11 » Поведенческие факторы ранжирования в Яндексе
- 2024-06-11 » Скорость загрузки сайта: почему это важно и как влияет на ранжирование
Все мы сидим в сточной канаве, но некоторые при этом смотрят на звезды Уайльд Оскар - (1854-1900) - английский писатель |
Мы создаем сайты, которые работают! Профессионально обслуживаем и продвигаем их , а также по всей России и ближнему зарубежью с 2006 года!
Как мы работаем
Заявка
Позвоните или оставьте заявку на сайте.
Консультация
Обсуждаем что именно Вам нужно и помогаем определить как это лучше сделать!
Договор
Заключаем договор на оказание услуг, в котором прописаны условия и обязанности обеих сторон.
Выполнение работ
Непосредственно оказание требующихся услуг и работ по вашему заданию.
Поддержка
Сдача выполненых работ, последующие корректировки и поддержка при необходимости.