Плагины¶
CakePHP позволяет настроить комбинацию контроллеров, моделей и представлений и предоставить ее в качестве плагина, который может быть использован в других приложениях. У вас есть модуль для управлением пользователями, простой блог, или модуль веб сервиса в вашем приложении? Сделайте из них плагины, чтобы иметь возможность использовать их в других приложениях в дальнейшем.
Основная связь между плагином и приложением, в котором он установлен, это конфигурация (настройки базы данных, и т.д.). В противном случае он работает в своем небольшом пространстве и ведет себя как будто это отдельное приложение.
Установка плагина¶
Чтобы установить плагин, необходимо поместить его в папку плагинов в app/Plugin. Если вы устанавливаете плагин ‘ContactManager’, то в директории app/Plugin вы должны иметь папку ‘ContactManager’, в которой находятся View, Model, Controller, webroot, и другие каталоги плагина.
В CakePHP 2.0, в отличие от предыдущих версий, плагины необходимо подключать вручную в app/Config/bootstrap.php.
Вы можете подключать их как по одному, так и все сразу:
CakePlugin::loadAll(); // Загружает все плагины
CakePlugin::load('ContactManager'); //Загружает один плагин
loadAll() загружает все доступные плагины и позволяет установить определенные настройки для каждого плагина. load() работает по похожему принципу, только загружает только указанные плагины.
С помощью load и loadAll вы можете повлиять на настройки и роутинг плагинов. Возможно, вы захотите загружать все плагины автоматически указывая пользовательские маршруты и файлы bootstrap для определенных плагинов.
Без проблем:
CakePlugin::loadAll(array(
'Blog' => array('routes' => true),
'ContactManager' => array('bootstrap' => true),
'WebmasterTools' => array('bootstrap' => true, 'routes' => true),
));
Вызывая плагины в таком стиле, вы больше не нуждаетесь в ручном подключении include() или require() настроек или маршрутизации плагина - это происходит автоматически в нужное время в нужном месте. Точно такие же параметры можно передавать методу load(), который загрузит только указанные плагины.
Наконец, вы можете указать параметры по умолчанию для loadAll, которые будут применены ко всем плагинам, если для них не указаны другие настройки.
Например, чтобы загрузить файлы bootstrap для всех плагинов и маршрутизацию для плагина Blog необходимо:
CakePlugin::loadAll(array(
array('bootstrap' => true),
'Blog' => array('routes' => true)
));
Обратите внимание, что все указанные файлы должны существовать в соответствующих плагинах, иначе PHP выдаст предупреждение для каждого файла, который не сможет загрузить. Это особенно важно помнить при указании настроек по умолчанию для всех плагинов.
Некоторые плагины требуют создания одной или нескольких таблиц в базе данных. В этих случаях плагины часто комплектуются schema-файлом, который можно вызвать из консоли Cake:
user@host$ cake schema create --plugin ContactManager
В документации к большинству плагинов будет указано, как правильно их настроить и какие изменения в базу данных необходимо внести. Некоторые плагины потребуют более тонкой настройки, чем другие.
Использование плагина¶
Вы можете обращатся к контроллерам, моделям, компонентам, поведениям и помошникам плагина путем добавления префикса (названия плагина) к имени класса.
Например, вы хотите использовать помошник ContactInfoHelper плагина ContactManager, чтобы вывести какую-нибудь контактную информацию в красивом виде в одном из ваших представлений. В таком случае в контроллере массив $helpers приобретет следующий вид:
public $helpers = array('ContactManager.ContactInfo');
После этого к помошнику можно обращаться, как и к другим помошникам в представлении:
echo $this->ContactInfo->address($contact);
Создание новых плагинов¶
Дла примера создадим плагин ContactManager, упомянутый выше. Для начала сделаем базовую структуру каталогов. Она должна выглядеть так:
/app
/Plugin
/ContactManager
/Controller
/Component
/Model
/Behavior
/View
/Helper
/Layouts
Обратите внимание, что папка плагина называется ‘ContactManager‘. Важно, чтобы название этой папки совпадало с названием самого плагина.
Вы заметите, что внутри папки плагина все выглядит, как обычное CakePHP приложение, чем оно, по сути, и является. На самом деле, не обязательно создавать те каталоги, которые не будут использоваться. Например, некоторые плагины содержат только компонент и поведение. В таком случае можно не создавать папку ‘View’.
Плагин также может содержать любые другие директории, которые есть у приложения, такие как: Config, Console, Lib, webroot, и т.д.
Примечание
Чтобы иметь доступ к плагину через URL, для него необходимо создать AppController и AppModel. Эти два класса должны иметь название с префиксом, состоящим из имени плагина (в данном случае префикс ‘ContactManager’). Они наследуют классы AppController и AppModel соответственно. Вот как они должны выглядеть для плагина ContactManager:
// /app/Plugin/ContactManager/Controller/ContactManagerAppController.php:
class ContactManagerAppController extends AppController {
}
// /app/Plugin/ContactManager/Model/ContactManagerAppModel.php:
class ContactManagerAppModel extends AppModel {
}
Если вы забудете объявить эти классы, то при попытке доступа к плагину через URL, CakePHP будет выдавать ошибку “Missing Controller”, пока вы их не объявите.
Обратите внимание, что процесс создания плагинов сильно упрощается при использовании коммандной строки Cake.
Чтобы “приготовить” плагин используйте следующую комманду:
user@host$ cake bake plugin ContactManager
Теперь, используя те же правила, вы можете “приготовить” остальные части плагина. Например, “приготовить” контроллеры:
user@host$ cake bake controller Contacts --plugin ContactManager
См. главу /console-and-shells/code-generation-with-bake, если вас возникли вопросы касательно коммандной строки.
Контроллеры плагина¶
Контроллеры плагина ContactManager будут находиться в /app/Plugin/ContactManager/Controller/. Так как основная задача этого плагина управление контактами, нам понадобится создать ContactsController.
Итак, мы размещаем новый ContactsController в /app/Plugin/ContactManager/Controller с кодом:
// /app/Plugin/ContactManager/Controller/ContactsController.php
class ContactsController extends ContactManagerAppController {
public $uses = array('ContactManager.Contact');
function index() {
//...
}
}
Примечание
Этот контроллер наследует AppController плагина (который называется ContactManagerAppController), а не AppController приложения.
Также обратите внимание, что имена моделей содержат префикс из имени плагина. Это необходимо для разделения моделей плагина и приложения.
В этом примере массив $uses можно опустить, так как модель ContactManager.Contact является основной моделью этого контроллера, он иллюстрирует, как правильно подключать модели в плагине.
Если вы хотите посмотреть, что у нас в итоге вышло, перейдите в /contact_manager/contacts. Вы должны увидеть ошибку “Missing Model”, так как мы еще не создали модель Contact.
Модели плагина¶
Модели плагина находятся в /app/Plugin/ContactManager/Model. Мы уже создали ContactsController, теперь сделаем модель Contact для этого контроллера:
// /app/Plugin/ContactManager/Model/Contact.php:
class Contact extends ContactManagerAppModel {
}
Теперь, зайдя в /contact_manager/contacts (предположим, вы создали таблицу ‘contacts’ в базе данных), вы увидите ошибку “Missing View”. Далее сделаем представление.
Примечание
Если вам необходимо связать модели в плагине, вы должны ставить имя плагина перед именем модели, разделяя их запятой.
Например:
// /app/Plugin/ContactManager/Model/Contact.php:
class Contact extends ContactManagerAppModel {
public $hasMany = array('ContactManager.AltName');
}
Если вы не желаете, чтобы ключи массивов связанной модели содержали префикс с именем плагина, используйте альтернативный синтаксис:
// /app/Plugin/ContactManager/Model/Contact.php:
class Contact extends ContactManagerAppModel {
public $hasMany = array(
'AltName' => array(
'className' => 'ContactManager.AltName'
)
);
}
Представления плагинов¶
Представления в плагинах работают так же, как и в обычных приложениях. Нужно всего лишь поместить их в правильную папку внутри каталога /app/Plugin/[PluginName]/View/. Для нашего плагина ContactManager, нам нужно представление для действия ContactsController::index(). Сделаем его:
// /app/Plugin/ContactManager/View/Contacts/index.ctp:
<h1>Contacts</h1>
<p>Following is a sortable list of your contacts</p>
<!-- Сортированный список контактов будет здесь....-->
Примечание
Чтобы узнать как использовать элементы плагина, см. Элементы
Переопределение представлений плагина в приложении¶
Вы можете переопределить любое представление плагина из приложения, используя специальные пути: “app/View/Plugin/[Plugin]/[Controller]/[view].ctp”. Например, для изменения представления действия index контроллера Contacts плагина ContactManager создайте следующий файл:
/app/View/Plugin/ContactManager/Contacts/index.ctp
Этот файл переопределит исходный файл “/app/Plugin/ContactManager/View/Contacts/index.ctp”.
Статические ресурсы плагина¶
Статика плагина (но не PHP файлы) должна находиться в папке ‘webroot’, так же, как и для обычного приложения:
app/Plugin/ContactManager/webroot/
css/
js/
img/
flash/
pdf/
Вы можете вставлять любые файлы в любую папку. Единственное ограничение, это то, что для MediaView необходимо указывать mime-тип статического контента.
Ссылки на статический контент в плагине¶
Прсто добавляйте /plugin_name/ в пути файлов и ссылки будут формироваться, как будто файлы лежат в webroot приложения.
Например, ссылка ‘/contact_manager/js/some_file.js’ будет вести к файлу ‘app/Plugin/ContactManager/webroot/js/some_file.js’.
Примечание
Важно отметить, что необходимо использовать префикс /your_plugin/ в ссылках на статику. Это приводит в действие магию!
Компоненты, помощники и поведения¶
Плагины могут содержать компоненты, помощники и поведения, как и обычное CakePHP приложение. Вы даже можете делать плагины, которые содержат только компоненты, помощники или поведения, что может быть отличным решением для создания многократно используемого компонента, который легко подключить к любому проекту.
Процесс создания этих компонентов в точности такой же, как и в обычном приложении, без специальных правил именования.
Обращение к компоненту из плагина или из приложения требует только наличия префикса имени плагина. Например:
// Компонент определенный в плагине 'ContactManager'
class ExampleComponent extends Component {
}
// в контроллерах:
public $components = array('ContactManager.Example');
То же самое применимо к помощникам и поведениям.
Примечание
При создании помощников класс AppHelper не доступен. Вы должны подключить его с помощью App::uses:
// Подключение AppHelper для помощника плагина
App::uses('AppHelper', 'View/Helper');
Расширение плагина¶
Этот пример послужит хорошим началом для создания плагина, однако вы можете сделать намного больше. Как правило, все, что вы можете сделать в приложении, вы можете сделать вместо этого в плагине.
Забегая вперед, вы можете добавить сторонние библиотеки в ‘Vendor’, добавить новые оболочки в консоль Cake и не забудьте сделать тесты чтобы пользователи могли автоматически проверить работоспособность вашего плагина!
В нашем примере ContactManager, мы могли бы сделать действия для добавления/удаления/редактирования/ в ContactsController, осуществить проверку данных в модели Contact и реализовать функционал для редактирования пользователями своих контактов. Решать вам, что воплощать в своих плагинах. Только не забудьте поделиться своим кодом с сообществом, чтобы каждый получил пользу от ваших великолепных плагинов!
Советы к плагинам¶
Как только плагин установлен в /app/Plugin, он становится доступен (если для него созданы AppController и AppModel, см. выше) по URL /plugin_name/controller_name/action. В нашем примере плагина ContactManager мы имеем доступ к ContactsController в /contact_manager/contacts.
Некоторые последние советы по работе с плагинами в CakePHP приложении:
- Если вы не создали [Plugin]AppController и [Plugin]AppModel, то получите ошибки при попытке доступа к контроллерам плагина.
- Вы можете сделать свои лэйауты в app/Plugin/[Plugin]/View/Layouts. Иначе плагины будут использовать лэйауты по умолчанию из /app/View/Layouts.
- Плагины могут общаться между собой, используя $this->requestAction('/plugin_name/controller_name/action'); в контроллерах.
- Если вы используете requestAction, убедитесь что названия контроллера и модели уникальны, насколько это возможно. В противном случае вы можете получить ошибку PHP “redefined class ...”