- Подписка на печатную версию:
- Подписка на электронную версию:
- Подшивки старых номеров журнала (печатные версии)
LXF141:CackePHP1
Материал из Linuxformat.
- CakePHP Простая разработка web-приложений с БД. Ну, довольно простая…
CakePHP |
---|
|
CakePHP: Раз – и web-приложениe!
- Чаcть I Если статья LXF138 подогрела ваш аппетит к написанию простых и быстрых web-приложений, Грэм Уэлдон расскажет о CakePHP еще кое-что.
На прошлом уроке мы создали базу данных фильмов, где можно было хранить все ваши фильмы в различных форматах, и освоили основы запуска проекта в CakePHP. На сей раз с помощью тех же приемов мы создадим приложение посложнее, с большим количеством моделей хранения данных, и продемонстрируем связи между моделями – вы увидите, как это просто.
Пойдем коротким путем, применив bake – утилиту CakePHP, чтобы уменьшить время разработки и сбежать в паб пораньше. [Разработчики любят игры слов: cake – пирожок, bake – выпекать, а идиома “а piece of cake”, «кусок пирога», означает «очень просто», т. е. CakePHP – «простой PHP», – прим. ред.]
Начнем с определения таблиц базы данных. Мы построим многопользовательскую библиотеку, для хранения книг от разных владельцев. Заодно украсим наше приложение, приспособив формат URL-адресов к поисковым машинам.
Сперва создадим новую базу данных, чтоб с ней работать:
CREATE DATABASE library; USE library;
Затем создадим таблицы books и users. Не стесняйтесь, добавляйте в них любые другие поля, если хотите хранить больше данных, чем я:
CREATE TABLE books ( id CHAR(36) NOT NULL PRIMARY KEY, user_id CHAR(36) NOT NULL, title VARCHAR(45) NOT NULL, slug VARCHAR(45) NOT NULL, author VARCHAR(45) NOT NULL, summary TEXT, purchased DATE, created DATETIME, modified DATETIME ); CREATE TABLE users ( id CHAR(36) NOT NULL PRIMARY KEY, name VARCHAR(45) NOT NULL, created DATETIME, modified DATETIME );
Прежде чем продолжить, выполните приведенные выше SQL- запросы в своей базе данных MySQL.
Введение в выпекание
Итак, таблицы в базе данных готовы и ждут; покажем-ка гостям пару фокусов в стиле CakePHP. Вместо того, чтобы вручную создавать код модели [Model], представлений [Views] и контроллера [Сontroller] – MVC-комплекс, воспользуемся bake, которая сгенерирует код за нас.
Я предполагаю, что вы загрузили последний стабильный релиз CakePHP 1.3 из GitHub (http://github.com/CakePHP/cakephp) или клонировали репозиторий с помощью Git.
Чтобы утилита bake работала, PHP должен быть доступен с командной строки. Для этого установите в системе php-cli.
Далее удобно добавить /cake/console – путь проекта CakePHP – в переменную окружения PATH, чтобы вызывать команду cake без указания полного пути. Ниже показано, как это сделать – чтобы добавить каталог консоли CakePHP в свой путь, скомандуйте
export PATH=”$PATH:/path/to/cakephp/cake/console”
После этого вы сможете запускать команду cake без указания полного пути до команды. Если вы планируете долгосрочную работу с CakePHP, добавьте это в профиль вашего пользователя, чтобы путь мог изменяться и cake становилась доступной при каждом запуске оболочки.
Выпекаем файлы проекта
Вручную создавать все файлы, необходимые для нашей библиотеки, мы опять-таки не будем: воспользуемся утилитой bake. Она их создаст, а мы настроим под себя. Это отличный способ написать и запустить приложение за кратчайший срок.
Перейдите в подходящий каталог web-сервера на своем компьютере – например,
cd /var/www/localhost
Если вам интересно, что же такое «личинка» [slug] в таблице с книгами, то это не мелкие червячки – так мы называем уникальную строку URL-адреса, построенную на основе названия книги. Мы генерируем их автоматически и незримо для пользователей, когда те создают книги.
Выпеките скелет проекта следующей командой:
cake bake project library
Буквально сейчас сотворилось волшебство. Поверьте. Но это не совсем «черный ящик»: можно посмотреть на созданные файлы и разобраться в структуре основного каталога приложения в CakePHP.
Поэтому улучите момент, чтобы взглянуть созданные для вас утилитой bake файлы и их структуру. Утилита создала копию структуры приложения, которую вы видите в загруженной (или клонированной) копии CakePHP. Блестяще! Эти файлы немного отличаются от стандартного набора файлов приложения, и это вам поможет. Утилита изменила некоторые переменные в web root/index.php, указав в них путь к каталогу CakePHP. А значит, вы можете разворачивать и распространять приложения, не копируя ядро CakePHP на каждом шагу! Блестяще вдвойне!
Настроим связь с базой данных
Если вы теперь попробуете открыть приложение, то заметите сообщения об ошибках и предупреждения, отмеченные желтыми квадратиками в браузере. Это не конец света, и CakePHP старается дать лучшие описания и полезные отчеты об ошибках, чтобы вы могли их исправить. Ошибки касаются доступа к базе данных, так как мы еще не настроили CakePHP на подключение к ней. Сделаем это сейчас. Перейдите в каталог ваших новых проектов командой cd library. Сначала зададим конфигурацию базы данных, чтобы cake смогла найти базу данных, с который мы хотим работать. Скопируйте или переместите файл config/database.php.default в config/database.php. Измените его так, чтобы значения параметров соединения по умолчанию соответствовали параметрам вашей базы данных. Тестовое соединение используется для модульного тестирования, и пока его можно смело удалить или проигнорировать. Вот при мер моей конфигурации по умолчанию:
var $default = array( ‘driver’ => ‘mysql’, ‘persistent’ => false, ‘host’ => ‘localhost’, ‘login’ => ‘dev’, ‘password’ => ‘dev’, ‘database’ => ‘library’, ‘prefix’ => ‘’, );
Снова воспользуемся bake – это сэкономит нам кучу времени. Тремя быстрыми командами мы сгенерируем код для наших моделей, представлений и контроллеров. Это покроет все уровни нашей парадигмы MVC. Можно это сделать и вручную, но благодаря bake можно очень быстро сгенерировать в CakePHP большой объем кода и выполнять повторяющиеся задачи, которые в противном случае потребовали бы гораздо больше времени.
Испечем все модели:
cake bake model all
Испечем все контроллеры:
cake bake controller all
И, наконец, испечем все представления:
cake bake view all
Смотрим, что получилось
Прежде чем двигаться дальше, разберемся, что именно создали наши три команды: снова глянем на сгенерированный код. Мало того, что меньше чем за две минуты создан базовый код моделей и контроллера, необходимый для запуска приложения: еще и определено, что вы хотите связать пользователей с книгами с помощью общепринятного использования поля user_id в таблице с книгами. Это позволяет контроллерам получать связаные данные, например, книги, когда опрашивается пользовательская модель, что невероятно полезно и удобно, когда бы вам ни понадобилось получить информацию о пользователе и быстро и легко ее отобразить.
Начальный тест-драйв
Осмотрев каталоги моделей, контроллеров и представлений, устроим нашему детищу тест-драйв. Ведь покамест единственное, где нам пришлось покопаться – это настройки базы данных, да и там мы всего лишь поменяли значения некоторых параметров.
Откройте в браузере каталог, где развернуто приложение. Вас поприветствует страница установки CakePHP по умолчанию; если есть какие-то предупреждения насчет базы данных, подправьте параметры в файле config/database.php, прежде чем продолжить.
Посмотрим на то, что у нас уже есть, взглянув на контроллер users. Откройте путь /users в своем приложении. URL-адрес будет зависеть от того, как было развернуто приложение. Мой таков: http://localhost/library/users. Вы увидите пустой список, а чуть ниже – некоторые действия.
Добавим книг
Теперь пора браться за дело всерьез – добавим несколько книг, прежде чем трубить отбой. К счастью, весь функционал уже готов – нужно только слегка модифицировать его, простоты ради.
Важно отметить, что используемый по умолчанию метод Inflector::slug использует символ подчеркивания при генерации коротких ссылок, но его можно изменить на любой другой символ или набор символов, отвечающий вашим нуждам. Для этого передайте в метод slug второй параметр: строку, которой будут заменены некорректные символы URL-адреса. Вот вам еще один пример разумной реализации по умолчанию в CakePHP, допускающей переделку под конкретного пользователя.
Пройдите по навигационным ссылкам слева, чтобы добавить новую книгу. Вы увидите, что ваш пользователь есть в выпадающем списке на форме add book. Эта информация была получена и применена автоматически, потому что использованная нами для таблиц пользователей и книг структура базы данных отвечает соглашениям CakePHP. Таким образом, с помощью предсказуемых запросов CakePHP может находить и отображать информацию, экономя ваше время.
Где мы сейчас?
А сейчас мы имеем полноценное приложение библиотеки; в нем пользователи связаны с книгами, которыми владеют, и можно добавлять, удалять, изменять и выводить списки любых записей. Довольно мило для приложения, для которого не было написано ни строчки кода, не правда ли? И мы не только набрались опыта, но и получили код, и можем менять его в соответствии с нашими нуждами!
Введение коротких ссылок
А теперь сделаем нечто изящное. Вы наверняка заметили, что URL-адреса, по которым вы переходите, для определения записей в них используют жуткие 36‑символьные строки. Ну да, это удобно, это работает, и мы можем развернуть приложение как есть, но гораздо лучше смотрятся адреса человеко-читаемые; да и поисковым системам они понравятся.
Откройте контроллер books в файле library/controllers/books_controller.php и найдите действие для просмотра. Помните, что, говоря действие, я имею в виду публичный метод класса контроллера.
Передадим в качестве параметра не идентификатор ID, а короткую ссылку [slug], соответственно изменив запрос find. Для этого нужно изменить сигнатуру метода просмотра, следующим образом:
public function view($slug = null) { // Здесь будет код заложен. }
Затем воспользуемся методами, предоставляемыми CakePHP в моделях по умолчанию. Каждому полю, определенному в модели, отвечает свой метод find. Это значит, что можно быстро и легко находить данные в любой модели и незачем добавлять методы, чтобы изменить способ возврата результатов CakePHP.
Поскольку мы ищем запись по короткой ссылке, изменим работу с идентификатором в контроллере books, чтобы для поиска и обработки данных вместо идентификатора использовалась короткая ссылка.
Продемонстрируем одно из главных преимуществ использования каркаса PHP вроде CakePHP для создания приложений: воспользуемся информацией, передаваемой пользователем через URL-адрес, для выполнения запросов к базе данных. На первый взгляд эта идея может показаться плохой из-за возможности SQL-инъекции. Однако CakePHP поддерживает безопасность запросов к базе данных во встроенных методах find() – сгенерированные SQL-запросы являются безопасными, верными и корректными.
Почти готово! Рассмотрим особый тип find, который я упомянул. Так как мы ищем данные по короткой ссылке, CakePHP предоставляет на это метод findBySlug. Легко! Теперь ваш код можно заменить таким:
function view($slug = null) { if (!$slug) { $this->Session->setFlash(__(‘Invalid book’, true)); $this->redirect(array(‘action’ => ‘index’)); } $this->set(‘book’, $this->Book->findBySlug($slug)); }
Теперь действие просмотра работает с короткими ссылками вместо идентификаторов. Далее обновим индексное представление в файле library/views/books/index.ctp, чтобы при переходе к действию просмотра бралась короткая ссылка на книгу, а не ее идентификатор. Без этого не обойтись: ведь мы изменили информацию, требуемую для поиска записей, и нужно ее передать представлению, отразив изменения. Измените строку
<?php echo $this->Html->link(__(‘View’, true), array(‘action’ => ‘view’, $book[‘Book’][‘id’])); ?>
на следующую:
<?php echo $this->Html->link(__(‘View’, true), array(‘action’ => ‘view’, $book[‘Book’][‘slug’])); ?>
Единственное различие – индекс slug в ассоциативном массиве $book, который используется представлением.
Автоматизируем ссылки!
Теперь в адресах есть короткие ссылки. Однако на нашей форме add для добавления книг короткая ссылка вводилась вручную, и негуманно заставлять пользователя набирать название книги больше одного раза, хотя бы и в другом стиле. Было бы здорово заполнять это поле автоматически: оно просто должно содержать правильные слова, а те формируются по названию книги, так что сделаем-ка это сами до или после сохранения, избавив пользователей от лишней мороки.
Добавить функционал, связанный с операцией сохранения, позволяет реализация метода afterSave или beforeSave. Припишите следующий код к модели Book в файле library/models/book.php:
public function beforeSave($op» tions = array()) { parent::beforeSave($options); $this->data[‘Book’][‘slug’] = Inflector::slug($this->data[‘Book’] [‘title’]); return true; }
Теперь, раз черная работа перекинута на модель, можно удалить поле ввода короткой ссылки из представления. Удалите следующую строку из файла library/models/book.php:
echo $this->Form->input(‘slug’);
Добавьте в наше приложение еще одну книгу. После ее добавления вас перенаправят на индексное представление книг, и вы увидите, что короткая ссылка, которую раньше нужно было вводить вручную, теперь генерируется автоматически и используется на странице представления books.
Закругляясь
На выполнение всех действий в уроке должно потребоваться около 15 минут, да еще где-то минут 20 нужно на чтение урока. На этот раз мы создали систему структурированного и организованного хранения книг в базе данных, привязанного к пользователям системы. Делай мы это на обычном PHP, пришлось бы дополнительно заботиться о соединении с базой данных, безопасности, правильном получении информации от пользователей моделями, разбивке на страницы и обо всем остальном, что в CakePHP моментально предоставляется вам по умолчанию.
Пример кода из GitHub (см. ниже) можно расширить и модифицировать так, чтобы создать собственный проект и получить хорошее приложение-основу для дальнейшего изучения и экспериментов.
Здесь и далее
Коды для нашего тройного урока доступны на GitHub под моей учетной записью http://github.com/predominant/cakephp_linux_format. Можете взять код оттуда, если не получается сгенерировать его утилитой bake или вы просто хотите собрать и запустить приложение побыстрее – код можно скопировать, опустив все этапы данного урока. Подробная информация и руководства по CakePHP доступны через его официальную сеть поддержки:
- Основной сайт http://cakephp.org
- «Поваренная книга» http://book.cakephp.org
- «Пекарня» http://bakery.cakephp.org
- Система отслеживания ошибок http://cakephp.lighthouseapp.com
- CakeQs http://cakeqs.org
О любых вопросах или предложениях по этой статье дайте мне знать через мой сайт http://grahamweldon.com или по электронной почте [graham@grahamweldon.com.