PHP
2 January 2012

Пишем свой блог с фреймворком Fat-Free Framework

Original author: Richard
Translation Tutorial
На всякий случай — это перевод (многие не замечают этого в интерефейсе ХабраХабра).
«Fat-Free» можно перевести с английского как «Обезжиренный» — фреймворк и в самом деле поражает своим размером (55 КБ) и скоростью работы.


Я наконец-то нашёл лёгкий и быстрый фреймворк. Он умещается в файл размером всего 55Кб и имеет множество возможностей, о которых вы можете узнать на его официальном сайте, поэтому не буду повторяться. Вместо этого я решил сделать небольшой учебник, из которого вы узнаете как сделать свой блог на этом фреймворке.
Вам понадобится PHP 5.3 на сервере. Я использовал Ubuntu 11.04 для написания этого учебника, на которую легко устанавливается эта версия. Если вы работаете на RHEL или Centos то я предлагаю заглянуть вам на IUS Community Project для получения последней версии PHP.

Установка


Скачайте Fat-Free Framework.
Fat-Free Framework работает одинаково хорошо и в корне сайта, и в подкаталоге. Я предполагаю, что вы будете использовать подкаталог, поскольку вам не нужно будет создавать отдельный сайт для этого урока.
Создайте папку с именем blog и распакуйте содержимое фреймворка в неё. Это должно выглядеть примерно так:



Поднимитесь на один уровень вверх в иерархии каталогов и установите следующие разрешения:

sudo chgrp -R www-data blog
sudo chmod -R 775 blog

Если вы используете Apache, то mod_rewrite должен быть включён. Измените .htaccess и откорректируйте RewriteBase так, чтобы он указывал на папку с блогом. Например: RewriteBase /blog.

Уже сейчас вы можете зайти в папку blog на сервере и увидеть такую страницу:



(Как только вы посетите эту страницу, будет будет создана специальная папка с кешем — не беспокоитесь об этом).

Начало


Всё что нам нужно уже есть в Fat-Free Framework.

Давайте сначала отредактируем главную страницу и создадим подключение к базе данных.

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

<?php
 
require __DIR__.'/lib/base.php';
 
//F3::set('CACHE',TRUE);
F3::set('DEBUG',3);
F3::set('UI','ui/');
 
F3::run();
 
?>

Для установки соединения с базой данных добавьте следующее между командами set и run:

F3::set('DB',
	new DB(
		'mysql:host=localhost;port=3306;dbname=ИмяВашейБазыДанных',
		'ИмяПользователя',
		'Пароль'
	)
);

Все файлы пользовательского интерфейса находятся в каталоге ui — вы можете удалить welcome.htm и style.css отсюда, так как они просто используются домашней страницей по-умолчанию.

Маршрутизация


Вы должны сказать фреймворку метод запроса (GET, POST, PUT и т.д.), адрес для запроса и как ответить на этот запрос.

Маршрут для домашней страницы:

F3::route('GET /',
	function () {
	// делаем что-нибудь
	}
);

Эта безымяная функция будет содержать логику для заполнения страницы.

Для просмотра записи блога:

F3::route('GET /view/@id',
	function () {
		$id = F3::get('PARAMS["id"]');
	}
);

Это позволяет фреймворку ожидать URI-параметр и присваивает его переменной PHP в функции.

Теперь маршруты для администратора:

// Главная страница администратора
F3::route('GET /admin',
	function () {	
	}
);
 
// Страница для добавления материала
F3::route('GET /admin/add',
	function() {
	}
);
 
// Для редактирования материала
F3::route('GET /admin/edit/@id',
	function() {
		$id = F3::get('PARAMS["id"]');
	}
);
 
// Служебная для принятия запросов
F3::route('POST /admin/edit/@id','edit');
F3::route('POST /admin/add','edit');
	function edit() {
 
	}
 
// Для удаления
F3::route('GET /admin/delete/@id',
	function() {
		$id = F3::get('PARAMS["id"]');
	}
);

Обратите внимание, что мы используем одну и ту же функцию для обработки добавления и редактирования сообщений, по этому она имеет имя (остальным функциям имена можно не давать).

Модели


ORMs в Fat-Free Framework делает всю грязную работу за вас — никаких директорий, файлов или кода.

Вот SQL запрос, который создаст 2 таблицы, необходимые для этого урока:

ХабраХабр почему-то не хочет красить этот кусок — прим. перев.

CREATE DATABASE `blog` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
 
USE `blog`;
 
CREATE TABLE IF NOT EXISTS `article` (
  `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `timestamp` datetime NOT NULL,
  `title` VARCHAR(128) NOT NULL,
  `summary` VARCHAR(128) NOT NULL,
  `content` text NOT NULL,
  `author` VARCHAR(128) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
 
INSERT INTO `article` (`id`, `timestamp`, `title`, `summary`, `content`, `author`) VALUES
(1, '2011-07-28 02:03:14', 'Hello World!', 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut ', 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', 'Mr White'),
(2, '2011-07-28 02:03:14', 'More Hello World!', 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut ', 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', 'Mr Green');
 
CREATE TABLE IF NOT EXISTS `user` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(255) NOT NULL,
  `password` VARCHAR(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
 
INSERT INTO `user` (`id`, `name`, `password`) VALUES
  ('1', 'admin', 'password');


Для посетителей


Теперь нам необходимо создать экземпляр объекта Axon, чтобы получить массив результатов. Также мы установим полученное значение в переменную articles.

	$article=new Axon('article');
	$articles=$article->afind();
	F3::set('articles',$articles);

Вы бы могли объединить последнии 2 строчки в одну F3::set('articles',$article->afind());, но для удобства я оставил две.

Для использования шаблонов нужно создать базовый файл макета в папке ui с именем layout.html:

<!DOCTYPE html>
<html>
   <head>
      <title>{{@html_title}}</title>
      <meta charset='utf8' />
   </head>
   <body>
      <F3:include href="{{@content}}"/>
   </body>
</html>

Движок использует шаблон {{@имя}} для получения значения переменной.

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

<p>Blog Titles</p>
<F3:repeat group="{{@list}}" value="{{@item}}">
	<p><a href="view/{{@item['id']}}">{{trim(@item['title'])}}</a> by {{@item['author']}}</p>
	<p>{{@item['summary']}}</p>
</F3:repeat>

Теперь, когда шаблон готов, мы можем завершить код в index.php для его отображения:

	F3::set('content','blog_home.html');
	echo Template::serve('layout.html');

Шаблон для ускорения работы приложения будет переделан движком в php код.

Полный пример будет выглядеть так:

F3::route('GET /',
	function () {
		F3::set('html_title','Home Page');
		$article=new Axon('article');
		F3::set('list',$article->afind());
		F3::set('content','blog_home.html');
		echo Template::serve('layout.html');	
	}
);

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

F3::route('GET /view/@id',
	function () {
		$id = F3::get('PARAMS["id"]');
		// создаём объект Axon и ищем в нём наш id
		$article=new Axon('article');
		$article->load("id='$id'");
		// устанавливаем переменные для шаблона
		F3::set('html_title',$article->title);
		$article->copyTo('POST');
		// подключаем сам шаблон
		F3::set('content','blog_detail.html');
		echo Template::serve('layout.html');
	}
);

Шаблон страницы будет находиться в файле blog_detail.html:

<h1>{{@POST.title}}</h1>
<p>Published: {{@POST.timestamp}} by {{@POST.author}}</p>
{{@POST.content}}
<p><a href='../'>Back to Homepage</a></p>

Для администратора


На главной странице администратора будут отображаться записи также, как и на главной. По этому код похожий:

F3::route('GET /admin',
	function () {
		F3::set('html_title','My Blog Administration');
		$article=new Axon('article');
		$list=$article->afind();
		F3::set('list',$list);
		F3::set('content','admin_home.html');
		echo Template::serve('layout.html');	
	}
);

Шаблон хранится в файле admin_home.html:

<!--перевёл этот шаблон, чтобы было понятнее-->
<h1>Панель администратора</h1>
<p><a href='admin/edit'>Добавить запись</a></p>
<table>
  <thead>
    <tr>
      <th>Заголовок</th>
      <th>Дата</th>
      <th>Автор</th>
      <th colspan='2'>Управление</th>
    </tr>
  </thead>
  <tbody>
  <F3:repeat group="{{@list}}" value="{{@item}}">
    <tr>
      <td>{{@item['title']}}</td>
      <td>{{@item['timestamp']}}</td>
      <td>{{@item['author']}}</td>
      <td><a href="admin/edit/{{@item['id']}}">Изменить</a></td>
      <td><a href="admin/delete/{{@item['id']}}">Удалить</a></td>
    </tr>
  </F3:repeat>
  </tbody>
</table>

Результат будет примерно такой:



Теперь создадим форму для редактирования и добавления записей в файле admin_edit.html:

<h1>Edit</h1>
<form name="blog" method="post" action="{{ @BASE }}{{ @PARAMS.0 }}" >
  <F3:check if="{{ @message }}">
    <p><span class="fail">{{ @message }}</span></p>
  </F3:check>
  <label for='title'>Title: </label><br /><input type="text" name="title" id="title" value="{{ htmlspecialchars(@POST.title) }}" size="60"/><br />
  <label for='author'>Author: </label><br /><input type="text" name="author" id="author" value="{{ htmlspecialchars(@POST.author) }}" size="60"/><br />
  <label for='summary'>Summary: </label><br /><textarea name="summary" id="summary" cols="60" rows="10">{{ htmlspecialchars(@POST.summary) }}</textarea><br />
  <label for='content'>Content: </label><br /><textarea name="content" id="content" cols="60" rows="10">{{ htmlspecialchars(@POST.content) }}</textarea><br />
  <input type="submit" value="Submit"/>
</form>

Обратите внимание, что есть области для отображения проверки сообщений.

Теперь код для маршрутов:

F3::route('GET /admin/add',
	function() {
		F3::set('html_title','My Blog Create');
		F3::set('content','admin_edit.html');
		echo Template::serve('layout.html');
	}
);
 
F3::route('GET /admin/edit/@id',
	function() {
		F3::set('html_title','My Blog Edit');
		$id = F3::get('PARAMS["id"]');
		$article=new Axon('article');
		$article->load("id='$id'");
		$article->copyTo('POST');
		F3::set('content','admin_edit.html');
		echo Template::serve('layout.html');
	}
);

Теперь напишем функцию для редактирования, о которой писалось ранее:

	function edit() {
		// Reset previous error message, if any
		F3::clear('message');
		$id = F3::get('PARAMS["id"]');
		$article=new Axon('article');
		//load in the article, set new values then save
		//if we don't load it first Axon will do an insert instead of update when we use save command
		if ($id) $article->load("id='$id'");
		//overwrite with values just submitted
		$article->copyFrom('POST');
		//create a timestamp in MySQL format
		$article->timestamp=date("Y-m-d H:i:s");
		$article->save();
		// Return to admin home page, new blog entry should now be there
		F3::reroute('/admin');
	}

Аутентификация


Добавьте следующие строчки:

// сообщаем фреймворку таблицу с пользователями и передаём значения
F3::set('AUTH',array('table'=>'user','id'=>'name','pw'=>'password'));

$auth = Auth::basic('sql');
// вход удачный
if ($auth) {
  // сохраняем в сессии
  F3::set('SESSION.user',$auth->name);
  // отображаем страницу администратора
  F3::set('content','admin_home.html');
} else {
  // вход неудачный
	F3::set('content','security.html');
}

security.html может выглядеть так:

<p>You must supply valid login details.</p>


Ещё добавьте строчку перед Template::serve:

if (!F3::get('SESSION.user')) F3::set('content','security.html');

Вот и всё. Вы также можете перенаправить пользователя на главную страницу:

if (!F3::get('SESSION.user')) F3::reroute('/');

Итог


Вот так просто можно написать блог с панелью администратора и базой данных.

Скачать готовый пример можно тут — blog.zip

+30
21.2k 245
Comments 74
Top of the day