- Подписка на печатную версию:
- Подписка на электронную версию:
- Подшивки старых номеров журнала (печатные версии)
LXF138:CakePHP
Материал из Linuxformat.
- CakePHP' Простая разработка web-приложений с БД. Ну, довольно простая…
CakePHP |
---|
|
CakePHP: Раз – и web-приложение!
- Хотите создать надежное web-приложение, но некогда возиться с PHP? Грэм Уэлдон считает, что CakePHP – то, что вам нужно.
Началось. У вас всего 15 минут, а нужно создать каталог огромной коллекции фильмов. Кто придет на помощь? Конечно, CakePHP! CakePHP – каркас для быстрой разработки приложений, охватывающий все стандартные вещи, встречающиеся в web-программировании. Решение повторяющихся задач высвободит вам больше времени на кофе, игры и прочее. На этом вводном уроке мы создадим библиотеку мультимедиа, где будет храниться информация о ваших фильмах.
Для работы CakePHP нужно совсем немного. Понадобится web-сервер типа Apache, PHP 4+ (лучше 5+), MySQL 4+ и текстовый редактор на ваш выбор. На момент написания статьи последней версией CakePHP была 1.3.
Загрузить последнюю версию можно в виде архива с сайта http://github.com/cakephp/cakephp/downloads, или получить ее из репозитория http://github.com/cakephp/cakephp с помощью Git.
После загрузки архива с сайта или из репозитория скопируйте содержимое пакета cakephp в DocumentRoot web-сервера. У вас должен появиться каталог /directory, содержащий подкаталоги /app, /cake, /plugins и /vendors и файлы .htaccess, index.php и README.
Настройка базы данных
Для повышения быстродействия CakePHP записывает файлы кэша и другие мелочи в каталог app/tmp. Нужно убедиться, что у пользователя, под которым запущен web-сервер, есть право на запись в этот каталог. Быстрее всего разрешить запись всем командой: chmod -R 777 app/tmp
Следующий шаг – настройка базы данных. Воспользуемся MySQL, так как это самая популярная из свободных СУБД, и для нашего приложения создадим следующую базу данных:
CREATE DATABASE linux_format_tutorial; CREATE TABLE `movies` ( `id` CHAR(36) NOT NULL PRIMARY KEY, `title` VARCHAR(255), `genre` VARCHAR(45), `rating` VARCHAR(45), `format` VARCHAR(45), `length` VARCHAR(45), `created` DATETIME, `modified` DATETIME );
Конечно, это всего лишь таблица, но для хранения информации и работы приложения ее достаточно.
Обратите внимание, что для идентификатора каждой записи используется поле типа CHAR(36). CakePHP замечает это, и при добавлении новых записей автоматически генерирует им уникальный универсальный идентификатор UUID вместо числового значения. Это полезная привычка, поскольку она упрощает дальнейшее слияние данных из различных баз. Таков один из подходов CakePHP, основанный на соглашениях и отражающий принцип разработки приложений в CakePHP: «Соглашения важнее конфигурации».
Еще один пример данного подхода заметен в полях created и modified. Не нужно писать никакого кода, чтобы поле created заполнялось текущими датой и временем при создании записи. Для заполнения второго поля делать тоже ничего не нужно. CakePHP возьмет все в свои руки и позаботится об этом сам, значительно ускорив разработку приложения и упростив его.
Так как для названий фильмов мы выбрали поле title, что соответствует одному из известных CakePHP «умолчательных» заголовков колонок, мы увидим еще немного волшебства – CakePHP автоматически возьмет названия всех записей (при составлении списков и далее в таком духе) именно из этого столбца.
Перед переходом к следующему шагу создайте таблицу.
Установка соединения с БД
Настройка базы данных в CakePHP проста. Есть файл /app/config/database.php.default – это пример файла конфигурации БД. Проще всего скопировать этот файл в /app/config/database.php. В созданной копии измените параметры доступа к базе данных. Для нашего приложения нужно настроить только соединение $default. Это должно выглядеть примерно так:
CakePHP включает файлы .htaccess для работы с модулями mod_rewrite на серверах Apache с эффективной перезаписью URL-адресов. Эти более удобные адреса не обязательны, но с ними пути проще запоминаются: http://mysite.com/movies/add лучше, чем http://mysite.com?url=movies/add. Установите mod_rewrite для Apache, если вы этого еще не сделали, и настройте его на применение дружелюбных URL-адресов.
var $default = array( ‘driver’ => ‘mysql’, ‘persistent’ => ‘false’, ‘host’ => ‘localhost’, ‘port’ => ‘’, ‘login’ => ‘имя_пользователя’, ‘password’ => ‘пароль’, ‘database’ => ‘linux_format_tutorial’, ‘schema’ => ‘’, ‘prefix’ => ‘’, ‘encoding’ => ‘’ );
Теперь можно грузить страницу приветствия CakePHP, открыв в браузере адрес, по которому расположен сервер. Вы увидите зеленые индикаторы, означающие успешную установку CakePHP. Если в настройках что-то не так, индикаторы будут желтыми, и появится подробное сообщение об ошибке, которое поможет решить проблему. Для нашего приложения можно игнорировать все сообщения о затравочном значении [Security Salt] или предупреждения о ключе шифрования [Cipher Key] – ему этого не надо.
Возьмемся за код всерьез, создав класс MoviesController в /app/controllers/movies_controller.php.
class MoviesController extends AppController { public $components = array(‘Session’); }
Для обработки сообщений об ошибках мы включили компонент Session.
Одно за другим создадим действия, предоставляемые пользователям, просматривающим базу данных фильмов. Действия – это публично доступные функции контроллера. Для всех операций, выполняемыхнад фильмом в базе данных, создадим в контроллере действия типа CRUD. CRUD – это сокращение от Create, Read, Update и Delete [Создать, Прочитать, Обновить и Удалить]. Наши действия получат названия index, add, edit, view и delete.
Начнем с действия index – вывод списка всех фильмов в базе данных. В контролере есть объект сущности Movie; он представляет собой модель. Он автоматически включается CakePHP и соответствует имени контроллера. Можер вызвать find() в этой модели, и CakePHP преобразует эти вызовы в запросе к базе данных – нам не придется писать SQL-запрос вручную. Потрясающе! Ниже мы вызываем метод find() с аргументом all и записываем результат в представление для последующего отображения.
class MoviesController extends AppController { public $components = array(‘Session’); public function index() { $movies = $this->Movie->find(‘all’); $this->set(‘movies’, $movies); } }
Вот и все, что нужно для действия index. Понимаю, что выглядит это безыскусным, но в том-то и прелесть CakePHP – незачем все усложнять.
Создаем первое представление
Действие готово – создадим представление, чтобы можно было просматривать данные и работать с ними. Представления в CakePHP – простые PHP-файлы с расширением ctp. Они написаны на обычном PHP.
Создайте свое первое представление в файле /app/views/movies/index.ctp. Сначала создайте каталог movies в /app/views. Добавьте туда код из фрагмента 1 на LXFDVD:
Это будет знакомо всем, кто сталкивался с HTML и PHP. Отличие в том, как вспомогательные классы представления используются для вывода информации вроде ссылок. Вспомогательный класс HtmlHelper позволяет передавать массивы данных в действия View, Edit и Delete. Они преобразуются в адреса наподобие http://mysite.com/movies/view/1234 (для ссылки на просмотр).
Представление итерирует переменную $movies, установленную ранее контроллером MoviesController, и выводит все записи в таблице (в конце концов, это табличные данные).
Если у вас другой стандарт структуры базы данных, это не проблема. CakePHP справится с любым. Следование соглашениям (http://book.cakephp.org/view/901) сэкономит вам время, но это не жесткое требование.
Теперь откроем адрес /movies/index на вашем сервере и просмотрим данные, выведенные новым представлением. Если на сервере только одно разрабатываемое приложение CakePHP, адрес будет таким: http://mysite.com/movies/index. Или, если приложение находится в подкаталоге, обращайтесь к нему: http://mysite.com/my_directory/movies/index.
На данный момент фильмов в базе нет. Срочно создадим функционал для их добавления: время-то идет!
Создание действия add и просмотр
Теперь расширим наш контроллер, добавив в него функцию add. С ее помощью новые фильмы будут добавляться в базу данных. Нужно проверить, были ли введены в форму какие-то данные, и если да, проверить ее на наличие ошибок и обработать. Это кажется сложным, но CakePHP облегчает решение данной задачи. Соответствующий фрагмент кода можно увидеть в Листинге 2 на LXFDVD.
Представление для добавления фильмов использует вспомогательный класс форм CakePHP, позволяющий легко создавать формы на все случаи жизни. Здесь мы просто определяем, для какой модели создается форма (в данном случае, модель Movie) и какие поля мы предоставим пользователям.
Создайте файл /app/views/movies/add.ctp и поместите туда следующий код:
<div class=”movies form”> <?php echo $this->Form->create(‘Movie’); echo $this->Form->inputs(array(‘title’, ‘genre’, ‘rating’, ‘format’, ‘length’)); echo $this->Form->end(‘Add’); ?> </div> <div class=”actions”> <h3>Actions</h3> <ul> <li><?php echo $this->Html->link(‘List Movies’, array(‘action’ => ‘index’));?></li> </ul> </div>
Само создание формы происходит в первых трех строках файла. Все остальное – HTML-код для расположения элементов на странице и генерации ссылки для возврата к списку фильмов.
Теперь можно перейти к форме создания фильмов, открыв адрес /movies/add или щелкнув по ссылке «New Movie», которую мы добавили на главную страницу.
Блестяще! Но можно пойти дальше и добавить пару фильмов. В примере на следующем экранном снимке мы добавляем информацию о фильме «Человек-паук 3» в формате Blu-ray. После добавления информации об очередном фильме вы перенаправляетесь на главную страницу, где в списке фильмов появляется новая запись.
Удаляем фильмы
Вы могли добавить фильм, которого у вас больше нет, или по каким-то другими причинам решить удалить запись из базы данных. Мы уже создали в представлениях ссылки на действие удаления, поэтому реализуем его. Этому действию не нужно представление, так как при удалении не нужен вывод никакой информации. Действие обработает удаление, и затем вы сразу будете перенаправлены на главную страницу с соответствующим сообщением.
Добавьте действие удаления в контроллер Movies:
class MoviesController extends AppController { // .. компонен ты .. // .. дейст вие index .. // .. дейст вие add .. public function delete($id = null) { if (!$id) { $this>Session>setFlash(‘Invalid id for movie’); $this>redirect(array(‘action’ => ‘index’)); } if ($this>Movie>delete($id)) { $this>Session>setFlash(‘Movie deleted’); } else { $this>Session>setFlash(__(‘Movie was not deleted’, true)); } $this>redirect(array(‘action’ => ‘index’)); } }
Для тех, у кого на нашем уроке возникли проблемы или просто не хватает терпения набирать код с журнала, был создан репозиторий, откуда можно легко и быстро загрузить код этого примера. Найти его можно на GitHub под моей учетной записью (http://github.com/predominant/cakephp_linux_format).
Дополнительная информация и руководства по CakePHP доступны через официальную сеть его поддержки. Мы попытались подобрать самые полезные:
- Основной сайт (http://cakephp.org)
- «Поваренная книга» (http://book.cakephp.org)
- «Пекарня» (http://bakery.cakephp.org)
- Система отслеживания ошибок (http://cakephp.lighthouseapp.com)
Ранее мы уже добавили ссылки на удаление фильмов на страницу индекса. А теперь можно запросто удалять фильмы, щелкнув по этим ссылкам! Вы могли заметить, что фрагмент кода, создающего ссылку на удаление, длиннее, чем для действий просмотра и редактирования. Это объясняется тем, что в действие удаления включен код JavaScript для показа предупреждения, который спрашивает пользователя, действительно ли он хочет удалить эту запись. Этот механизм позволит пользователю вернуться назад, избежав случайного удаления, так как с действием не связано ни одного представления.
<?php echo $this->Html->link(‘Delete’, array(‘action’ => ‘delete’, $movie[‘Movie’][‘id’]), null, sprintf(‘Are you sure you want to delete %s?’, $movie[‘Movie’][‘title’])); ?>
Добавление фильма с действием Add. Да, это просто, но вся прелесть в малом объеме требуемого кода.
Редактируем данные
Даже лучшим из лучших случается ошибиться, и хорошо бы иметь действие для редактирования данных, чтобы при необходимости исправлять ошибки или вносить в записи изменения. Это действие очень похоже на действие добавления; основное отличие в том, что работа производится с ID существующей записи. На самом деле они настолько похожи, что опытные разработчики CakePHP объединяют действия add и edit в одно. Для экономии места код вынесен на LXFDVD в Листинг 3; добавьте его в свой контроллер.
Основные различия между действиями add и edit в том, что действию редактирования передается идентификатор записи и в нем не вызывается метод create() объекта Movie, по той причине, что при сохранении в базе должны уцелеть все имеющиеся в записи поля.
Представление для редактирования
Пока все должно выглядеть знакомым. Представление edit, которое мы намерены создать, почти идентично форме добавления add. Повторюсь, разработчики, какое-то время проработавшие с CakePHP, объединяют add и edit в одно представление, чтобы не было повторов кода. Единственное отличие состоит в появлении в форме входного параметра id и кнопки для отправки формы.
Создайте файл /app/views/movies/edit.ctp и поместите туда следующий код:
<div class=”movies form”> <?php echo $this>Form>create(‘Movie’); echo $this>Form>inputs(array(‘id’, ‘title’, ‘genre’, ‘rating’, ‘format’, ‘length’)); echo $this>Form>end(‘Edit’); ?> </div> <div class=”actions”> <h3>Actions</h3> <ul> <li><?php echo $this>Html>link(‘List Movies’, array(‘action’ => ‘index’));?></li> </ul> </div>
Сохраним представление
Пора проверить, как все работает. Как и прежде, откройте в браузере главную страницу и перейдите к странице редактирования данных для одного из ваших фильмов. На экране появятся все поля ввода для записи. Обратите внимание, что поле id не отображается. Это скрытое поле формы, и пользователь не может работать с этими данными. Наше последнее действие и представление выведут подробную информацию о каждом фильме, показав все данные, не отображаемые на главной странице, такие как время создания и изменения записи.
Когда вы открываете в браузере действие просмотра, ему передается идентификатор в URL-адресе, чтобы мы знали, информацию о каком фильме нужно показать.
Добавьте такое действие просмотра в контроллер Movies:
class MoviesController extends AppController { // .. компонен ты .. // .. дейст вие index .. // .. дейст вие add .. // .. дейст вие delete .. // .. дейст вие edit .. function view($id = null) { if (!$id) { $this>Session>setFlash(‘Invalid movie’); $this>redirect(array(‘action’ => ‘index’)); } $this>set(‘movie’, $this>Movie>findById($id)); } }
Создаем подробное представление
Наше последнее представление – просто таблица со всей имеющейся информацией о фильме. Создайте это представление в файле /app/views/movies/view.ctp – код приведен в Листинге 4 на LXFDVD.
Последние действие, на которое мы сослались с главной страницы, теперь работает! Щелкните по ссылке «view» рядом с одним из фильмов – вы увидите результат работы только что созданного представления. Обратите внимание, что выводится также удобный список подходящих действий для текущей записи.
Если изменить запись или создать новую, CakePHP обновит поля со временем создания и изменения. Это часть автоматического функционала, предоставляемого каркасом. Отредактируйте пару записей, чтобы посмотреть, как меняются их поля.
Что дальше?
Теперь у нас есть полностью работающее приложение базы данных фильмов, которым можно пользоваться дома или разместить в Интернете. Все за 20 минут. Другая большая проблема, с которой вы столкнетесь – чем заняться в высвободившееся время, пока CakePHP делает всю грязную работу. Удачи вам, и не забудьте рассказать нам о том, что у вас получится, на форуме (http://forum.linuxformat.ru) – надеюсь, за что бы вы ни взялись, вы сэкономите массу драгоценного времени!