→ Пошук по сайту       Увійти / Зареєструватися
Знання

CakePHP — что это такое и с чем его едят. PHP фреймворк

CakePHP — это бесплатный, имеющий открытые исходные коды, фреймворк для быстрой разработки приложений на PHP.
Вот небольшой список вещей, в восторге от которых вы будете, работая с CakePHP:
  1. Активное и дружелюбное сообщество
  2. Хорошая лицензия
  3. Полная поддержка как php4, так и php5
  4. Полное взаимодействие с базой данных
  5. Скаффолдинг («строительные леса») для автоматического создания страниц
  6. Авто-генерирование кода
  7. Архитектура MVC (Модель-Отображение-Контроллер)
  8. Диспетчер, преобразующий URL к нужному вам виду
  9. Встроенная верификация данных
  10. Система быстрых шаблонов (php с добавлением помощников)
  11. Помощники отображения для AJAX, Java Script?, HTML-форм и многого другого
  12. Компоненты, автоматизирующие работу с Почтовыми сообщениями, Cookie, Безопасностью, Сессиями и Запросами
  13. Удобные Списки Контроля Доступа (ACL)
  14. Автоматическая обработка данных
  15. Удобное кеширование
  16. Поддержка многоязычности готового web-приложения
  17. Работа из любого каталога сайта, почти без необходимости изменять конфигурацию Apache
При написании программы на CakePHP принято следовать шаблону MVC (Модель-Отображение-Контроллер). Программирование с применением этой модели разделяет ваше приложение на три основные части. Модель оперирует информацией Базы Данных, Отображение создает страницу с информацией из модели, а Контроллер обрабатывает запросы, сделанные пользователями.

Рисунок демонстрирует каркас MVC запроса в Cake. Рассмотрим простейший пример. Предположим пользователь Иван нажал на ссылку «Купить пирог!», эта ссылка ведет на нашу страницу.
  1. Иван нажимает на ссылку http://www.example.com/cakes/buy, и его браузер делает запрос к нашему веб-серверу.
  2. Диспетчер проверяет запрошенный адрес (/cakes/buy) и запускает необходимый Контроллер. Контроллер обрабатывает свою логику, например он проверяет вошел ли Иван в систему (залогинился ли он на сайте).
  3. Контроллер также взаимодействует с Моделями для обмена информацией. Как правило, Модели — это таблицы базы данных, но также вполне могут быть LDAP записями, RSS-лентами или простыми файлами. В данном случае Контроллер использует Модель для того чтобы выбрать из базы данных информацию о последней покупке Ивана.
  4. После того как Контроллер обработал данные — он передает их в Отображение. Отображение принимает данные и преобразует их в готовые страницы для отображения пользователям. Обычно результатом работы отображения является HTML документ, но не трудно получить PDF, XML документы или объект JSON. Все зависит от ваших потребностей.
  5. Отображение использует информацию из Контроллера для того чтобы создать готовый документ для пользователя. Иван видит в браузере готовую страницу.

Почти каждый запрос в вашем веб-приложении проходит по этой схеме.

Поместите код в ваш Document Root. Директория должна выглядить как-то так:

/path_to_document_root 
/app 
/cake 
/vendors 
.htaccess 
index.php 
VERSION.txt
Сейчас на простом примере создания блога мы будем доставать и устанавливать Cake, создавая и настраивая базу данных, создавать достаточно кода приложения, чтобы просматривать, добавлять, редактировать и удалять посты в блоге.

Создание базы данных блога

Настраиваем основную базу данных для нашего блога. Сейчас, создадим простую таблицу для хранения постов. Также вкинем туда несколько постов, чтобы использовать их в целях тестирования. Выполняем следующий запрос SQL в нашей базе данных:

/* Сначала, создаем таблицу постов: */
CREATE TABLE posts (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(50),
    body TEXT,
    created DATETIME DEFAULT NULL,
    modified DATETIME DEFAULT NULL
);

/* Затем вставим пару постов для тестирования: */
INSERT INTO posts (title,body,created)
    VALUES ('The title', 'This is the post body.', NOW());
INSERT INTO posts (title,body,created)
    VALUES ('A title once again', 'And the post body follows.', NOW());
INSERT INTO posts (title,body,created)
    VALUES ('Title strikes back', 'This is really exciting! Not.', NOW());

Файлы и имена классов

Класс с названием из двух и более слов называется без пробела с заглавных букв все слова, в то время как файл с этим классом должен содержать знак подчеркивания вместо пробела. Например, класс с названием KissesAndHugsController должен храниться в файле kisses_and_hugs_controller.php. Хотя название типа класса совсем не обязательно должно содержаться в названии файла с этим классом. Например, класс EmailComponent расположен в файле email.php, а класс HtmlHelper в файле с названием html.php.

Соглашение о Моделях

Название класса модели всегда записывается в единственном числе. Названия вроде Person, BigPerson и ReallyBigPerson — типичные представители названий моделей. Названия таблиц в базе данных, которым соответствует название Модели, должны записываться во множественном числе и через знак подчеркивания, если включают несколько слов. Для перечисленных моделей таблицы должны называться как persons, big_persons и really_big_persons. Таблицы объединений, использующиеся при схеме связи hasAndBelongsToMany, должны называться именами объединяемых таблиц во множественном числе через знак подчеркивания. Названия двух таблиц в составе новой должны следовать в алфавитном порядке (не zebras_apples, но apples_zebras). Например, таблица для объединения записей (модель Post) и тегов к ним (модель Tag) должна называться posts_tags.

Соглашение о Контроллерах

Названия классов Контроллеров имеют множественное число и слово “Controller” на конце. Если название состоит более чем из одного слова, то пробел не ставится и каждое следующее слово названия пишется с заглавной буквы. PeopleController, BigPeopleController и ReallyBigPeopleController — вот обычные имена контроллеров. Первая функция в классе Контроллера, которую мы обычно определяем называется index(). Если был вызван Контроллер, но в запросе не было указано действие, то вызывается index(). Например если мы запрашиваем http://www.example.com/apples/, то вызывается Контроллер ApplesController и дейтвие index(), если же действие было определено (http://www.example.com/apples/view), то вызовется контроллер (ApplesController) и определенное запросом действие (view()).

Соглашение об Отображениях

Шаблоны Отображения именуются так же как функции внутри класса Контроллера. Например, если в классе Контроллера People Controller объявлена функция getReady(), то Cake PHP будет искать шаблон этого Отображения по адресу /app/views/people/get_ready.ctp. Вот шаблон местоположения шаблона: /app/views/<Контроллер>/<имя_функции_через_подчеркивание>.ctp.

Настройка базы данных Cake

Сообщим Cake где находится наша база данных и как с ней связаться. Это будет первый и последний этап, где что-либо настраивается вручную. Копия конфигурации базы данных находится в /app/config/database.php.default. Копируем этот файл в ту же директорию, только переименовуем в database.php. Конфиг-файл должен быть достаточно понятным: просто заменяем значения в масиве $default теми, что применены к нашей настройке. Образец завершенного массива настроек может выглядить как следующий:
<?
var $default = array('driver'   => 'mysql',
                     'connect'  => 'mysql_pconnect',
                     'host'     => 'localhost',
                     'login'    => 'cakeBlog',
                     'password' => 'c4k3-rUl3Z',
                     'database' => 'cake_blog_tutorial' );
?>
Когда мы сохранили наш новый файл database.php, мы можем открыть свой браузер и увидеть приветственную страницу Cake. Она также должна сообщить нам, что файл соединения с базой данных найден, и что Cake может успешно связываться с базой.

Создание модели Post

Создавая модель Cake, которая будет взаимодействовать с нашей базой данных, мы получим потребность в создании операций «показать», «добавить», «редактировать», и «удалить». Файлы класса модели Cake здесь /app/models, а файл который мы будем создавать будет сохранен в /app/models/post.php. Завершенный файл должен выглядить так:
/app/models/post.php
<?php 

class Post extends AppModel
{
    var $name = 'Post';
}
?>
В связи со способом, по которому классу и файлу даны имена, это говорит Cake'у, что вы хотите чтобы модель Post была доступна в нашем Post Controller, который связан с таблицей в нашей базе данных 'posts'. Переменная $name всегда стоит того, чтобы ее добавили, и используется чтобы совладать с некоторыми именами классов в PHP4.

Создание контроллера постов

Дальше мы создадим контроллер для наших постов. Контроллер это то, где будет весь код для взаимодействия с постами, и он также находится там где и все действия для этой модели. Нам нужно разместить этот новый контроллер в файл под названием posts_controller.php в нашем каталоге /app/controllers. Вот как должен выглядить основной контроллер: /app/controllers/posts_controller.php
<?php

class PostsController extends AppController
{
    var $name = 'Posts';
}
?>
Теперь добавим действие в наш контроллер. Когда пользователи запрашивают www.example.com/posts, это то же, что и запрос www.example.com/posts/index. С тех пор как мы хотим, чтобы пользователи могли просматривать список постов, когда они приходят по этой ссылке, действие index будет выглядить как это: /app/controllers/posts_controller.php (действие index добавлено)
<?php

class PostsController extends AppController
{
    var $name = 'Posts';
    function index()
    {
        $this->set('posts', $this->Post->findAll());
    }
}
?>
После определения функции index() в нашем Posts Controller, пользователи могут получить доступ к коду запрашивая www.example.com/posts/index. Также, если бы мы определили функцию foobar(), пользователи могли бы получить доступ по адресу www.example.com/posts/foobar. Простое указание в действие использует set() для вставки данных в отображение (которое мы создадим следующим). Устанавливается переменная отображения 'posts' эквивалентная возвращаемому значению метода findAll() модели Post. Наша модель Post автоматически доступна в $this->Post. Создание отображений постов Теперь когда у нас есть наша база данных соединена использованием нашей модели, а наш код приложения определен нашим контроллером, давайте создадим отображение для действия index, которое мы определили выше. Отображения Cake это просто фрагменты HTML и PHP, которые устанавливаются в разметку приложения. Разметки можно определять и переключаться между ними, но пока, давайте просто использовать стандартную. При назначении переменной 'posts' в отображении используя метод set()? Это будет передавать данные в отображение, которое будет выглядить как это: // print_r($posts) output:
Array 
( 
	[0] => Array 
		( 
		[Post] => Array 
			( 
			[id] => 1 
			[title] => The title 
			[body] => This is the post body. 
			[created] => 2009-06-03 
			[modified] => 
			) 
		) 
	[1] => Array 
	( 
	[Post] => Array 
		( 
		[id] => 2 
		[title] => A title once again 
		[body] => And the post body follows. 
		[created] => 2009-06-03
		[modified] => 
		) 
	) 
	[2] => Array
	( 
	[Post] => Array 
		( 
		[id] => 3 
		[title] => Title strikes back 
		[body] => This is really exciting! Not. 
		[created] => 2009-06-03
		[modified] => 
		) 
	) 
)
Файлы отображений Cake хранятся в /app/views внутри каталога названного в честь контроллера к которому они принадлежат (мы должны создать каталог 'posts' в таком случае). Для форматирования данных постов в приятную таблицу, наш код отображения может выглядить так:
/app/views/posts/index.thtml
<h2>Blog posts

<table>
    <tr>
        <th>Id</th>
        <th>Title</th>
        <th>Created</th>
    </tr>
    
   <!--Здесь проходим цикл через  масив $posts, выводя информацию о постах -->

    <?php foreach ($posts as $post): ?>
    <tr>
        <td><?php echo $post['Post']['id']; ?></td>
        <td>
            <?php echo $html->link($post['Post']['title'], "/posts/view/".$post['Post']['id']); ?>
        </td>
        <td><?php echo $post['Post']['created']; ?></td>
    </tr>
    <?php endforeach; ?>

</table>
Когда определяем ссылки в Cake, мы просто даем путь относящийся к базе приложения, а Cake заполняет оставшееся. То есть, наши ссылки будут принимать форму /controller/action/id. Теперь мы можем направить свой браузер на http://www.example.com/posts/index. Мы должны увидеть отображение, коректно сформатированное с заголовком и таблицей со списком постов. Если мы нажмем на одну из ссылок, которые мы создали в этом отображении (эта ссылка это заголовок поста с адресом /posts/view/some_id), мы наверняка будем осведомлены Cake'ом, что действие еще не определено. Мы создадим его сейчас: /app/controllers/posts_controller.php (view action added)
<?php
class PostsController extends AppController
{
    var $name = 'Posts';
    function index()
    {
          $this->set('posts', $this->Post->findAll());
    }
    function view($id = null)
    {
        $this->Post->id = $id;
        $this->set('post', $this->Post->read());
    }
}
?>
Теперь давайте создадим отображение для нашего нового действия 'view' и разместим в /app/views/posts/view.thtml.
/app/views/posts/view.thtml
<h2><?php echo $post['Post']['title']?></h2>
<p><small>Created: <?php echo $post['Post']['created']?></small></p>

<p><?php echo $post['Post']['body']?></p>

Добавление постов

Во-первых, начнем с действия add() в Posts Controller:
/app/controllers/posts_controller.php ( действие add добавлено)
<?php
class PostsController extends AppController
{
    var $name = 'Posts';
    function index()
    {
         $this->set('posts', $this->Post->findAll());
    }
    function view($id)
    {
        $this->Post->id = $id;
        $this->set('post', $this->Post->read());
    }
    function add()
    {
        if (!empty($this->data))
        {
            if ($this->Post->save($this->data))
            {
                $this->flash('Your post has been saved.','/posts');
            }
        }
    }
}
?>
Действие add(): если данные формы не пустые, попробовать сохранить модель поста использовав эти данные. Если по каким-то причинам данные не сохраняются, выдать ошибки верификации данных и отрендерить отображение с показом этих ошибок. Когда пользователь использует форму для отправки данных в наше приложение, эта информация доступна в $this->params. Мы можем вывести их с помощью pr(). $this->data это псеводоним для $this->params['data']. Функция $this->flash() это функция контроллера, которая отображает сообщения пользователю на секунду (используя разметку для флеш-сообщений) потом перенаправляет пользователя по другому адресу (/posts, в нашем случае). Если DEBUG стоит на 0 $this->flash() переадресует автоматически, однако, если DEBUG на 0 мы сможем увидить флеш верстку и кликнуть на сообщении чтобы управлять переадресацией. Вызываемый метод save() проверит наявность верификационных ошибок и не сохранит данные если таковые присутствуют.

Верификация данных

Чтобы воспользоваться преимуществами возможностей проверки, нам надо использовать HTML хелпер в вашем отображении. HTML хелпер доступен по умолчанию во всех отображениях в $html. Вот наше отображения для добавления:
/app/views/posts/add.thtml

<h2>Add Post
<form method="post" action="<?php echo $html->url('/posts/add')?>">
    <p>
        Title:
        <?php echo $html->input('Post/title', array('size' => '40'))?>
        <?php echo $html->tagErrorMsg('Post/title', 'Title is required.') ?>
    </p>
    <p>
        Body:
        <?php echo $html->textarea('Post/body', array('rows'=>'10')) ?>
        <?php echo $html->tagErrorMsg('Post/body', 'Body is required.') ?>
    </p>
    <p>
        <?php echo $html->submit('Save') ?>
    </p>
</form>
Как и с $html->link(), $html->url() будет генерировать подходящую ссылку из контроллера и действия, которое мы предоставили. По умолчанию, это выводит тег формы POST, но это можно модифицировать вторым параметром. Функции $html->input() и $html->textarea() убирает элементы формы одинаковых имен. Первый параметр сообщает Cake, к которой модели/полю они относятся, а второй параметр для дополнительных аттрибутов HTML (как размер поля). Функция tagErrorMsg() выводит сообщения об ошибках в случае появления верификационных проблем. Если мы хотим обновить свое отображение /app/views/posts/index.thtml чтобы включить новую ссылку “Add Post” направляющую www.example.com/posts/add. Возвращение к модели.
/app/models/post.php (верификационный массив добавлен)
<?php
class Post extends AppModel
{
    var $name = 'Post';
    var $validate = array(
        'title'  => VALID_NOT_EMPTY,
        'body'   => VALID_NOT_EMPTY
    );
}
?>
Массив $validate сообщает Cake как проверять наши данные когда вызван метод save(). Значение для тех ключей просто константы установленные Cake'ом, который переводит их в регулярные выражения. Сейчас проверки Cake'а базируются на регулярных выражениях, но мы так же можем использовать Model::invalidate() чтобы просмотреть свои собственные верификации.

Удаление постов

Начнем с действия delete() в Posts Controller:
<?
/app/controllers/posts_controller.php (только действие delete)
function delete($id)
{
    $this->Post->del($id);
    $this->flash('The post with id: '.$id.' has been deleted.', '/posts');
}
?>
Этот код удаляет пост определенный по $id, и использует flash() чтобы показать пользователю сообщение подтверждения перед переадрисаций в /posts. Поскольку мы просто выполняем некий код и переадресовуем, это действие не имеет отображения. Мы можем обновить отображения index чтобы позволить пользователям удалять посты.
/app/views/posts/index.thtml (добавленны ссылки добавления и удаления)
<h2>Blog posts</h2>

<p><?php echo $html->link('Add Post', '/posts/add'); ?></p>
<table>
    <tr>
        <th>Id</th>
        <th>Title</th>
        <th>Created</th>
    </tr>

   <!-- Цикл в котором показуются посты -->

    <?php foreach ($posts as $post): ?>
    <tr>
        <td><?php echo $post['Post']['id']; ?></td>
        <td>
            <?php echo $html->link($post['Post']['title'], '/posts/view/'.$post['Post']['id']);?>
            <?php echo $html->link(
                'Delete',
                "/posts/delete/{$post['Post']['id']}",
                null,
                'Are you sure?'
            )?>
        </td>
        </td>
        <td><?php echo $post['Post']['created']; ?></td>
    </tr>
    <?php endforeach; ?>

</table>

Редактирование постов

Вот как будет выглядить действие редактирования Posts Controller:
/app/controllers/posts_controller.php (только действие edit)
<?
function edit($id = null)
{
    if (empty($this->data))
    {
        $this->Post->id = $id;
        $this->data = $this->Post->read();
    }
    else
    {
        if ($this->Post->save($this->data['Post']))
        {
            $this->flash('Your post has been updated.','/posts');
        }
    }
}
?>
Это проверяет на наличие отправленных данных формы. Если ничего не отправлено, ищем пост и отправляем его в отображение. Если какие-то данные были отправлены, пробуем сохранить модель Post.
Отображение редактирования может выглядить так:
/app/views/posts/edit.thtml
<h2>Edit Post</h2>

<form method="post" action="<?php echo $html->url('/posts/edit')?>">
    <?php echo $html->hidden('Post/id'); ?>
    <p>
        Title:
        <?php echo $html->input('Post/title', array('size' => '40'))?>
        <?php echo $html->tagErrorMsg('Post/title', 'Title is required.') ?>
    </p>
    <p>
        Body:
        <?php echo $html->textarea('Post/body', array('rows'=>'10')) ?>
        <?php echo $html->tagErrorMsg('Post/body', 'Body is required.') ?>
    </p>
    <p>
        <?php echo $html->submit('Save') ?>
    </p>
</form>
Это отображение выводит форму редактирования (с заполненными значениями), и нужные сообщения об ошибках (если есть). Теперь мы можем обновить наше отображение index ссылками на редактирование определенных постов:
/app/views/posts/index.thtml (edit links added)
<h2>Blog posts</h2>
<p><?php echo $html->link("Add Post", "/posts/add"); ?>
<table>
    <tr>
        <th>Id</th>
        <th>Title</th>
        <th>Created</th>
    </tr>

   <!-- Здесь в цикле отображаются посты -->

    <?php foreach ($posts as $post): ?>
    <tr>
        <td><?php echo $post['Post']['id']; ?></td>
        <td>
            <?php echo $html->link($post['Post']['title'], '/posts/view/'.$post['Post']['id']);?>
            <?php echo $html->link(
                'Delete',
                "/posts/delete/{$post['Post']['id']}",
                null,
                'Are you sure?'
            )?>
            <?php echo $html->link('Edit', '/posts/edit/'.$post['Post']['id']);?>
        </td>
        </td>
        <td><?php echo $post['Post']['created']; ?></td>
    </tr>
    <?php endforeach; ?>

</table>

Скаффолдинг

Скаффолдинг (scaffolding) – это технология, позволяющая разработчикам определять и разрабатывать базовые приложения, способные создавать, получать, изменять и удалять объекты. Кроме того, скаффолдинг в CakePHP позволяет разработчикам определять, как объекты связаны между собой, а также создавать и разрывать такие связи. Все, что необходимо для создания скаффолдинга – это модель и её контроллер. Определив в файле контроллера переменную $scaffold, мы будм готовы к работе. Скаффолдинг – хороший путь на этапах проектирования веб-приложений. Для уменьшения нагрузки на разработчика, в CakePHP был включен скаффолдинг. Механизм скаффолдинга анализирует наши таблицы и создает стандартные списки, кнопки «добавить», «удалить» и «изменить», а также стандартные формы для редактирования, и отображение для просмотра отдельных элементов, хранящихся в БД. Для добавления скаффолдинга, определите в контроллере переменную $scaffold:
<?php
class CategoriesController extends AppController {
    var $scaffold;
}
?>
Скаффолдинг знает об ассоциациях моделей, поэтому если наша модель Category belongsTo User, то мы увидим связанные ID пользователя в списке категорий. Если мы захотим увидеть что-либо кроме ID (например, имя пользователя), то мы можем определить в модели переменную $displayField. Определим переменную $displayField в нашем классе User, чтобы связанные с категориями пользователи отображались в скаффолдинге по имени, а не по ID.
<?php
class User extends AppModel {
    var $name = 'User';
    var $displayField = 'first_name';
}
?>

Изменение отображений скаффолдинга

Изменение выполняется путем создания шаблонов. Измененные отображения скаффолдинга для определенного контроллера (в данном примере - PostsController) должны быть размещены так:

/app/views/posts/scaffold.index.ctp
/app/views/posts/scaffold.show.ctp
/app/views/posts/scaffold.edit.ctp
/app/views/posts/scaffold.new.ctp
Измененные отображения скаффолдинга для всех контроллеров должны быть размещены так:

/app/views/scaffolds/index.ctp
/app/views/scaffolds/show.ctp
/app/views/scaffolds/edit.ctp
/app/views/scaffolds/new.ctp
/app/views/scaffolds/add.ctp

Итог

Создание приложений таким способом выиграет вам время. И это всего лишь пример, основы. Cake обладает большим количеством возможностей и является очень гибким. Это руководство можно использовать как начало для создания более богатых на возможности приложений.

Теперь можно смело начинать свой собственный проект, прочитав более глубокое руководство и API.

В глобальной сети очень много ресурсов посвященных Cake, где можно найти уйму полезных вещей!

Над материалом работал:
Владислав Разенков
загрузка...
Сторінки, близькі за змістом