В этом уроке:
Мы разработаем контроллер новости
Добавим к нашей cms на CodeIgniter визуальный редактор FCKEditor
Встроим JQuery календарь Datepicker
В прошлых уроках я начал делать сайт в UTF-8 кодировке, но не везде придерживался этого. Поэтому получилось некоторое несоответствие. В конце урока будет ссылка на результат этого урока (там в архиве все в правильной кодировке). Для того чтобы сделать сайт в UTF-8 необходимо придерживаться трех правил:
кодировка в БД
кодировка всех страниц в UTF-8
Добавить AddDefaultCharset utf-8 в .htaccess
В разделе head указать
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Начинаем с создания таблицы:
DROP TABLE IF EXISTS `cm_news`;
CREATE TABLE `cm_news` (
`id` INT(10) NOT NULL AUTO_INCREMENT,
`title` VARCHAR(255) DEFAULT NULL,
`date` DATE DEFAULT NULL,
`anons` text,
`content` text,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
Создаем базовую модель CRUD.
В этой модели мы реализуем 4 основных функции:
Добавление в БД. (данные будут поступать из формы)
Редактирование записей в БД. (данные будут поступать из формы)
Удаление записей БД.
Вывод списка записей.
Вывод одной записи.
Плюс мне пришлось сделать 2 дополнительных функции. Т.к. я использовал календарь Datepicker, мне пришлось сделать преобразование (туда/обратно) даты из формата 01.10.2010 в формат MySQL 2010-10-01.
Листинг файла CRUD.php с комментариями.
<?php
/**
* @author allexe
* @copyright 2010
* 26.8.2010
* Описание файла: Общая модель для работы с БД
*/
if (!defined('BASEPATH')) exit('No direct script access allowed');
class Crud extends Model
{
var $table = ''; //Имя таблицы
var $idkey = 'id'; //Ключ ID
var $add_rules = array(); //Правила валидации для добавления
var $edit_rules = array(); //Правила валидации для редактирования
//Конструктор
function Crud()
{
parent::Model();
}
/**
* Функция для добавления
*/
function add()
{
//Проверяем прошли ли переданные формой данные правила валидации
$this->form_validation->set_rules($this->add_rules);
if ($this->form_validation->run()) {
$data = array();
foreach ($this->add_rules as $one) {
//Для каждого поля описанного в правилах валидации получаем
//значение. Имя поля в форме соответствует имю поля в БД.
//Для даты выполняем преобразование.
$f = $one['field'];
if ($f == 'date') {
$date = $this->input->post($f);
$data[$f] = $this->date_to_mysql($date);
} else {
$data[$f] = $this->input->post($f);
}
}
//Вставляем массив с данными из формы в БД
$this->db->insert($this->table, $data);
return $this->db->insert_id(); //Возвращает номер
} else {
return false;
}
}
/**
* Функция для редактирования
*/
function edit($id)
{
$this->form_validation->set_rules($this->edit_rules);
if ($this->form_validation->run()) {
$data = array();
foreach ($this->edit_rules as $one) {
$f = $one['field'];
if ($f == 'date') {
$date = $this->input->post($f);
$data[$f] = $this->date_to_mysql($date);
} else {
$data[$f] = $this->input->post($f);
}
}
$this->db->where($this->idkey, $id);
$this->db->update($this->table, $data);
return $data; //Возвращает вставленные данные
} else {
return false;
}
}
/**
* Функция удаления
*/
function del($id)
{
$this->db->where($this->idkey, $id);
$this->db->delete($this->table);
}
/**
* Получение данных
*/
function get($id)
{
$this->db->where($this->idkey, $id);
$query = $this->db->get($this->table);
$rez = $query->row_array();
foreach ($rez as $key => $value) {
if ($key == 'date') {
$rez['date'] = $this->mysql_to_date($value);
}
}
return $rez;
}
/**
* Получение списка
* $start_from - выбирать с этой записи
* $limit - количество выбираемых записей
*/
function getlist($start_from = false, $limit = false)
{
if (($start_from) & ($limit)) {
$this->db->limit($limit, $start_from);
} elseif ($limit) {
$this->db->limit($limit);
}
$query = $this->db->get($this->table);
$rez = $query->result_array();
for ($i = 0; $i < count($rez); $i++) {
$one = $rez[$i];
foreach ($one as $key => $value) {
if ($key == 'date') {
$rez[$i]['date'] = $this->mysql_to_date($value);
}
}
}
return $rez;
}
/**
* Преобразует дату в формат MySql
*/
function date_to_mysql($str)
{
$day = substr($str, 0, strpos($str, '.'));
$str = substr($str, strpos($str, '.') + 1);
$month = substr($str, 0, strpos($str, '.'));
$year = substr($str, strrpos($str, '.') + 1);
$mysql_date = $year . '-' . $month . '-' . $day;
return $mysql_date;
}
/**
* Преобразует дату формате MySql в формат 01.10.2010
*/
function mysql_to_date($str)
{
$year = substr($str, 0, strpos($str, '-'));
$str = substr($str, strpos($str, '-') + 1);
$month = substr($str, 0, strpos($str, '-'));
$day = substr($str, strrpos($str, '-') + 1);
$date = $day . '.' . $month . '.' . $year;
return $date;
}
}
?>
Основная работа с БД в CodeIgniter осуществляется через класс Database ($this->db->). Рекомендую прочитать более подробно про Класс Active Record.
Создаем модель mdl_news.
Эта модель будет включать всего несколько переменных для передачи их в родительскую модель CRUD. Это: название таблицы, название ключевого поля, массивы с правилами валидации при добавлении и редактировании.
<?php
/**
* @author allexe
* @copyright 2010
* 26.8.2010
* Описание файла: Модель для работы с таблицей новостей
*/
if (!defined('BASEPATH')) exit('No direct script access allowed');
class mdl_news extends CRUD
{
var $table = 'news'; //Имя таблицы
var $idkey = 'id';
var $add_rules = array(array('field' => 'title', 'label' => 'Заголовок новости',
'rules' => 'required|max_length[255]'), array('field' => 'date', 'label' =>
'Дата новости', 'rules' => 'required'), array('field' => 'anons', 'label' =>
'Анонс новости', 'rules' => 'required'), array('field' => 'content', 'label' =>
'Текст новости', 'rules' => 'required'));
var $edit_rules = array(array('field' => 'title', 'label' => 'Заголовок новости',
'rules' => 'required|max_length[255]'), array('field' => 'date', 'label' =>
'Дата новости', 'rules' => 'required'), array('field' => 'anons', 'label' =>
'Анонс новости', 'rules' => 'required'), array('field' => 'content', 'label' =>
'Текст новости', 'rules' => 'required'));
}
?>
Про то, как работает валидации уже обсуждалось в Уроке 5.
Перейдем к созданию видов.
Вид admin/news (список новостей):
Просто выводим таблицу со списком заголовков новостей, датами и ссылкой на удаление новости. Каждый заголовок является ссылкой на редактирование новости.
<h2>Список новостей</h2>
<?=anchor(base_url().'admin/news/add','Добавить новость');?>
<table border="0" width="400" cellspacing="4">
<tr><td>Дата новости</td><td>Заголовок</td><td>Удалить</td></tr>
<?php foreach($list as $one):?>
<tr><td><?=$one['date'];?></td><td><?=anchor(base_url().'admin/news/edit/'.$one['id'],$one['title']);?></td><td><?=anchor(base_url().'admin/news/del/'.$one['id'],'X');?></td></tr>
<?endforeach;?>
</table>
base_url() и anchor() — это функции хелпера URL. Из формируемых ссылок видно, что добавление новостей будет происходить в функции add контроллера admin/news, редактирование edit, удаление del.
В файл вида передается массив с данными о новостях из контроллера news содержащийся в переменной list. Процесс обработки (когда пользователь заходит по адресу cms.ru/admin/news/ выглядит так:
Создание вида admin/one_news
Для редактирования и добавления новостей я использовал один вид. В файл вида передается переменная $type. В зависимости от ее значения несколько меняется отображение. Файл вида состоит из формы включающей 4 поля: 2 input (для даты и заголовка новости), 2 textarea для анонса и полного текста новости.
Содержание файла вида admin/one_news
<?=$validation_errors;?>
<?php if ($type=='add'): ?>
<?=form_open ('admin/news/add'); ?>
<?php elseif ($type=='edit'): ?>
<?=form_open ('admin/news/edit/'.$one['id']); ?>
<?php endif;?>
<table border="0" width="400" cellspacing="4">
<tr>
<td>Дата новости</td><td><input type="text" name="date" class="datepicker" value="<?=set_value ('date',($type == 'edit')? $one['date']: '')?>"></td>
</tr>
<tr>
<td>Заголовок</td><td><input type="text" name="title" value="<?=set_value ('title',($type == 'edit')? $one['title']: '')?>"></td>
</tr>
<tr>
<td colspan="2">Анонс</td>
</tr>
<tr>
<td colspan="2">
<?php if ($type=='add'): ?>
<textarea id="anons" name="anons" class="anons" cols="80" rows="5"><?=set_value ('anons')?></textarea>
<?php elseif ($type=='edit'): ?>
<textarea id="anons" name="anons" class="anons" cols="80" rows="5"><?=set_value ('anons',$one['anons'])?></textarea>
<?php endif;?>
</tr>
<tr>
<td colspan="2">Полный текст новости</td>
</tr>
<tr>
<td colspan="2">
<?php if ($type=='add'): ?>
<textarea id="content" name="content" class="content" cols="150" rows="50"><?=set_value ('content')?></textarea>
<?php elseif ($type=='edit'): ?>
<textarea id="content" name="content" class="content" cols="150" rows="50"><?=set_value ('content',$one['content'])?></textarea>
<?php endif;?>
</td>
</tr>
<tr>
<td align="left">
<input type="submit" value="<?=($type == 'edit')? 'Изменить': 'Добавить';?>">
</td>
<td></td>
</tr>
</table>
</form>
<?=show_fckeditor ('anons')?>
<?=show_fckeditor ('content')?>
Конструкция вешает на textarea с id=»anons» визуальный редактор FCKEditor. class=»datepicker» — вешает на input календарь Datepicker.
Подробней прочитать про подключения календаря Datepicker иподключение FCKEditor к CodeIgniter.
Теперь перейдем к созданию контроллера admin/news. Ничего сложно в нем нет. Стандартно реализованы функции добавления, удаления, вывода списка новостей и одной новости.
Контроллер admin/news
<?php
/**
* @author allexe
* @copyright 2010
* 26.8.2010
* Описание файла: Контроллер Новости
*/
if (!defined('BASEPATH')) exit('No direct script access allowed');
class news extends Controller
{
function news()
{
parent::Controller();
if (!($this->userlib->logged_in())) {
redirect(base_url() . 'users/login/');
}
}
/**
* Выводим список новостей для редактирования
*/
function index()
{
$header_data['page_title'] = 'Раздел новости';
$this->load->view('admin/header.php', $header_data);
$CI = &get_instance(); //Доступ к CodeIgniter
$CI->load->model('mdl_news');
$data['list'] = $CI->mdl_news->getlist();
$CI->load->view('admin/news.php', $data);
$this->load->view('admin/footer.php');
}
/**
* Добавление новости
*/
function add()
{
$this->load->helper('fckeditor');
$CI = &get_instance();
$CI->load->model('mdl_news'); //Загрузка модели
if ($CI->mdl_news->add() !== false) {
//Делаем редирект на список ссылок
redirect('admin/news');
} else {
//Выводим форму добавления
$header_data['page_title'] = 'Добавление новости';
$this->load->view('admin/header.php', $header_data);
//Теперь готовим вывод серединки
$data = array();
$data['validation_errors'] = validation_errors();
$data['type'] = 'add';
$this->load->view('admin/one_news', $data);
//Здесь вывод футера
$this->load->view('admin/footer.php');
}
}
/**
* Редактирование новости
*/
function edit($id)
{
$this->load->helper('fckeditor');
$CI = &get_instance();
$CI->load->model('mdl_news'); //Загрузка модели
if ($CI->mdl_news->edit($id) !== false) {
//Делаем редирект на список ссылок
redirect('admin/news');
} else {
//Выводим форму добавления
$header_data['page_title'] = 'Редактирование новости';
$this->load->view('admin/header.php', $header_data);
//Теперь готовим вывод серединки
$data = array();
$data['validation_errors'] = validation_errors();
$data['type'] = 'edit';
$CI->load->model('mdl_news');
$data['one'] = $CI->mdl_news->get($id);
$this->load->view('admin/one_news', $data);
//Здесь вывод футера
$this->load->view('admin/footer.php');
}
}
/**
* Удаление новости
*/
function del($id)
{
$CI = &get_instance();
$CI->load->model('mdl_news'); //Загрузка модели
$CI->mdl_news->del($id);
redirect('admin/news');
}
}
?>
$this->load->helper(‘fckeditor’); — необходимо для загрузки FCKEditor.
Разберем простую последовательность обработки на примере кода:
//Доступ к CodeIgniter
$CI = &get_instance();
//Загрузка модели
$CI->load->model('mdl_news');
//Обращение к функции getlist модели mdl_news
//(сама функция находится в модели CRUD
//т.к. она является родительской mdl_news extends CRUD)
//которая возвращает список новостей
$data['list'] = $CI->mdl_news->getlist();
//Вызов файла вида с передачей ему массива с новостями
$CI->load->view('admin/news.php', $data);
//Дальнейшая обработка происходит в файле вида из которого
//происходит вывод на экран.