Строим свою 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-04-22 » Комментирование кода и генерация документации в PHP
- 2024-04-22 » SEO в России и на Западе: в чем основные отличия
- 2024-04-22 » SEO для международного масштабирования
- 2024-04-22 » Как использовать XML-карты для продвижения сайта
- 2024-04-22 » Цифровой маркетинг: инструменты для продвижения и рекламы в 2024 году
- 2024-04-22 » Что такое CSS-модули и зачем они нам?
- 2024-04-17 » 23 сервиса для эффективного экспресс-аудита любого сайта
- 2024-04-08 » Яндекс переходит на новую версию Wordstat
- 2024-04-08 » Яндекс интегрировал в свой облачный сервис эмпатичную нейросеть
- 2024-04-08 » Новая версия нейросети Claude превзошла по мощности аналоги Google и OpenAI
- 2024-04-08 » Как пользоваться GPT 4 и Claude бесплатно и без VPN
- 2024-03-13 » Стратегии SEO на 2024 год
- 2024-03-13 » Как использовать анимацию с помощью JavaScript-библиотеки GSAP
- 2024-03-13 » Использование GSAP 3 для веб-анимации
- 2024-03-13 » Cогласование топографической съёмки с эксплуатирующими организациями
- 2024-02-19 » Теряются лиды? Как настроить сквозную аналитику
- 2024-02-17 » Мерч и IT: на что обратить внимание в 2024 году
- 2024-02-16 » Копируем с RSync: основные примеры синхронизации файлов
- 2024-02-15 » Лучшие noCode AI платформы для создания диалоговых ботов
- 2024-02-14 » Факторы ранжирования Google 2024 — исследование Semrush
- 2024-02-12 » Перенос сайта на другой хостинг
- 2024-02-05 » В России сформирован реестр хостинг-провайдеров
- 2024-02-04 » Использование SSH для подключения к удаленному серверу Ubuntu
- 2024-02-03 » Подключаемся к серверу за NAT при помощи туннеля SSH. Простая и понятная инструкция
- 2024-02-02 » Настройка CI/CD для Gitlab-репозитория: схемы и гайд по шагам
- 2024-02-01 » GitLab CI Pipeline. Запуск сценария через SSH на удаленном сервере
- 2024-01-29 » Introduction to GitLab’s CI/CD for Continuous Deployments
- 2024-01-26 » Настройка GitLab CI/CD
- 2024-01-25 » Установка shell gitlab runner
- 2024-01-25 » Установка и регистрация gitlab-runner в docker контейнере
Секрет быть несчастным: иметь время занудствовать на тему, счастлив ты или нет Шоу Джордж Бернард - (1856-1950) - английский писатель. В своем творчестве ниспровергал догматизм и предвзятость, традиционность представлений |
Мы создаем сайты, которые работают! Профессионально обслуживаем и продвигаем их , а также по всей России и ближнему зарубежью с 2006 года!
Как мы работаем
Заявка
Позвоните или оставьте заявку на сайте.
Консультация
Обсуждаем что именно Вам нужно и помогаем определить как это лучше сделать!
Договор
Заключаем договор на оказание услуг, в котором прописаны условия и обязанности обеих сторон.
Выполнение работ
Непосредственно оказание требующихся услуг и работ по вашему заданию.
Поддержка
Сдача выполненых работ, последующие корректировки и поддержка при необходимости.