Встречайте четвертую часть цикла статей по разработке с Kohana PHP V3 (KO3). редыдущие части можно найти по метке "знакомство с kohana 3.0". В этот раз речь пойдет о работе с моделями.
Определение модели возьмем из документации Kohana 2.x:
По сути, модель – это манипулятор данными.
Первым делом мы должны определить, что будет являться данными: XML-лента, CSV, JSON, DB или что-то другое? Не стану вас мучать и скажу, что в этот раз мы поработаем с давним другом MySQL. Поэтому следующим шагом станет настройка подключения к базе данных.
Давайте откроем загрузочный файл (”application/bootstrap.php”), найдем там строку “// ‘database’ => MODPATH.’database’, // Database access” и раскомментируем ее. Весь блок теперь должен выглядеть так:
Теперь сохраните файл. Мы только что приказали фреймворку загружать модуль базы данных, но он еще не сконфигурирован. Скопируйте “database.php” из “modules/database/config/” в “application/config/”. Откройте файл “application/config/database.php” и отредактируйте его в соответствии с вашими настройками. Мой выглядит так:
Сохраните файл. Для этой серии статей я создал базу данных “mykohana3″, вам желательно сделать то же самое. Таблицу в базе данных мы создадим с помощью следующего SQL-кода:
Запустите его в вашем любимом MySQL-клиенте, лично я предпочитаю SQLYog. Как в конфигурации подключения к БД, так и для таблицы я выставил кодировку “utf8″. Это понадобится нам в будущем.
Давайте в “application/classes” создадим новую папку “model”. В ней создайте новый файл и поместите туда следующее:
Сохраните это как “post.php” в “application/classes/model/”. Теперь разберем код построчно.
Это базовый запрос MySQL, который выбирает до десяти записей из базы данных, который сортируются по полю ‘id’ в порядке убывания.
Это возвращает массив с результатом запроса. Метод “query” в данном примере принимает три параметра. Первый – тип запроса, у нас это “select”, поэтому мы передаем константу “Database::SELECT”. Также есть три других: “Database::INSERT”, “Database::UPDATE” и “Database::DELETE”. Метод “as_array()” возвращает массив с результатами, так что исчезает необходимость делать “while($row = mysql_fetch_array())”.
Теперь, когда у нас в модели появился метод, можно начать его использовать. Откройте “ko3.php” в “/application/classes/controller” и добавьте в класс следующий код:
Только что мы вызвали из модели метод “getLastTenPosts()” и поместили возвращаемое им значение в массив, который затем передали нашему виду. Кстати о видах: откройте новый файл и поместите туда:
Сохраните это как “posts.php” в папке “application/views/pages/”. Этот вид перебирает передаваемый контроллером массив и выводит записи из базы данных. Хотя, стоп, у нас же в базе данных еще нет статей! Исправим это следующими SQL-запросами:
Теперь, перейдя по адресу “http://localhost/mykohana3/ko3/posts”, вы должны увидеть две записи.
Давайте теперь реализуем добавление новых данных в базу. Откройте нашу модель (”application/classes/model/post.php”) и добавьте в класс следующее:
Выше находится довольно простой запрос типа INSERT, но что такое “$this->_db>escape()”? Этот метод обрамит ваши строковые переменные кавычками и очистит их от мусора. Сохраните это и вернитесь к “posts.php” из “application/views/pages”. Замените его содержимое этим:
Сохраните файл и откройте контроллер (”application/classes/controller/ko3.php”). Добавим-ка к нему новый метод:
Этот код является промежуточным звеном между “action_posts” и моделью, он служит для непосредственного сохранения записи. Давайте вернемся к методу “action_posts” и приведем его к такому виду:
Сохраните это и перезагрузите браузер. Внизу должна появиться форма страшноватого вида. Введите что-то и нажмите «Отправить». Если вы заполнили оба поля, то ваша запись должна появиться наверху вместе с надписью “Saved”. В ином случае должно появиться сообщение об ошибке.
Прежде чем закончить ознакомление с моделями, хочу показать, как еще можно было производить добавление записи в базу данных. Существует несколько способов, но я обращу внимание только на так называемый Query Builder. MySQL-запрос в методе «addPost()» с ним выглядел бы так:
Query Builder удобен в частности тем, что позволяет переключаться между разными типами баз данных (из MySQL в Oracle, и т.п.)
Обновление записей я в модели не реализовал, так что можете рассматривать это как домашнее задание.
Определение модели возьмем из документации Kohana 2.x:
Модели — это классы, предназначенные для работы с информацией, передаваемой или запрашиваемой контроллером. Например, если у вас есть гостевая книга, то контроллер запрашивает у модели последние десять записей; модель их возвращает; контроллер передает эти данные виду. Контроллер также может с помощью модели добавить новые записи и обновить или удалить существующие.
По сути, модель – это манипулятор данными.
Первым делом мы должны определить, что будет являться данными: XML-лента, CSV, JSON, DB или что-то другое? Не стану вас мучать и скажу, что в этот раз мы поработаем с давним другом MySQL. Поэтому следующим шагом станет настройка подключения к базе данных.
Давайте откроем загрузочный файл (”application/bootstrap.php”), найдем там строку “// ‘database’ => MODPATH.’database’, // Database access” и раскомментируем ее. Весь блок теперь должен выглядеть так:
Kohana::modules(array(
// 'auth' => MODPATH.'auth', // Basic authentication
// 'codebench' => MODPATH.'codebench', // Benchmarking tool
'database' => MODPATH.'database', // Database access
// 'image' => MODPATH.'image', // Image manipulation
// 'orm' => MODPATH.'orm', // Object Relationship Mapping
// 'pagination' => MODPATH.'pagination', // Paging of results
// 'userguide' => MODPATH.'userguide', // User guide and API documentation
));
Теперь сохраните файл. Мы только что приказали фреймворку загружать модуль базы данных, но он еще не сконфигурирован. Скопируйте “database.php” из “modules/database/config/” в “application/config/”. Откройте файл “application/config/database.php” и отредактируйте его в соответствии с вашими настройками. Мой выглядит так:
<?php defined('SYSPATH') OR die('No direct access allowed.');
return array
(
'default' => array
(
'type' => 'mysql',
'connection' => array(
/**
* The following options are available for MySQL:
*
* string hostname
* integer port
* string socket
* string username
* string password
* boolean persistent
* string database
*/
'hostname' => 'localhost',
'username' => 'root',
'password' => FALSE,
'persistent' => FALSE,
'database' => 'mykohana3',
),
'table_prefix' => '',
'charset' => 'utf8',
'caching' => FALSE,
'profiling' => TRUE,
),
'alternate' => array(
'type' => 'pdo',
'connection' => array(
/**
* The following options are available for PDO:
*
* string dsn
* string username
* string password
* boolean persistent
* string identifier
*/
'dsn' => 'mysql:host=localhost;dbname=mykohana3',
'username' => 'root',
'password' => FALSE,
'persistent' => FALSE,
),
'table_prefix' => '',
'charset' => 'utf8',
'caching' => FALSE,
'profiling' => TRUE,
),
);
Сохраните файл. Для этой серии статей я создал базу данных “mykohana3″, вам желательно сделать то же самое. Таблицу в базе данных мы создадим с помощью следующего SQL-кода:
CREATE TABLE `posts` (
`id` MEDIUMINT(8) UNSIGNED NOT NULL AUTO_INCREMENT,
`title` VARCHAR(255) DEFAULT NULL,
`post` TEXT,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC;
Запустите его в вашем любимом MySQL-клиенте, лично я предпочитаю SQLYog. Как в конфигурации подключения к БД, так и для таблицы я выставил кодировку “utf8″. Это понадобится нам в будущем.
Давайте в “application/classes” создадим новую папку “model”. В ней создайте новый файл и поместите туда следующее:
<?php
defined('SYSPATH') or die('No direct script access.');
class Model_Post extends Kohana_Model
{
/**
* Get the last 10 posts
* @return ARRAY
*/
public function getLastTenPosts()
{
$sql = 'SELECT *'."\n".
'FROM `posts`'."\n".
'ORDER BY `id` DESC'."\n".
'LIMIT 0, 10';
return $this->_db->query(Database::SELECT, $sql, FALSE)
->as_array();
}
}
Сохраните это как “post.php” в “application/classes/model/”. Теперь разберем код построчно.
$sql = 'SELECT *'."\n".
'FROM `posts`'."\n".
'ORDER BY `id` DESC'."\n".
'LIMIT 0, 10';
Это базовый запрос MySQL, который выбирает до десяти записей из базы данных, который сортируются по полю ‘id’ в порядке убывания.
return $this->_db->query(Database::SELECT, $sql, FALSE)
->as_array();
Это возвращает массив с результатом запроса. Метод “query” в данном примере принимает три параметра. Первый – тип запроса, у нас это “select”, поэтому мы передаем константу “Database::SELECT”. Также есть три других: “Database::INSERT”, “Database::UPDATE” и “Database::DELETE”. Метод “as_array()” возвращает массив с результатами, так что исчезает необходимость делать “while($row = mysql_fetch_array())”.
Теперь, когда у нас в модели появился метод, можно начать его использовать. Откройте “ko3.php” в “/application/classes/controller” и добавьте в класс следующий код:
public function action_posts()
{
$posts = new Model_Post();
$ko3 = array();
$this->template->title = 'Kohana 3.0 Model Test';
$this->template->meta_keywords = 'PHP, Kohana, KO3, Framework, Model';
$this->template->meta_description = 'A test of of the KO3 framework Model';
$this->template->styles = array();
$this->template->scripts = array();
// Get the last 10 posts
$ko3['posts'] = $posts->getLastTenPosts();
$this->template->content = View::factory('pages/posts', $ko3);
}
Только что мы вызвали из модели метод “getLastTenPosts()” и поместили возвращаемое им значение в массив, который затем передали нашему виду. Кстати о видах: откройте новый файл и поместите туда:
<?php foreach($posts as $post):?>
<h1><?php echo $post['title'];?></h1>
<?php echo $post['post'];?>
<hr />
<?php endforeach;?>
Сохраните это как “posts.php” в папке “application/views/pages/”. Этот вид перебирает передаваемый контроллером массив и выводит записи из базы данных. Хотя, стоп, у нас же в базе данных еще нет статей! Исправим это следующими SQL-запросами:
insert into `posts`(`id`,`title`,`post`) values (1,'Test Post','This is some sample text.');
insert into `posts`(`id`,`title`,`post`) values (2,'Another post','Some more text');
Теперь, перейдя по адресу “http://localhost/mykohana3/ko3/posts”, вы должны увидеть две записи.
Давайте теперь реализуем добавление новых данных в базу. Откройте нашу модель (”application/classes/model/post.php”) и добавьте в класс следующее:
public function addPost($title, $post)
{
$sql = sprintf('INSERT INTO `posts`'."\n".
'SET `title` = %s,'."\n".
' `post` = %s',
$this->_db->escape($title),
$this->_db->escape($post));
$this->_db->query(Database::INSERT, $sql, FALSE);
}
Выше находится довольно простой запрос типа INSERT, но что такое “$this->_db>escape()”? Этот метод обрамит ваши строковые переменные кавычками и очистит их от мусора. Сохраните это и вернитесь к “posts.php” из “application/views/pages”. Замените его содержимое этим:
<?php if(!empty($msg)):?>
<?php echo $msg.'<br />';?>
<?php endif;?>
<?php foreach($posts as $post):?>
<h1><?php echo $post['title'];?></h1>
<?php echo $post['post'];?>
<hr />
<?php endforeach;?>
<form method="POST" action="<?php echo url::base();?>ko3/posts/">
<table>
<tr>
<td>
Title
</td>
<td>
<input type="text" name="title" style="border: 1px solid #000000;"/>
</td>
</tr>
<tr>
<td>
Post
</td>
<td>
<textarea cols="20" rows="5" name="post"></textarea>
<input type="submit" name="submit" value="Submit"/>
</td>
</table>
</form>
Сохраните файл и откройте контроллер (”application/classes/controller/ko3.php”). Добавим-ка к нему новый метод:
private function _addPost($title, $post_content)
{
// Load model
$post = new Model_Post();
// Check required fields
if(empty($title))
{
return(array('error' => 'Please enter a title.'));
}
elseif(empty($post_content))
{
return(array('error' => 'Please enter a post.'));
}
// Add to DB
$post->addPost($title, $post_content);
return TRUE;
}
Этот код является промежуточным звеном между “action_posts” и моделью, он служит для непосредственного сохранения записи. Давайте вернемся к методу “action_posts” и приведем его к такому виду:
public function action_posts()
{
// Load model
$posts = new Model_Post();
// Setup view stuff
$ko3 = array();
$this->template->title = 'Kohana 3.0 Model Test';
$this->template->meta_keywords = 'PHP, Kohana, KO3, Framework, Model';
$this->template->meta_description = 'A test of of the KO3 framework Model';
$this->template->styles = array();
$this->template->scripts = array();
$ko3['msg'] = "";
// Handle POST
if($_POST)
{
$ret = $this->_addPost((isset($_POST['title']) ? $_POST['title'] : ""),
(isset($_POST['post']) ? $_POST['post'] : ""));
if(isset($ret['error']))
{
$ko3['msg'] = $ret['error'];
}
else
{
$ko3['msg'] = 'Saved.';
}
}
// Get the last 10 posts
$ko3['posts'] = $posts->getLastTenPosts();
// Display it.
$this->template->content = View::factory('pages/posts', $ko3);
}
Сохраните это и перезагрузите браузер. Внизу должна появиться форма страшноватого вида. Введите что-то и нажмите «Отправить». Если вы заполнили оба поля, то ваша запись должна появиться наверху вместе с надписью “Saved”. В ином случае должно появиться сообщение об ошибке.
Прежде чем закончить ознакомление с моделями, хочу показать, как еще можно было производить добавление записи в базу данных. Существует несколько способов, но я обращу внимание только на так называемый Query Builder. MySQL-запрос в методе «addPost()» с ним выглядел бы так:
public function addPost($title, $post)
{
DB::insert('posts', array('title','post'))
->values(array($title, $post))
->execute();
}
Query Builder удобен в частности тем, что позволяет переключаться между разными типами баз данных (из MySQL в Oracle, и т.п.)
Обновление записей я в модели не реализовал, так что можете рассматривать это как домашнее задание.