Как создать объектно-ориентированный блог с помощью PHP

14 января 2018

В последние несколько недель NETTUTS опубликовала немало замечательных руководств о том, как начать использовать PHP и MySQL для создания простых веб-приложений, таких как окно крика. Сегодня мы будем использовать наши знания PHP и MySQL в следующем шаге, создав простой блог. Хотя существует множество превосходных бесплатных платформ для блогов, цель этого учебника заключается не в том, чтобы сделать «лучший» блог, а в том, чтобы использовать процесс создания блога, чтобы узнать о передовых методах структуры базы данных и о том, как использовать данные более эффективно, используя объекты в PHP.

В этом учебнике предполагается, что у вас есть некоторое базовое понимание PHP, MySQL, XHTML и более поздних версий jQuery JavaScript.

Часть 1) Создание нашей базы данных

Прежде чем мы перейдем в наш клиент MySQL и начнем создавать наши таблицы, мы должны выложить то, что хотим в нашем блоге. Очевидная вещь, которую нам нужно удержать, - это сообщения в блогах, и в каждом посте она должна содержать заголовок, пост, автора и дату его публикации.

Теперь мы можем просто сделать одну таблицу для хранения этой информации и, скорее всего, создать базовый блог, но только с одной таблицей у нас не будет такого большого контроля над нашими данными. Например, мы могли бы просто сохранить имя автора в той же таблице, что и запись в блоге, но что, если мы хотим сохранить электронную почту автора? Конечно! Мы просто добавим другое поле в нашу таблицу, это будет очевидное решение.

Проблема возникает, когда по дороге вы хотите изменить адрес электронной почты этого автора. Теперь вам нужно изменить его для каждого отдельного сообщения в блоге, созданного человеком.

Итак, что мы собираемся сделать, это сделать отдельную таблицу под названием «Люди», и в этом мы сохраним всю информацию, которая нам нужна от автора, например, электронные письма, URL-адреса, их имя и уникальный идентификатор. Затем в нашей таблице сообщений в блоге мы укажем на человека, которого хотим, используя уникальный идентификатор этого человека. Этот идентификатор называется внешним ключом, а связь между таблицей сообщений блога и таблицей людей называется отношением «один ко многим».

Еще одна вещь, которую мы хотим иметь в нашем блоге, - это тег для каждого сообщения в блоге. Снова мы хотим сделать нашу базу данных эффективной, поэтому мы создадим отдельную таблицу для наших тегов. Теперь, что мы делаем? Должно ли мы создать поле в таблице сообщений блога, которое является внешним ключом для нашего тега? Проблема с использованием отношения «один-к-одному» на этот раз иногда в сообщениях блога имеет более одного тега; так что снова мы будем использовать отношения «один ко многим». Для этого нам нужно создать другую таблицу, которая будет называться чем-то вроде «blog_post_tags», которая будет содержать два внешних ключа, один будет идентификатором блога, а другой будет идентификатором тега, с которым связано сообщение в блоге. Таким образом, мы можем назначить столько тегов, сколько хотим в сообщении в блоге, но все же можем редактировать информацию об этом конкретном теге во всех сообщениях с помощью простого запроса MySQL.

Теперь, когда мы изложили, на что мы хотим, чтобы наша база данных выглядела, давайте ее создадим. Я буду использовать PhpMyAdmin, так как это самый распространенный клиент администратора MySQL. Существует несколько различных соглашений об именах, которые вы можете использовать при создании имен базы данных, таблицы и полей. Мне лично нравится использовать все строчные буквы и подчеркивания вместо пробелов.

Примечание. Если у вас нет PHP и MySQL в вашей системе или на сервере, который может ее запустить, я рекомендую загрузить отдельную установку Apache, PHP и MySQL. MAMP хорош для Mac и WAMP хорош для ПК.

Сначала нам нужно создать нашу базу данных, я назову ее «nettuts_blog».

Затем мы создадим наши таблицы; первым будет «blog_posts».

«blog_posts» будет иметь пять полей: «id», «title», «post», «author_id» и «date_posted». Для «id» мы сделаем его первичным ключом и настроим его на автоматическое увеличение. Что это будет делать, так это генерировать наш уникальный идентификатор для нас. Каждый раз, когда мы добавляем сообщение, он дает ему число, начинающееся с одного и продвигающееся на столько сообщений, сколько у нас есть.

Теперь нам также нужно установить тип переменной для каждого поля. Идентификатор будет установлен на тип int, короткий для integer, так как он может быть только числом, и мы установим максимальную длину равным 11. Поле «title» будет установлено на тип varchar с максимальной длиной 255. « post "будет тип« текст », и мы не будем устанавливать максимальную длину, так как сообщения могут быть очень длинными. «author_id» будет таким же, как «id», но мы не будем устанавливать его в качестве нашего первичного ключа или автоматически увеличивать его, и мы будем устанавливать «date_posted» для ввода «Date».

Наша следующая таблица будет «людьми». Мы не называем это «авторами», потому что по дороге мы, возможно, захотим создать возможность регистрировать и отправлять комментарии, и эти люди не будут считаться авторами.

«люди» будут содержать также пять полей: «id», «first_name», «last_name», «url» и «email».

«id» будет установлен как int, первичный ключ и автоматическое увеличение, так же, как мы установили id «blog_posts». «first_name», «last_name», «url» и «email» будут установлены для ввода varchar с максимальной длиной 255.

Наша следующая таблица будет «тегами» и теперь будет содержать только два поля: id "и" name ". В будущем мы могли бы сделать это более сложным, добавив описание, но для этого урока мы не будем. Как и раньше, «id» будет установлен как int, первичный ключ и автоинкремент. «name» будет типом varchar и имеет максимальную длину 255.

И наша последняя таблица «blog_post_tags» будет иметь только два поля: «blog_post_id» и «tag_id». Оба они будут настроены на тип int с максимальной длиной 11. Как вы, скорее всего, заметили, мы не установили первичный ключ для этой таблицы. Это связано с тем, что мы никогда не будем получать данные из этой таблицы, если мы не будем запрашивать конкретную запись в блоге или все сообщения определенного идентификатора тега.

Часть 2) Создание наших объектов в PHP

Прежде чем мы начнем с нашего реального кода PHP, нам необходимо создать наши файлы и папки, для этого урока мы будем иметь наш index.php в нашей корневой папке, а затем в папку, наша таблица стилей CSS, наши файлы JavaScript, includes.php, которая будет содержать ссылки на наши объекты и соединение с MySQL, и blogpost.php, которые будут содержать наш BlogPost obejct.

Теперь, когда у нас есть наш набор баз данных, нам нужно создать объекты на PHP, которые будут обрабатывать данные для нас. Объекты в программировании - это способ объединить разные атрибуты (как переменные) и методы, которые все относятся к одному и тому же. Объекты также помогают нам организовывать наши программы намного больше. Прежде чем мы перейдем к нашим объектам для нашего блога, давайте просто создадим простой объект, чтобы мы могли проиллюстрировать, что они находятся в более «реальной жизни».

Наш объект будет называться «Bike», теперь есть два типа вещей, которые каждый объект имеет, свойства и методы. Свойства определяют объект, а методы - это то, что делает объект. Например, наш объект Bike имел бы такие свойства, как размер колес, количество передач и, возможно, размер рамки. Для методов у нас может быть что-то вроде «Педаль».

Теперь, чтобы вернуться в наш блог, нам нужен только один объект, который теперь называется «BlogPost». BlogPost будет иметь шесть свойств, id, title, post, author, tags и date. Поэтому давайте сделаем это на PHP.

Чтобы определить объект в PHP, мы определяем его как «класс». Класс - это структура каждого объекта, или, как википедия описывает его: «В объектно-ориентированном программировании класс представляет собой конструкцию языка программирования, которая используется в качестве плана для создания объектов. Этот проект включает атрибуты и методы, которые все созданные объекты доля." (http: en.wikipedia.org wiki Concrete_class). Мы собираемся открыть нашу страницу blogpost.php и определить наш первый объект.

Примечание. В каждом разделе учебника я собираюсь оставить закрывающие и закрывающие PHP-теги; «» вам нужно будет включить их в начале и конце документа.

class BlogPostn{n}

В нашем классе нам нужно сначала определить наши свойства. Для этого нам нужно создать переменные, но с «публикой» перед ними. Просто быстрая заметка, если вы используете PHP4, тогда вам нужно будет использовать «var» вместо «public».

class BlogPost
{
    public $id;
    public $title;
    public $post;
    public $author;
    public $tags;
    public $datePosted;
}

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

Наш первый метод будет тем, что называется конструктором; этот метод автоматически вызывается всякий раз, когда мы создаем новый экземпляр объекта BlogPost.

Общее использование конструктора состоит в том, что вы можете создать новый объект и быстро установить свойства этого объекта.

Итак, мы хотим создать новую функцию __construct (), и мы собираемся передать пять значений, id, title, post, author id и date. Для каждого имени переменной мы будем вводить слово «in» перед словом, чтобы мы могли определить внутри наших функций, какие переменные передаются и какие переменные уже присутствуют.

class BlogPost
{
    public $id;
    public $title;
    public $post;
    public $author;
    public $tags;
    public $datePosted;
    function __construct($inId, $inTitle, $inPost, $inAuthorId, $inDatePosted)
    {
    }
 }

Проблема здесь в том, что с этим текущим кодом каждый раз, когда мы создаем новый экземпляр BlogPost, нам нужно предоставить все эти свойства. Но что, если мы хотим создать новое сообщение в блоге и еще не определили эти переменные? Чтобы справиться с этим, нам нужно «перегрузить» аргументы для нашей функции, чтобы, если мы вызываем функцию и не передаем один из аргументов, она автоматически установит ее в значение по умолчанию.

function __construct($inId=null, $inTitle=null, $inPost=null, $inPostFull=null, $inAuthorId=null, $inDatePosted=null)
{
}

Как вы можете видеть, все, что мы делаем для выполнения нашей задачи, задает каждому аргументу значение «null». Теперь внутри нашего конструктора нам нужно установить каждую из наших переменных в наши переданные значения. Для этого мы хотим установить их на объект, который мы сейчас находим; Мы можем сделать это с помощью этого «ключевого слова». В отличие от многих других языков для доступа к свойству в PHP вы используете «->», где на большинстве языков (I.E. JavaScript, ASP.ET) вы используете «.».

function __construct($inId=null, $inTitle=null, $inPost=null, $inPostFull=null, $inAuthorId=null, $inDatePosted=null)
{
    $this->id = $inId;
    $this->title = $inTitle;
    $this->post = $inPost;
}

Это работает для id, title и post. Но как насчет наших других? На сегодняшний день нам нужно будет переформатировать данные, полученные из MySQL, чтобы они были более удобочитаемыми. Это легко осуществить; Мы просто взорвали его (также известный как расщепление на других языках программирования), а затем вернем его вместе. MySQL дает нам в этом формате yyyy-mm-dd, поэтому, если мы взорвем его, используя «-» в качестве нашего разделителя, мы получим массив, содержащий три значения. Первый проведет наш год, следующий пройдет в нашем месяце, и последний будет днем. Теперь все, что мы делаем, объединяет их в любом формате, который мы хотим. Я иду с mm dd yyyy.

$splitDate = explode("-", $inDatePosted);
$this->datePosted = $splitDate[1] . "/" . $splitDate[2] . "/" . $splitDate[0];

Для автора все, что нам нужно сделать, это запросить базу данных для человека с идентификатором нашего идентификатора автора. Мы можем сделать это с помощью базового запроса MySQL.

$query = mysql_query("SELECT first_name, last_name FROM People WHERE id = " . $inAuthorId);
$row = mysql_fetch_assoc($query);
$this->author = $row["first_name"] . " " . $row["last_name"];

Left Joi

Теперь теги будут немного сложнее. Нам нужно будет поговорить с базой данных, поэтому нам нужно создать запрос MySQL. Мы не будем беспокоиться о подключении к базе данных прямо сейчас, которое будет определено за пределами этого класса. Теперь у нас есть идентификатор блога. Мы можем сравнить это с тегами сообщений блога в нашей таблице blog_post_tags, но тогда мы вернемся только к идентификатору тега и вам нужно будет сделать еще один запрос, чтобы получить информацию о теге. Это не хорошо; Мы хотим быть эффективными, поэтому давайте сделаем это только в одном запросе!

Для этого мы будем делать то, что называется левым соединением, это означает, что мы также будем выбирать данные из другой таблицы, но только тогда, когда они совпадают с данными из «левых» или других выбранных нами данных. Поэтому сначала давайте просто получим идентификаторы тегов, которые связаны с идентификатором нашего блога в таблице blog_post_tags.

$query = mysql_query("SELECT * FROM blog_post_tags WHERE blog_post_tags.blog_post_id = " . $inId);

Теперь давайте добавим наше левое соединение и скажем наш запрос, что нам нужны только данные в таблице тегов:

$query = mysql_query("SELECT tags.* FROM blog_post_tags LEFT JOIN (tags) ON (blog_post_tags.tag_id = tags.id) WHERE blog_post_tags.blog_post_id = " . $inId);

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

Теперь мы хотим обработать эти данные на PHP с помощью простого цикла while. Мы также создадим два массива, которые будут содержать наши данные: один для имени тега, а другой для идентификатора тега. Мы также создадим строку для хранения всех наших тегов. Сначала мы установим его в «Нет тегов», чтобы, если мы не вернем никаких данных из нашего MySQL-запроса, он вернет, что у нас нет тегов, иначе это значение будет перезаписано именами тегов.

$postTags = "No Tags";
$tagArray = array();
$tagIDArray = array();
while($row = mysql_fetch_assoc($query)
{
    array_push($tagArray, $row["name"]);
    array_push($tagIDArray, $row["id"]);
}

Теперь мы проверим, будет ли массив иметь длину больше нуля (мы не хотим выполнять весь этот дополнительный код, если нам не нужно). Далее, для каждого тега в нашем массиве имен тегов мы собираемся конкатенировать строку тегов. Мы будем использовать простую инструкцию if else.

if (sizeof($tagArray) > 0)
{
    foreach ($tagArray as $tag)
    {
        if ($postTags == "No Tags")
        {
            $postTags = $tag;
        }
        else
        {
            $postTags = $postTags . ", " . $tag;
        }
    }
}
$this->tags = $postTags;

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

Последний шаг для нашего класса заключается в том, чтобы добавлять операторы if для каждого свойства, чтобы, если мы ничего не передаем, он не будет пытаться установить свойство текущего объекта в ничто (это вызовет ошибку). Вот весь класс BlogPost с добавленными инструкциями if:

<?php
class BlogPost
{
public $id;
public $title;
public $post;
public $author;
public $tags;
public $datePosted;
function __construct($inId=null, $inTitle=null, $inPost=null, $inPostFull=null, $inAuthorId=null, $inDatePosted=null)
{
    if (!empty($inId))
    {
        $this->id = $inId;
    }
    if (!empty($inTitle))
    {
        $this->title = $inTitle;
    }
    if (!empty($inPost))
    {
        $this->post = $inPost;
    }
    if (!empty($inDatePosted))
    {
        $splitDate = explode("-", $inDatePosted);
        $this->datePosted = $splitDate[1] . "/" . $splitDate[2] . "/" . $splitDate[0];
    }
    if (!empty($inAuthorId))
    {
        $query = mysql_query("SELECT first_name, last_name FROM people WHERE id = " . $inAuthorId);
        $row = mysql_fetch_assoc($query);
        $this->author = $row["first_name"] . " " . $row["last_name"];
    }
    $postTags = "No Tags";
    if (!empty($inId))
    {
        $query = mysql_query("SELECT tags.* FROM blog_post_tags LEFT JOIN (tags) ON (blog_post_tags.tag_id = tags.id) WHERE blog_post_tags.blog_post_id = " . $inId);
        $tagArray = array();
        $tagIDArray = array();
        while($row = mysql_fetch_assoc($query))
        {
            array_push($tagArray, $row["name"]);
            array_push($tagIDArray, $row["id"]);
        }
        if (sizeof($tagArray) > 0)
        {
            foreach ($tagArray as $tag)
            {
                if ($postTags == "No Tags")
                {
                    $postTags = $tag;
                }
                else
                {
                    $postTags = $postTags . ", " . $tag;
                }
            }
        }
    }
    $this->tags = $postTags;
}
}
?>

Теперь, когда наш класс объектов завершен, большая часть сложного материала выполнена! Теперь все, что нам нужно сделать, это настроить наше соединение с базой данных и HTML для отображения наших сообщений!

Часть 3) Получение данных из MySQL и отображение их с помощью PHP

Прежде чем мы что-то сделаем, нам нужно настроить наш файл include.php, чтобы сохранить ссылку на наш объект BlogPost и подключиться к нашей базе данных MySQL. Сначала давайте включим наш объект с простым заявлением include:

include 'blogpost.php';

Теперь добавим соединение с базой данных:

$coection = mysql_coect("localhost", "username", "password") or die ("<p class='error'>Sorry, we were unable to coect to the database server.</p>");
$database = "nettuts_blog";
mysql_select_db($database, $coection) or die ("<p class='error'>Sorry, we were unable to coect to the database.</p>");

Затем нам нужно получить наши сообщения в блоге из базы данных. Для этого мы создадим функцию, которая может принимать до двух аргументов. Мы будем перегружать их обоих; поэтому вы можете вызвать функцию с аргументами 0, 1 или 2.

function GetBlogPosts($inId=null, $inTagId=null)
{
}

Внутри нашей функции нам нужно проверить, какие аргументы были переданы, и создать наш MySQL-запрос соответственно.

function GetBlogPosts($inId=null, $inTagId =null)
{
    if (!empty($inId))
    {
    }
    else if (!empty($inTagId))
    {
    }
    else
    {
    }
}

Итак, что мы здесь делаем, спрашивает, не является ли каждый аргумент не пустым, причина, по которой мы используем пустую функцию вместо того, чтобы просто выполнять стандартное сравнение «! = Null», потому что пустой не только проверяет, равна ли переменная, но и пустым также (IE ""). Теперь мы напишем запрос в зависимости от того, какие переменные мы имеем. Если мы перейдем к сообщению в блоге, мы просто захотим этого единственного сообщения в блоге, если мы дадим функции inTagId, мы хотим, чтобы все сообщения имели этот тег, а в остальном мы просто хотим, чтобы все записи в блоге находились в нашей базе данных.

if (!empty($inId))
{
    $query = mysql_query("SELECT * FROM blog_posts WHERE id = " . $inId . " ORDER BY id DESC");
}
else if (!empty($inTagId))
{
    $query = mysql_query("SELECT blog_posts.* FROM blog_post_tags LEFT JOIN (blog_posts) ON (blog_post_tags.postID = blog_posts.id) WHERE blog_post_tags.tagID =" . $tagID . " ORDER BY blog_posts.id DESC");
}
else
{
    $query = mysql_query("SELECT * FROM blog_posts ORDER BY id DESC");
}

Следующий шаг - обработать данные, возвращаемые из каждого запроса, создать объекты, а затем добавить их в возвращаемый массив.

$postArray = array();
while ($row = mysql_fetch_assoc($query))
{
    $myPost = new BlogPost($row["id"], $row['title'], $row['post'], $row['postfull'], $row['firstname'] . " " . $row['lastname'], $row['dateposted']);
    array_push($postArray, $myPost);
}
return $postArray;

Вот полный код include.php:

<?php
include 'blogpost.php';
$coection = mysql_coect('localhost', 'username', 'password') or die ("<p class='error'>Sorry, we were unable to coect to the database server.</p>");
$database = "nettuts_blog";
mysql_select_db($database, $coection) or die ("<p class='error'>Sorry, we were unable to coect to the database.</p>");
function GetBlogPosts($inId=null, $inTagId =null)
{
    if (!empty($inId))
    {
        $query = mysql_query("SELECT * FROM blog_posts WHERE id = " . $inId . " ORDER BY id DESC");
    }
    else if (!empty($inTagId))
    {
        $query = mysql_query("SELECT blog_posts.* FROM blog_post_tags LEFT JOIN (blog_posts) ON (blog_post_tags.postID = blog_posts.id) WHERE blog_post_tags.tagID =" . $tagID . " ORDER BY blog_posts.id DESC");
    }
    else
    {
        $query = mysql_query("SELECT * FROM blog_posts ORDER BY id DESC");
    }
    $postArray = array();
    while ($row = mysql_fetch_assoc($query))
    {
        $myPost = new BlogPost($row["id"], $row['title'], $row['post'], $row['postfull'], $row["author_id"], $row['dateposted']);
        array_push($postArray, $myPost);
    }
    return $postArray;
}
?>

Теперь мы можем перейти к отображению наших данных, открыть наш файл index.php и настроить базовую HTML-страницу. Внутри нашего тела мы создадим раздел с идентификатором «main», который будет содержать наш блог. Мы дадим нашему блогу название, а затем добавим второй div внутри основного, который будет называться «blogPosts».

<div id="main">
    <h1>My Simple Blog</h1>
    <div id="blogPosts">
    </div>
</div>

Внутри нашего blogPosts div мы добавим некоторый PHP, чтобы мы могли отображать наши сообщения. Сначала мы собираемся включить наш файл include.php, а затем назовем нашу функцию GetBlogPosts без аргументов, чтобы получить все наши сообщения в блоге и установить их в массив под названием blogPosts.

<?php
include 'includes/includes.php';
$blogPosts = GetBlogPosts();
?>

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

foreach ($blogPosts as $post)
{
}

Внутри цикла мы используем $ post в качестве текущего элемента массива, и поскольку $ blogPosts представляет собой массив объектов BlogPost, мы можем просто использовать «->» для доступа к каждому требуемому нам свойству. Давайте начнем с простого повторения заголовка каждого сообщения в блоге на нашей странице и просто добавим
- в качестве примера.

foreach ($blogPosts as $post)
{
    echo $post->title . "<br/>";
}

Если мы перейдем к нашей базе данных и вставим некоторые поддельные данные, тогда откройте index.php в браузере, мы получим что-то вроде этого:

Давайте действительно будем строить наши сообщения в HTML. Каждый пост будет завернут в div с классом «post». Тогда у нас будет заголовок сообщения внутри тега h1 и фактического сообщения внутри тега

.

foreach ($blogPosts as $post)
{
    echo "<div class='post'>";
    echo "<h2>" . $post->title . "</h2>";
    echo "<p>" . $post->post . "</p>";
    echo "</div>";
}

Давайте также дадим каждому сообщению нижний колонтитул, в который войдут автор сообщения, дата публикации и теги сообщения. Мы поместим всю эту информацию в тег span с классом «footer».

foreach ($blogPosts as $post)
{
    echo "<div class='post'>";
    echo "<h1>" . $post->title . "</h1>";
    echo "<p>" . $post->post . "</h1>";
      echo "<span class='footer'>Posted By: " . $post->author . " Posted On: " . $post->datePosted . " Tags: " . $post->tags . "</span>";
    echo "</div>";
}

Теперь давайте посмотрим наш файл index.php снова в браузере:

Похоже, все работает! Затем добавим стиль.

Намного лучше; вы можете просмотреть это онлайн здесь или нажать большие кнопки «demo». Это для этого урока. В следующем учебном пособии мы добавим больше функциональности в наш блог, включая некоторые приятные функции AJAX!

Надеюсь, теперь у вас есть лучшее понимание того, как работает объектно-ориентированное программирование. Даже если вы в конечном итоге делаете большую часть своего развития, используя структуру, очень важно иметь основное понимание основ. Если у вас есть какие-либо конкретные вопросы об этом учебнике, не стесняйтесь чирикать мне @benemills. Я хотел бы поблагодарить Джеймса Падольси за помощь в этой статье.

Следите за частью 2!

Подписаться на RSS-канал NETTUTS для более ежедневных веб-разработок tuts и articles.