Данная серия руководств предназначена для тех разработчиков приложений на PHP, кто хочет начать использовать CakePHP, чтобы облегчить себе жизнь. Прочитав до конца, вы научитесь устанавливать и настраивать конфигурацию CakePHP, изучите основы проектирования Модель-Представление-Контроллер (MVC), узнаете, как проводить валидацию пользовательских данных в CakePHP, как применять помощников CakePHP, и как, используя CakePHP, можно быстро написать и запустить приложение. Может показаться, что нужно изучить очень много, но не переживайте - большую часть CakePHP сделает за вас.
Предполагается, что вы уже прочитали первую, вторую, третью, и четвертую части данной серии, и у вас есть рабочая среда, которая была установлена для выполнения примеров. Если у вас не установлен CakePHP, то прежде чем идти дальше, необходимо обратиться к первой и второй частям данной серии.
Предполагается, что вы знаете язык программирования PHP, обладаете фундаментальным пониманием проектирования баз данных, и не боитесь замарать рук.
Для того чтобы начать работу, у вас должна быть среда, в которой можно работать. CakePHP предъявляет минимальные разумные требования к серверу:
- Сервер HTTP с поддержкой сессий (и желательно
mod_rewrite). Данное руководство было написано при использовании Apache V1.3 сmod_rewrite. - PHP версии 4.3.2 или выше (включая PHP версии 5). Данное руководство создавалось на основе PHP версии 5.0.4
- Поддерживаемое ядро базы данных (на сегодняшний день - MySQL, PostgreSQL или используя надстройку над ADODB). Руководство было написано при использовании MySQL V4.1.15.
Также необходима база данных и пользователь базы данных, готовые к использованию приложением. В руководстве представлены синтаксические структуры для создания всех необходимых таблиц в MySQL.
Самый простой способ получить CakePHP - это зайти на сайт CakeForge.org и загрузить самую последнюю стабильную версию. Данное руководство создавалось на основе версии 1.1.8. (Полные сборки и копии Subversion также доступны для загрузки. Подробное описание приведено в Справочнике по CakePHP - см. Ресурсы).
В конце четвертой части, вам было задано усовершенствовать Tor. Справились?
Добавление представления и функции Favorites
Для просмотра списка Favorites (Избранное), необходимо добавить функцию favorites в контроллер users, как показано в листинге 1.
Листинг 1. Добавление функции favorites в контроллер users
function favorites () {
$username = $this->Session->read('user');
$favorites = array();
if ($username)
{
$this->User->recursive = 2;
$results = $this->User->findByUsername($username);
foreach($results['Product'] as $product)
{
$favorites[] = array('Product' => $product, 'Dealer' => $product['Dealer']);
}
$this->set('products', $favorites);
} else {
$this->redirect('/users/login');
}
}
|
Не забудьте про переадресацию пользователя, если он не вошел в систему. Это позволит избежать появления ошибки, если пользователь просматривает страницу, не войдя в систему.
Также необходимо добавить файл favorites.html в директорию app/views/users/, который может выглядеть так, как показано в листинге 2.
Листинг 2. Favorites.html
<h2>Your Favorite Products</h2>
<?php
echo $this->renderElement('products_table', array('products' => $products) );
?>
|
Фактически, все, что делает представление, это показывает таблицу products. Однако сейчас таблица products отображается вместе с ссылкой Add To Favorites (добавить в Избранное). Это неправильно, так как просматривается именно список товаров в favorites (Избранном). Должна быть ссылка Remove From Favorites (удалить из Избранного).
Добавление ссылки Remove From Favorites (удалить из Избранного)
Итак, ваше задание заключалось в добавлении ссылки Remove From Favorites (удалить из Избранного) в таблицу products, настроив ее таким образом, чтобы пользователь видел ссылку Remove (удалить), если товар присутствует в его списке favorites (Избранное), и ссылку Add (добавить), если данного товара нет в списке favorites (Избранное) пользователя. Давайте посмотрим на таблицу products еще раз, так как это очень важно.
Листинг 3. Таблица рroducts
<?php
if ( isset($ajax) ) {
echo $ajax->link('Add to Favorites', '/products/add_to_favorites/' .
$product['Product']['id'], array('update'=>'updated', 'loading' =>
"Element.show('loading')",'complete' => "Element.hide('loading')"));
}
?>
|
Ссылка Remove From Favorites (удалить из Избранного) аналогична тому, что показано в листинге 4.
Листинг 4. Ссылка Remove from Favorites (удалить из Избранного)
echo $ajax->link('Remove from Favorites', '/products/remove_from_favorites/' .
$product['Product']['id'], array('update'=>'updated', 'loading' =>
"Element.show('loading')",'complete' => "Element.hide('loading')"));
|
Также в контроллере products должна быть функция removeFromFavorites.
Листинг 5. Функция
removeFromFavorites
function removeFromFavorites($id) {
$username = $this->Session->read('user');
$success = false;
$user = $this->Product->User->findByUsername($username, 'User.id');
$this->Product->User->id = $user['User']['id'];
$success = $this->Product->User->removeFavorite($id);
if ( $this->RequestHandler->isAjax() ) {
$this->set('products', $this->Product->findAll());
} else {
if ( $success ) {
$this->Session->setFlash('Removed product from favorites');
$this->redirect('/users/favorites');
} else {
$this->Session->setFlash('Access denied');
$this->redirect('/products/index');
}
}
}
|
Аналогично, необходимо создать метод removeFavorite в контроллере users.
Листинг 6. Создание метода
removeFavorite
function removeFavorite($product_id) {
if($this->getID()) {
$user = $this->read();
$fav = array();
foreach($user['Product'] as $product) {
if ($product_id != $product['id'])
{
$fav[] = $product['id'];
}
}
$user['Product'] = array('Product'=> $fav);
if($this->save($user)) {
return true;
} else {
return false;
}
}
return false;
}
|
Наверно, вы обратили внимание, что при просмотре списка favorites, отображается ссылка Add to Favorites (добавить в Избранное). Вместо нее пользователь должен видеть кнопку Remove from Favorites (удалить из Избранного) для тех товаров, которые были добавлены и находятся в списке favorites. Как это сделать?
По своей сути, кэширование иногда может быть очень сложным. Существуют различные типы кэширования, и у каждого есть свои преимущества и недостатки. Крайне важно понимать, что имеется в виду под словом "кэширование" в данном случае.
Как правило, кэширование происходит при каждом запросе, когда отвечающее приложение говорит "Мне не нужно никуда идти за информацией. Она уже есть у меня". Чаще всего, если пользователь компьютера слышит слово "кэш", то он думает о кэше браузера. Обычно, для того чтобы ускорить работу пользователя, браузер сохраняет копии просмотренных статических файлов - рисунки, таблицы стилей, статические HTML-файлы и файлы сценариев. Хотя данный тип кэширования иногда доставляет неприятности разработчикам Web-приложений, в данном руководстве он рассматриваться не будет.
Еще один пример кэширования - запрос браузером контента у приложения. Если Web-приложение применяет кэширование, то оно может ответить на запрос предварительно созданной копией контента, что снижает излишние затраты ресурсов на вторичное создание контента. Данный тип кэширования и будет описан в данном приложении.
Как правило, в приложении кэширование используется по двум причинам. Первая - оно помогает снизить потребление ресурсов на сервере. Хотя в большинстве случаев эта экономия минимальна, но для часто просматриваемых сайтов, обслуживающих большое количество запросов, эти небольшие экономии в сумме сводятся к значительному увеличению производительности. Вторая причина - скорость. Так как приложению не приходится проходить через процесс повторного создания контента для запроса, то контент может быть предоставлен гораздо быстрее. Опять же, в большинстве случаев, экономия минимальна, но использование кэширования позволяет часто просматриваемым сайтам получать прирост в скорости.
Итак, вас уговорили. Теперь вы готовы к тому, чтобы кэшировать все и всегда. Как это сделать? Как CakePHP может упростить данную задачу?
Для начала, необходимо включить кэширование. По умолчанию оно отключено. Включить его можно в app/config/core.php - найдите запись: define('CACHE_CHECK', false); и измените ее на define('CACHE_CHECK', true);.
Задавая значение true (истина), вы, тем самым, указываете CakePHP, что кэширование включено. Давайте пойдем дальше, так как настроить кэширование можно позднее. Мы еще не закончили: необходимо указать CakePHP, что конкретно необходимо кэшировать и на какой промежуток времени.
Включив кэширование, необходимо указать, что нужно кэшировать. Это можно реализовать в контроллере для представлений, которые необходимо кэшировать, добавив кэширование в массив helpers. Например, если необходимо кэшировать представления products, то в массиве helpers контроллера products должно присутствовать кэширование. Когда вы создавали контроллер products в Tor, то указали, что используются helpers (помощниики) форм и HTML. При добавлении кэширования в этот список массив helpers будет выглядеть следующим образом: var $helpers = array('Html', 'Form', 'Cache' );.
Теперь, когда используется помощник кэширования, необходимо указать, что конкретно следует кэшировать. Это можно выполнить различными способами, однако все они зависят от массива $cacheAction.
Кэширование конкретного запроса
Предположим, что необходимо кэшировать конкретный запрос. Представим, что есть три или четыре товара, которые часто просматриваются, и вы хотите кэшировать только представления "просмотра" ("view") данных товаров. В этом случае, необходимо описать запросы, которые вы хотите кэшировать, в качестве ключей массива для $cacheAction и указать временной срок в качестве значений ключа. Массив $cacheAction является переменной класса так же, как и массив $helpers. Для кэширования этих конкретных представлений, $cacheAction должен выглядеть так, как показано в листинге 7.
Листинг 7. $cacheAction
var $cacheAction = array (
'view/1/' => 3600,
'view/2/' => 3600,
'view/3/' => 3600
);
|
Данный $cacheAction указывает CakePHP, что необходимо кэшировать представления "просмотра" для товаров 1-3 в течение 3,600 секунд (один час). Указанный временной срок может задаваться в любом формате, который интерпретируется strtotime(). Можно просто задать 1 hour (1 час).
Возможно, простого кэширования нескольких товаров будет недостаточно и появится желание кэшировать все представления определенной функции. Предположим, что необходимо кэшировать представления функции редактирования (edit). Для этого, следует определить функцию как ключ массива и указать промежуток времени, в течение которого представления должны храниться в кэше, практически так же, как вы делали это ранее.
var $cacheAction = array ( 'edit/' => '+1 hour' ); |
Можно даже смешать и согласовать.
Листинг 8. Смешивание и согласование
var $cacheAction = array (
'view/1/' => 3600,
'view/2/' => 3600,
'view/3/' => 3600,
'edit/' => '+1 hour'
);
|
Данный прием позволяет экономить время. Теперь вы кэшировали представления "просмотра" наиболее часто просматриваемых товаров и все представления редактирования, но может появиться желание сделать больше.
Кэширование всех функций контроллера
Возможно, необходимо кэшировать все, что делает контроллер. В этом случае, нет никакой необходимости описывать каждую функцию в массиве $cacheAction. Можно просто в качестве значения $cacheAction задать промежуток времени хранения кэшированной информации: var $cacheAction = "+1 hour";.
Значением должна быть строка, которую может интерпретировать strtotime(). Если задать $cacheAction только одно значение, то это укажет CakePHP, что нужно кэшировать все представления контроллера.
Так как $cacheAction является переменной класса, то можно обращаться к переменной непосредственно из функции. Предположим, что необходимо изменить $cacheAction из функции. В этом случае, будет тот же самый синтаксис, который используется для изменения любой переменной класса.
function foo() {
$this->cacheAction = array()...
}
|
Как правило, в этом нет никакой необходимости, но может возникнуть ситуация, когда понадобится и такое кэширование. Если вы столкнетесь с такой ситуацией, то теперь знаете, как это можно сделать. В CakePHP есть различные способы кэширования представлений. Это легко. Более сложной задачей, является определение когда нужно, а точнее, когда не нужно кэшировать.
Когда использовать кэширование?
Возможно, у вас появилось ощущение, что кэширование - это самое замечательное изобретение человечества. Более того, очень часто так и есть. Однако возникает вопрос, в каком случае не следует кэшировать представления?
Чаще всего, не следует кэшировать данные, которые постоянно изменяются. Например, предположим, что пользователи Tor добавляют товары несколько раз в минут. В этом случае, кэширование представления index может стать помехой. Если контент изменяется так часто, что кэшированная страница никогда не используется, то получается, что вы просто увеличили затраты ресурсов на хранение кэшированной страницы и проверку при каждом запросе, не была ли она изменена.
Однако это вовсе не означает, что кэширование не нужно использовать вообще. Просто необходимо уточнить CakePHP что следует кэшировать.
Использование разметки <cake:nocache></cake:nocache> в представлении
В представлении или макете, CakePHP позволяет исключить некоторый контент из кэширования, если заключить его в теги <cake:nocache></cake:nocache>. Корректное использование этой разметки позволит CakePHP кэшировать статические части представления или макета, и гарантировать, что динамические составляющие страницы считываются при каждом запросе.
Не всю информацию можно заключать в теги <cake:nocache></cake:nocache>. А именно, нельзя просто заключить переменные в теги <cake:nocache></cake:nocache> для того, чтобы сделать их динамическими. В сущности говоря, в теги <cake:nocache></cake:nocache> можно заключать конструкции CakePHP, например, помощников и вызовы элементов.
Например, в Tor, используемый по умолчанию макет, созданный в четвертой части должен выглядеть примерно так :
Листинг 9. Макет, используемый по умолчанию
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Tor : <?php echo $title_for_layout;?></title>
<link rel="icon" href="<?php echo $this->webroot . 'favicon.ico';?>"
type="image/x-icon" />
<link rel="shortcut icon" href="<?php echo $this->webroot .
'favicon.ico';?>" type="image/x-icon" />
<?php
if ( isset($javascript) ) {
echo $javascript->link('prototype.js');
echo $javascript->link('scriptaculous.js?load=effects');
echo $javascript->link('controls.js');
}
?>
<?php echo $html->css('cake.generic');?>
</head>
<body>
<div id="container">
<div id="header">
<h1><?php echo $html->link('Tor', '/') ?> : Welcome <?php echo
$session->read('user') ?></h1>
<div id="menu">
<?php echo $html->link('Products', '/products') ?> |
<?php echo $html->link('View Favorites', '/users/favorites') ?> |
<?php echo $html->link('Login', '/users/login') ?> |
<?php echo $html->link('Logout', '/users/logout') ?> |
</div>
</div>
<div id="content">
<?php if ($session->check('Message.flash'))
{
$session->flash();
}
echo $content_for_layout;
?>
</div>
</div>
<?php echo $cakeDebug?>
</body>
</html>
|
Если кэширование включено, то при первой загрузке любой страницы, которая использует макет по умолчанию, Welcome <?php echo $session->read('user') ?> будет заменено на Welcome или Welcome wrestler - то есть, неважно какой пользователь вошел в систему, он увидит кэшированное имя пользователя.
Чтобы указать, что не следует кэшировать имя пользователя, необходимо заключить строку <?php echo $session->read('user') ?> в теги<cake:nocache></cake:nocache>. Окончательный результат будет выглядеть следующим образом:
Листинг 10. Описание того, что имя пользователя не должно кэшироваться
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Tor : <?php echo $title_for_layout;?></title>
<link rel="icon" href="<?php echo $this->webroot . 'favicon.ico';?>"
type="image/x-icon" />
<link rel="shortcut icon" href="<?php echo $this->webroot .
'favicon.ico';?>" type="image/x-icon" />
<?php
if ( isset($javascript) ) {
echo $javascript->link('prototype.js');
echo $javascript->link('scriptaculous.js?load=effects');
echo $javascript->link('controls.js');
}
?>
<?php echo $html->css('cake.generic');?>
</head>
<body>
<div id="container">
<div id="header">
<h1><?php echo $html->link('Tor', '/') ?> : Welcome
<cake:nocache><?php echo $session->read('user')
?></cake:nocache></h1>
<div id="menu">
<?php echo $html->link('Products', '/products') ?> |
<?php echo $html->link('View Favorites', '/users/favorites') ?> |
<?php echo $html->link('Login', '/users/login') ?> |
<?php echo $html->link('Logout', '/users/logout') ?> |
</div>
</div>
<div id="content">
<?php if ($session->check('Message.flash'))
{
$session->flash();
}
echo $content_for_layout;
?>
</div>
</div>
<?php echo $cakeDebug?>
</body>
</html>
|
Можно выполнить проверку, указав, что контроллер products использует кэширование функции представления (view). Добавьте кэширование в список помощников (helpers) и укажите представление в $cacheAction.
Листинг 11. Описание того, что контроллер products использует кэширование функции представления
<?php
class ProductsController extends AppController
{
var $name = 'Products';
var $helpers = array('Html', 'Form', 'Javascript', 'Ajax', 'Cache' );
var $components = array('Acl', 'RequestHandler');
var $cacheAction = array(
'view/' => '+1 hour'
);
...
|
Теперь, посмотрите товар. Вы должны увидеть файл, созданный в app/tmp/cache/views, который соответствует тому товару, который вы смотрели. Зайдите в систему под другим пользователем и посмотрите тот же самый товар. Вы увидите, что имя пользователя не было кэшированно. Отредактируйте этот товар. Теперь CakePHP известно, что нужно удалить кэшированное представление. Разве не изящно?
Использование тегов <cake:nocache></cake:nocache> позволяет найти изящное решение кэширования представлений и сохранения актуального контента. Случается, что и этого недостаточно. Иногда приходится чистить кэш вручную.
Даже если вам известно, что подлежит кэшированию, а что нет, иногда возникает необходимость очищать кэш вручную. Может возникнуть мысль, что такая необходимость возникает при изменении и обновлении информации. Например, если товар был отредактирован, то представления просмотра и редактирования данного товара, так же как и представление index товаров должны быть удалены из кэша. Вы правы! Их действительно необходимо удалить из кэша.
Но вам не придется делать это самостоятельно, так как за вас это сделает CakePHP. CakePHP знает, что при добавлении, изменении или удалении данных, и если эти действия оказывают влияние на кэшированное представление, необходимо удалить кэшированное представление. Это позволяет сэкономить огромное количество усилий.
Но нет никакой необходимости в явной чистке кэша. Например, если внешний процесс, такой как выполняемый по расписанию пакетный скрипт, изменяет информацию в базе данных напрямую, а не через приложение, то не придется чистить кэш вручную. Чистку можно выполнить при помощи глобальной функции clearCache.
Аналогично тому, как CakePHP предоставляет различные способы кэширования данных, существует несколько способов удаления информации из кэша:
- Для очистки кэша только от кэшированного представления "просмотра" товара 1 необходимо использовать следующую структуру:
clearCache('products_view_1');. - Для очистки кэша от всех представлений "просмотра" контроллера products необходимо использовать следующую структуру:
clearCache('products_view');. - Для очистки кэша от всех представлений контроллера products необходимо использовать следующую структуру:
clearCache('products');. - Для очистки кэша от различных типов представлений, необходимо передать массив в
clearCache:clearCache('products', 'users_view');
Если необходимо очистить весь кэш, то вызовите функцию без параметров:clearCache();. Эту функцию можно вызвать, создав контроллерemptycacheи поместив вызов функции в функцию index. Данная функция должна вызываться вручную, или через что-либо в событии, которое должно быть автоматизировано процессом.
Поздравляю! Вы прочитали всю серию до конца. Вероятно, вы в приподнятом настроении и готовы создавать свое собственное приложение.
Но прежде, в app/config/core.php, задайте 2 в качестве значения DEBUG. Это укажет CakePHP, что необходимо отображать отладочную информацию SQL в нижней части окна представлений. Кэшированные страницы хранятся в app/tmp/cache/views. Откройте одну из них, чтобы иметь представление о том, как выглядят кэшированные страницы. Удалите кэшированные файлы и представление товара. Обратите внимание на то, сколько запросов было сделано и как долго они выполнялись. Теперь перезагрузите. Представление было кэшировано. Сколько запросов было запущено на этот раз? Узнайте больше о кэшировании. Рассмотрите различные способы его использования в Tor. Когда разберетесь со всем окончательно, удалите его и займитесь разработкой своего собственного приложения.
Итак, вы много узнали из серии "Быстрое создание Web-сайтов с помощью CakePHP", но только создание своего собственного приложения с помощью CakePHP позволит применить свои знания на практике.
| Описание | Имя | Размер | Метод загрузки |
|---|---|---|---|
| Part 5 source code | os-php-cake5.source.zip | 158KB | HTTP |
Научиться
- Оригинал статьи: Cook up Web sites fast with CakePHP, Part 5: Adding cache.
- Чтобы получить более подробную информацию о CakePHP, посетите сайт
CakePHP.org.
- Подробное описание CakePHP API. Здесь расположена свежая документация по CakePHP.
-
Огромное количество информации предлагается на сайте The Bakery, представляющем сообщество пользователей CakePHP.
-
Валидация данных в CakePHP использует Perl-совместимые регулярные выражения PHP.
-
Прочитайте руководство "Как использовать регулярные выражения в PHP."
-
Хотите узнать больше о шаблонах проектирования? Прочитайте книгу
Шаблоны проектирования: Элементы объектно-ориентированного программного обеспечения многократного использования
.
-
Прочитайте исходные материалы по созданию пользователей.
-
Прочитайте Википедия: Модель-Представление-Контроллер.
-
Полезные первоисточники по шаблону Модель-Представление-Контроллер.
-
Здесь представлен полный список различных типов шаблонов проектирования программного обеспечения.
-
Прочитайте о шаблонах проектирования.
-
Для получения дополнительной информации по PHP посетите Ресурсы проекта PHP на IBM developerWorks.
-
Будьте в курсе всех событий с сайтом технические события и web-трансляции developerWorks.
-
Узнавайте обо всех предстоящих конференциях, выставках, web-трансляциях и других cобытиях, представляющих интерес для разработчиков ПО IBM с открытым исходным кодом во всем мире.
-
Посетите раздел, посвященный ПО с открытым исходным кодом, на developerWorks для получения обширного количества информации, инструментальных средств, и обновлений проекта, призванного помочь в разработке при помощи технологий с открытым исходным кодом и в использовании их совместно с продуктами IBM.
-
Интервью и обсуждения, которые будут интересны для разработчиков ПО, доступны для прослушивания на сайте подкасты developerWorks.
Получить продукты и технологии
-
Внесите новшества в Ваш следующий проект разработки с открытым исходным кодом при помощи пробного программного обеспечения IBM, доступного для загрузки или представленного на DVD.
Обсудить
- Примите участие в обсуждении материала на форуме.
-
Форум разработчиков PHP на developerWorks предлагает разработчикам PHP место для обсуждения всех тем, относящихся к PHP. Задавайте разработчикам PHP свои вопросы по PHP-скриптам, синтаксису, функциям, переменным, отладке PHP и любым другим темам.
-
Вступите в сообщество developerWorks, приняв участие в блогах developerWorks.