Создание простого блога на MongoDB и PHP
Введение
Если вы хотите создать блог с использованием MongoDB и PHP, то эта статья поможет вам понять, как:
- Соединяться с базой данных MongoDB;
- Сохранять документы в коллекцию;
- Запрашивать документы из коллекции;
- Выполнять запросы ранжирования;
- Сортировать и обновлять документы, а также удалять один или более документов из коллекции.
Причина, по которой я выбрал именно блог, заключается в том, что это простейшее CRUD-приложение, позволяющее освоить основы веб-разработки с использованием связки PHP и MongoDB.
Мы создадим простой пользовательский интерфейс с помощью Bootstrap, используя текстовые поля и кнопки. Все данные будут храниться в базе MongoDB.
Вы можете скачать полные исходники, увидеть демо фронтэнда и бэкэнда (имя пользователя и пароль будут duythien).
Что такое MongoDB?
Согласно официальному сайту MongoDB это документо-ориентированная СУБД без SQL, которой свойственна высокая производительность, доступность и легкая масштабируемость. Список остальных СУБД подобного типа вы можете увидеть здесь.
Концепция MongoDB: базы данных, коллекции и документы
- База данных. MongoDB объединяет информацию в базы данных так же, как это делают реляционные БД. Если вы знакомы с реляционными базами данных, то думайте о документо-ориентированных БД так же. В реляционных СУБД (RDBMS) база данных состоит из таблиц, хранимых процедур, представлений и так далее. В MongoDB база данных состоит из коллекций. База данных MongoDB может включать в себя одну или более коллекций. Например, база данных для блога под именем blog может включать в себя следующие коллекции: статьи, авторы, комментарии, категории и тому подобное;
- Коллекция эквивалентна таблице в реляционной СУБД. Коллекция создается внутри базы данных. Документы внутри коллекции могут иметь различные поля. Как правило, все документы в коллекции имеют похожее назначение;
- Документ это запись в коллекции MongoDB и базовый элемент данных в MongoDB. Документы аналогичны объектам JSON, но имеют расширенный формат, известный как BSON. Документ включает в себя набор полей или пар ключ-значение. Думайте о документе, как о многомерном массиве. В массиве у вас есть набор ключей, привязанных к значениям (документ == массив). Смотрите документацию.
Установка MongoDB
MongoDB запускается на большинстве платформ и поддерживает 32- и 64-битную архитектуру. MongoDB доступна, как в исходных кодах, так и виде установочного пакета. В условиях разработки используются исходники MongoDB в 64-битном формате.
В этой части статьи будет рассказано как установить БД на Ubuntu Linux и Windows. Для остальных операционных систем смотрите документацию.
Рассмотрим сначала установку MongoDB на Ubuntu Linux. Откройте терминал и выполните следующие команды:
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
#
echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list
Далее следует команда для обновления репозитория и установки крайней стабильной версии MongoDB:
sudo apt-get update
sudo apt-get install mongodb-10gen
После этого установка MongoDB завершена. Теперь перезапустите сервис MongoDB через командную строку так, как показано ниже:
sudo service mongodb start
sudo service mongodb stop
Если при запуске произошла ошибка, то попробуйте выполнить следующую команду:
sudo mongod --fork --logpath /var/log/mongodb/mongodb.log
#or
sudo mongod -f /etc/mongodb.conf
Теперь опишем установку MongoDB на Windows:
Перейдите на страницу загрузок на официальном сайте MongoDB и скачайте крайнюю стабильную версию для Windows.
После окончания загрузки, извлеките и поместите содержимое архива на диск C:. MongoDB требует наличия папки данных, в которой должны содержаться все файлы.
Стандартное расположение для MongoDB это папка данных, находящаяся по адресу C:datadb. Если её не существует, то создайте.
Для запуска MongoDB, наберите в командной строке:
C:> cd mongodbbin
C:mongodbbin> mongod
Итак, MongoDB установлена! Теперь перезапустите сервис MongoDB:
net start MongoDB
net stop MongoDB
Установка драйвера PHP для MongoDB
Сервер MongoDB уже настроен на работу с текущим веб-сервером, но не поддерживает PHP. Чтобы «рассказать» серверу MongoDB о PHP, нам нужно установить драйвер PHP-MongoDB. Это библиотека для PHP.
Если вы используете Linux, то инсталляция гениально проста:
sudo pecl install mongo
Добавьте строку extension=mongo.so в файл конфигурации php.ini, а затем запустите:
sudo –i
echo 'extension=mongo.so' >> /etc/php5/apache2/php.ini
Перезапустите веб-сервер и выполните:
php -i |grep "mongo"
php --re mongo
Установка драйвера для Windows
Установим драйвер на Windows-машину с PHP 5.4 и сервером Apache (XAMPP):
- Скачайте ZIP-архив и извлеките его содержимое;
- Скопируйте файл php_mongo.dll из извлеченных данных в директорию с расширениями PHP (C:xamppphpext);
- Откройте файл php.ini внутри папки с PHP и добавьте в него следующую строку: extension=php_mongo.dll;
- Сохраните файл и закройте его. Перезапустите XAMP;
- Откройте текстовый редактор и добавьте следующий код в новый файл: <?php phpinfo();?>, сохраните файл под именем phpinfo.php внутри DocumentRoot сервера Apache (речь идет о папке htdocs) и откройте данный скрипт в браузере. Если увидите среди выведенной информации mongo, значит установка прошла успешно.
Веб-разработка с Mongo и PHP
Соединение с сервером баз данных MongoDB
Подключение к MongoDB из PHP очень похоже на подключение к любой другой базе данных. Хостом по умолчанию является localhost, а портом - 27017:
$connection = new Mongo();
Подключение к удаленному хосту с определенным логином и портом выполняется так:
$connecting_string = sprintf('mongodb://%s:%d/%s', $hosts, $port,$database), $connection= new Mongo($connecting_string,array('username'=>$username,'password'=>$password));
Выбор базы данных
Как только связь с базой данных установлена, мы получаем доступ к базе данных. Сделать это можно так:
$dbname = $connection->selectDB('dbname');
Основы (CRUD-операции)
MongoDB предоставляет хорошие возможности для чтения и манипуляции данными. CRUD расшифровывается как: create - создание, read - чтение, update - обновление и delete - удаление. Эти термины являются основой для взаимодействий с базой данных.
Создание/выбор коллекции
Создание и выбор коллекции очень похож на получение доступа и создание базы данных. Если коллекция не создана, то сделать это можно так:
$collection = $dbname->collection;
//or
$collection = $dbname->selectCollection('collection');
Например, следующая команда создаст коллекцию «posts» в моем блоге:
$posts = $dbname->posts
Создание документа
Создать документ в MongoDB очень просто. Создается массив. Переводится в метод insert для объекта коллекции:
$post = array(
'title' => 'Что такое MongoDB',
'content' => 'MongoDB это высокопроизводительная документо-ориентированная база данных...',
'saved_at' => new MongoDate()
);
$posts->insert($post);
Метод insert() сохраняет данные в коллекцию. Массив $post автоматически получает поле с именем _id, содержащее уникальный сгенерированный ObjectId для вставленного BSON-документа.
Вы также можете использовать метод save(), который обновляет существующую запись или создает новую, если её еще не существует.
Чтение документа
Чтобы получить данные из коллекции, я использую метод find(), который получает все данные из коллекции. Метод findOne() возвращает только один документ, удовлетворяющий определенному в запросе критерию.
Следующие примеры показывают, как запросить одну или несколько записей:
// all records
$result = $posts::find();
// one record
$id = '52d68c93cf5dc944128b4567';
$results = $posts::findOne(array('_id' => new MongoId($id)));
Обновление документа
Перейдем к модификации существующего документа или документа в коллекции. По умолчанию, метод update() обновляет одиночный документ.
Если задана опция multi в значении true, то метод будет обновлять все документы, удовлетворяющие выбранному критерию:
$id = '52d68c93cf5dc944128b4567';
$posts->update(
array('_id' => new MongoId($id)),
array('$set' => array(title' => Что такое Фалькон?'))
);
Метод update() принимает два параметра. Первый это критерий, описывающий объекты, которые нужно обновить, а второй – объект, которым нужно заменить объекты удовлетворяющие условиям записи.
Имеется также третий опциональный параметр, через который вы можете передать массив вариантов.
Мини-блог
Вот так будет выглядеть структура нашего будущего проекта:
|-------admin
|------index.php # Это административная панель
|------auth.php
|-------view
|------admin
|-------create.view.php # форма создания статьи
|-------dashbroad.view.php
|------index.view.php
|------layout.php # основной шаблон, используемый для отображения результатов каждого действия приложения
|------single.view.php # Это шаблон для одиночной статьи
|-------config.php # Определение параметров БД
|-------app.php # Подключение multi-php файлов
|-------db.php # Контейнер класса db
|-------index.php
|-------single.php
|-------static # Контейнер css,js...
|-----css
|-----js
|-------vendor
|----markdown # Библиотека, конвертирующая разметку в html
Перед началом работы, создайте структуру файлов и папок, как показано выше.
config.php
Это главный конфигурационный файл проекта, который говорит, как подключаться к базе данных. Здесь также определены имя, логин и пароль пользователя для доступа к базе:
<?php
define('URL', 'http://duythien.dev/sitepoint/blog-mongodb');
define('UserAuth', 'duythien');
define('PasswordAuth', 'duythien');
$config = array(
'username' => 'duythien',
'password' => 'qazwsx2013@',
'dbname' => 'blog',
'connection_string'=> sprintf('mongodb://%s:%d/%s','127.0.0.1','27017','blog')
);
В этом коде мы определяем параметры UserAuth и PasswordAuth для защиты папки admin через HTTP-аутентификацию.
Здесь мы используем HTTP-аутентификацию для простоты, чтобы сконцентрироваться на главной задаче данной статьи – подключении к MongoDB. Для настройки уровней доступа, можно воспользоваться фреймворком с ACL.
Содержание файла app.php:
<?php
include 'config.php';
include 'layout.php';
include 'db.php';
use BlogDB,
BlogLayout;
// конструктор для db
$db = new DBDB($config);
// конструктор для представления
$layout = new LayoutLayout();
Административная часть
Эта папка включает в себя CRUD-код:
<?php
require_once 'auth.php';
require_once '../app.php';
require_once '../vendor/markdown/Markdown.inc.php';
use MichelfMarkdownExtra,
MichelfMarkdown;
if ((is_array($_SESSION) && $_SESSION['username'] == UserAuth)) {
$data = array();
$status = (empty($_GET['status'])) ? 'dashboard' : $_GET['status'];
switch ($status) {
// создание записи
case 'create':
break;
// редактирование записи
case 'edit':
break;
// удаление записи
case 'delete':
// отображение всех записей на контрольной панели
default:
$currentPage = (isset($_GET['page'])) ? (int)$_GET['page'] : 1;
$data = $db->get($currentPage, 'posts');
$layout->view('admin/dashboard', array(
'currentPage' => $data[0],
'totalPages' => $data[1],
'cursor' => $data[2]
));
break;
}
}
Полный текст файла index.php смотрите здесь. Выше я использовал функцию view, определенную в классе layout.php, которая автоматически загружает dashboard.view.php:
<?php namespace BlogLayout;
Class Layout
{
/**
* @var array
*/
public $data;
public function view($path, $data)
{
if (isset($data)) {
extract($data);
}
$path .= '.view.php';
include "views/layout.php";
}
}
GET-параметр status соответствует CRUD-действию. Например, когда статус он имеет значение “create”:
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$article = array();
$article['title'] = $_POST['title'];
$article['content'] = Markdown::defaultTransform($_POST['content']);
$article['saved_at'] = new MongoDate();
if (empty($article['title']) || empty($article['content'])) {
$data['status'] = 'Пожалуйста, заполните оба поля.';
} else {
// затем создаем новую строку в коллекции posts
$db->create('posts', $article);
$data['status'] = 'Строка была успешно вставлена.';
}
}
$layout->view('admin/create', $data);
Функция view(‘admin/create’, $data) показывает HTML-форму, в которой пользователь может ввести название/содержание нового поста в блоге, которое сохранится в MongoDB. По умолчанию скрипт отображает вот такую форму:
<form action="" method="post">
<div><label for="Title">Заголовок</label>
<input type="text" name="title" id="title" required="required"/>
</div>
<label for="content">Содержание</label>
<p><textarea name="content" id="content" cols="40" rows="8" class="span10"></textarea></p>
<div class="submit"><input type="submit" name="btn_submit" value="Сохранить"/></div>
</form>

Теперь разберемся с файлом db.php, полную версию которого можно найти здесь.
<?php
namespace BlogDB;
class DB
{
/**
* Return db
* @var object
*/
private $db;
/**
* Results limit.
* @var integer
*/
public $limit = 5;
public function __construct($config)
{
$this->connect($config);
}
//подключение к mongodb
private function connect($config)
{
}
//получение всех данных
public function get($page, $collection)
{
}
//получение данных по id
public function getById($id, $collection)
{
}
//создание статьи
public function create($collection, $article)
{
}
//удаление статьи по id
public function delete($id, $collection)
{
}
//обновление статьи
public function update($id, $collection, $acticle)
{
}
//создание и обновление комментария
public function commentId($id, $collection, $comment)
{
}
}
Методы-курсоры MongoDB делают постраничную навигацию (пагинацию) достаточно простой. Комбинирование методов limit и skip очень в этом помогает. Также можно скомбинировать с методом order. Например:
public function get($page,$collection){
$currentPage = $page;
$articlesPerPage = $this->limit;
//число статей, которые нужно пропустить сначала
$skip = ($currentPage - 1) * $articlesPerPage;
$table = $this->db->selectCollection($collection);
$cursor = $table->find();
//общее число статей в базе данных
$totalArticles = $cursor->count();
//общее число страниц для отображения
$totalPages = (int) ceil($totalArticles / $articlesPerPage);
$cursor->sort(array('saved_at' => -1))->skip($skip)->limit($articlesPerPage);
$data=array($currentPage,$totalPages,$cursor);
return $data;
}
index.php: файлы шаблонов могут быть найдены в папке view; например, index.view.php. Ниже приведен пример файла index.php:
<?php
require 'app.php';
try {
$currentPage = (isset($_GET['page'])) ? (int)$_GET['page'] : 1; //текущий номер страницы
$data = $db->get($currentPage, 'posts');
$layout->view('index', array(
'currentPage' => $data[0],
'totalPages' => $data[1],
'cursor' => $data[2],
'name' => 'Duy Thien'
));
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "n";
}
Откройте браузер и введите в адресной строке http://duythien.dev/sitepoint/blog-mongodb. Это отобразит список всех статей в блоге:

single.php: когда вы просматриваете страницу с постом (нажмите кнопку «Читать далее..»), то используется файл single.view.php из папки views.
Вот логика работы шаблона single.php:
<?php
require 'app.php';
// получение поста
$post = $db->getById($_GET['id'], 'posts');
if ($post) {
$layout->view('single', array(
'article' => $post
));
}
Этот файл получает _id статьи через HTTP GET-параметр. Мы вызываем метод findOne() для коллекции articles, передавая ему значение _id в качестве параметра. Метод findOne() используется для запроса одиночного документа.
Смотрите функцию getById() в файле db.php:

Введите произвольное имя и e-mail в соответствующие поля ввода под секцией комментариев, и заполните текстовое поле самим комментарием.
Затем кликните по кнопке «Сохранить» и страница перезагрузится, отобразив добавленный вами комментарий.
Вот так выглядит файл comment.php:
<?php
require 'app.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$id = $_POST['article_id'];
$comment = array(
'name' => $_POST['fName'],
'email' => $_POST['fEmail'],
'comment' => $_POST['fComment'],
'posted_at' => new MongoDate()
);
$status = $db->commentId($id, 'posts', $comment);
if ($status == TRUE) {
header('Location: single.php?id=' . $id);
}
}
Комментарии к статье хранятся в виде массива в поле документа под названием comments. Каждый комментарий является документом, содержащим несколько полей.
Заключение
В данной статье, мы описали процесс создания простейшего CRUD-приложения на PHP и MongoDB. Мы даже использовали примитивный MVC-подход при разработке (смотрите полный пример на Github).
На ваши плечи ложится ответственность за использование фреймворка для более надежной аутентификации посредством HTTP, добавление дополнительного функционала, но основные вещи уже реализованы и вы можете использовать приведенный пример для своего блога, наполнив его контентом.
Для подробной информации о MongoDB обратитесь к документации. Надеюсь, данная статья оказалась полезной для вас!