Плагины

CakePHP позволяет вам настроить комбинацию контроллеров, моделей, и просматривать и выпускать их в виде готовых к использованию приложений, которые другие пользователи могут использовать в своих приложения CakePHP. Если вы создали отличный менеджер пользователей, простой блог или модуль веб-сервисов в одном из ваших приложений, почему бы не упаковать его как плагин CakePHP? Таким образом, вы может повторно использовать его в других приложениях и делиться им с сообществом!

Плагин CakePHP в конечном счёте отделён от самого хост-приложения и, как правило, предоставляет некоторые чётко определенные функции, которые могут быть аккуратно упакованы и повторно использованы с небольшими усилиями в других приложениях. Приложение и плагин работают в своих соответствующих пространствах, но совместно используют свойства хост-приложения (например, параметры подключения к базе данных), которые определены и разделены через конфигурацию приложения.

В CakePHP 3.0 каждый плагин определяет собственное пространство имён верхнего уровня. Например: DebugKit. По соглашению, плагины используют своё имя пакета в качестве своего пространства имен. Если вы хотите использовать другое пространство имён, вы можете настроить плагину пространство имен, когда загружаются плагины.

Установка плагина с Composer

Многие плагины доступны на Packagist и могут быть установлены с помощью Composer. Чтобы установить DebugKit, вам нужно сделать следующее:

php composer.phar require cakephp/debug_kit

Это установит последнюю версию DebugKit и обновит ваш composer.json, файл composer.lock, обновит vendor/cakephp-plugins.php, и обновит ваш автозагрузчик.

Если плагин, который вы хотите установить, недоступен на packagist.org, вы можете клонировать или копировать код плагина в каталог plugins. Предполагая, что вы хотите установить плагин с именем „ContactManager“, у вас должна быть папка в plugins с именем „ContactManager“. В этом каталоге будут находится src, тесты и любые другие каталоги данного плагина.

Файл карты плагина

При установке плагинов через Composer вы можете заметить, что создаётся vendor/cakephp-plugins.php. Этот файл конфигурации содержит карту имён плагинов и их путей в файловой системе. Это позволяет устанавливать плагины в стандартный каталог поставщиков, который находится за пределами обычных путей поиска. Класс Plugin будет использовать этот файл для поиска плагинов, когда они загружаются с помощью load() или loadAll(). Вам обычно не нужно будет редактировать этот файл вручную, поскольку Composer и пакет plugin-installer будут управлять ими за вас.

Загрузка плагина

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

// В config/bootstrap.php
// Или в in Application::bootstrap()

// Загружает один плагин
Plugin::load('ContactManager');

// Загружает плагин с пространством имён поставщиков на верхнем уровне.
Plugin::load('AcmeCorp/ContactManager');

// Loads all plugins at once
Plugin::loadAll();

loadAll() загружает все доступные плагины, позволяя вам устанавливать определённые настройки для определённых плагинов. load() работает аналогично, но загружает только те плагины, которые вы явно указываете.

Примечание

Plugin::loadAll() не будет загружать плагины с расширением имён поставщиков, которые не определены в vendor/cakephp-plugins.php.

Также есть удобная команда оболочки для включения плагина. Выполните следующую строку:

bin/cake plugin load ContactManager

Это приведёт к загрузке Plugin::load('ContactManager'); snippet в bootstrap для вас.

Автозагрузка классов плагина

При использовании bake для создания плагина или при установке плагина с использованием Composer, вам обычно не нужно вносить какие-либо изменения в ваше приложение, чтобы CakePHP распознавал классы, которые живут внутри него.

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

"psr-4": {
    (...)
    "MyPlugin\\": "plugins/MyPlugin/src/",
    "MyPlugin\\Test\\": "plugins/MyPlugin/tests/"
}

Если вы используете пространства имён поставщиков для своих плагинов, сопоставление пространства имён в пути должно выглядеть следующим образом:

"psr-4": {
    (...)
    "AcmeCorp\\Users\\": "plugins/AcmeCorp/Users/src/",
    "AcmeCorp\\Users\\Test\\": "plugins/AcmeCorp/Users/tests/"
}

Кроме того, вам нужно будет сообщить Composer об обновлении кеша автозагрузки:

$ php composer.phar dumpautoload

Если вы не можете использовать Composer по какой-либо причине, вы также можете использовать резервную автозагрузку для своего плагина:

Plugin::load('ContactManager', ['autoload' => true]);

Конфигурация плагина

Методы load() и loadAll() могут помочь в настройке и маршрутизации плагинов. Возможно, вы хотите загрузить все плагины автоматически, указав собственные маршруты и файлы начальной загрузки для определенных плагинов:

// В config/bootstrap.php,
// или в Application::bootstrap()

// Используем loadAll()
Plugin::loadAll([
    'Blog' => ['routes' => true],
    'ContactManager' => ['bootstrap' => true],
    'WebmasterTools' => ['bootstrap' => true, 'routes' => true],
]);

Или вы можете загружать плагины индивидуально:

// Загрузка только блога и включение маршрутов
Plugin::load('Blog', ['routes' => true]);

// Включить файл конфигурации начальной загрузки / инициализации.
Plugin::load('ContactManager', ['bootstrap' => true]);

При любом подходе, вам больше не нужно ручное подключение конфигурации плагина или файла маршрутов через include() или require(), - это происходит автоматически в нужное время и в нужном месте.

Вы можете указать набор значений по умолчанию для loadAll(), который будет применяться к каждому плагину, который не имеет более конкретной конфигурации.

Следующий пример загрузит загрузочный файл из всех плагинов, а также маршруты из плагина Blog:

Plugin::loadAll([
    ['bootstrap' => true],
    'Blog' => ['routes' => true]
]);

Обратите внимание, что все указанные файлы должны фактически существовать в настроенных плагине(-ах), или PHP выдаст предупреждения для каждого файла, который он не может загрузить. Вы можете избежать возможных предупреждений, используя опцию ignoreMissing:

Plugin::loadAll([
    ['ignoreMissing' => true, 'bootstrap' => true],
    'Blog' => ['routes' => true]
]);

При загрузке плагинов, используемое имя плагина должно соответствовать пространству имён. Например, если у вас есть плагин с пространством имён верхнего уровня Users, вы должны загрузить его с помощью:

Plugin::load('User');

Если вы предпочитаете иметь имя своего поставщика как верхний уровень и иметь пространство имён, например AcmeCorp/Users, то вы должны загрузить плагин так:

Plugin::load('AcmeCorp/Users');

Это обеспечивает правильное разрешение имён классов при использовании plugin syntax.

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

Использование плагинов

Вы можете ссылаться на контроллеры плагинов, модели, компоненты, поведение и помощники, перед этим, предварительно указав имя плагина.

Например, предположим, что вы хотите использовать ContactInfoHelper плагина ContactManager для вывода некоторой контактной информации в одном из ваших представлений. В вашем контроллере ваш массив $helpers может выглядеть так:

public $helpers = ['ContactManager.ContactInfo'];

Примечание

Это разделённое точкой имя класса описывается в plugin syntax.

Затем вы сможете получить доступ к ContactInfoHelper, как и к любому другому помощнику в вашем представлении, например:

echo $this->ContactInfo->address($contact);

Создание собственных плагинов

В качестве рабочего примера давайте начнём создавать плагин ContactManager, упомянутый выше. Для начала мы создадим нашу базовую структуру плагина. Это должно выглядеть так:

/src
/plugins
    /ContactManager
        /config
        /src
            /Controller
                /Component
            /Model
                /Table
                /Entity
                /Behavior
            /View
                /Helper
            /Template
                /Layout
        /tests
            /TestCase
            /Fixture
        /webroot

Обратите внимание на имя папки плагина, „ContactManager“. Важно, чтобы эта папка имела то же имя, что и плагин.

Внутри папки плагина вы заметите, что он очень похож на приложение CakePHP, и это в основном то, что есть. Вам не нужно включать какие-либо папки, которые вы не используете. Некоторые плагины могут определять только компонент и поведение, и в этом случае они могут полностью опустить каталог „Template“.

Плагин также может содержать любые другие каталоги, которые могут использовать ваше приложение, такие как Config, Console, webroot и т. Д.

Создание плагина с использованием Bake

Процесс создания плагинов может быть значительно упрощён с использованием оболочки bake.

Чтобы испечь(создать) плагин, используйте следующую команду:

bin/cake bake plugin ContactManager

Теперь вы можете дальше создавать ваше приложение, используя те же соглашения, которые применяются к остальной части вашего приложения. Например - контроллеры для выпечки:

bin/cake bake controller --plugin ContactManager Contacts

Пожалуйста, обратитесь к главе Генерация кода с помощью Bake, если у вас возникли проблемы с использованием командной строки. Обязательно заново создайте автозагрузчик после создания плагина:

$ php composer.phar dumpautoload

Маршрутизация плагина

Плагины могут предоставлять файлы маршрутов, содержащие их маршруты Каждый плагин может содержать файл config/routes.php. Этот файл маршрутов может быть загружен при добавлении плагина или загружен в файл маршрутов приложения. Чтобы создать маршруты плагинов ContactManager, введите следующее в plugins/ContactManager/config/routes.php:

<?php
use Cake\Routing\Route\DashedRoute;
use Cake\Routing\Router;

Router::plugin(
    'ContactManager',
    ['path' => '/contact-manager'],
    function ($routes) {
        $routes->get('/contacts', ['controller' => 'Contacts']);
        $routes->get('/contacts/:id', ['controller' => 'Contacts', 'action' => 'view']);
        $routes->put('/contacts/:id', ['controller' => 'Contacts', 'action' => 'update']);
    }
);

Вышеуказанное свяжет стандартные маршруты для вашего плагина. Вы можете настроить этот файл с более конкретными маршрутами позже.

Прежде чем вы сможете получить доступ к своим контроллерам, вам необходимо убедиться, что плагин загружен и загружены маршруты плагина. В вашем config/bootstrap.php добавьте следующее:

Plugin::load('ContactManager', ['routes' => true]);

Вы также можете загружать маршруты плагинов в список маршрутов вашего приложения. Это даёт вам больший контроль над тем, как загружаются маршруты плагинов, и позволяет вам переносить маршруты плагинов в дополнительные области или префиксы:

Router::scope('/', function ($routes) {
    // Подключаем другие маршруты.
    $routes->scope('/backend', function ($routes) {
        $routes->loadPlugin('ContactManager');
    });
});

Вышеизложенное приведёт к URL-адресам, таким как /backend/contact_manager/contacts.

Добавлено в версии 3.5.0: RouteBuilder::loadPlugin() был добавлен в 3.5.0

Контроллеры плагина

Контроллеры для нашего плагина ContactManager будут храниться в plugins/ContactManager/src/Controller/. Поскольку главное, что мы будем делать, это управление контактами, нам понадобится ContactController для этого плагина.

Итак, мы размещаем наш новый ContactController в plugins/ContactManager/src/Controller и это выглядит так:

// plugins/ContactManager/src/Controller/ContactsController.php
namespace ContactManager\Controller;

use ContactManager\Controller\AppController;

class ContactsController extends AppController
{

    public function index()
    {
        //...
    }
}

Также создайте AppController, если у вас его еще нет:

// plugins/ContactManager/src/Controller/AppController.php
namespace ContactManager\Controller;

use App\Controller\AppController as BaseController;

class AppController extends BaseController
{
}

Плагины ``AppController``(а) могут содержать логику контроллера, общую для всех контроллеров в плагине, но не обязательно, если вы не хотите её использовать.

Если вы хотите получить доступ к тому, что у нас уже есть, посетите /contact-manager/contacts. Вы должны получить ошибку «Отсутствующая модель», потому что у нас ещё нет модели контактов.

Если ваше приложение включает в себя маршрутизацию по умолчанию CakePHP, вы сможете получить доступ к своим контроллерам плагинов, используя URL-адреса, такие как:

// Получаем доступ к указательному маршруту контроллера плагина.
/contact-manager/contacts

// Любые действия над контроллером плагина.
/contact-manager/contacts/view/1

Если ваше приложение определяет префикс маршрутизации, то по умолчанию маршрутизация CakePHP будет также включать маршруты, которые используют следующий шаблон:

/:prefix/:plugin/:controller
/:prefix/:plugin/:controller/:action

См. Раздел о Конфигурация плагина для получения информации о том, как загружать файлы маршрутов с плагинами.

Для плагинов, которые вы не создавали с помощью bake, вам также нужно будет отредактировать файл composer.json, чтобы добавить ваш плагин к классам автозагрузки, это можно сделать в соответствии с документацией Автозагрузка классов плагина.

Модели плагина

Модели для плагина хранятся в plugins/ContactManager/src/Model. Мы уже определили ContactController для этого плагина, поэтому давайте создадим таблицу и объект для этого контроллера:

// plugins/ContactManager/src/Model/Entity/Contact.php:
namespace ContactManager\Model\Entity;

use Cake\ORM\Entity;

class Contact extends Entity
{
}

// plugins/ContactManager/src/Model/Table/ContactsTable.php:
namespace ContactManager\Model\Table;

use Cake\ORM\Table;

class ContactsTable extends Table
{
}

Если вам нужно ссылаться на модель внутри вашего плагина при создании ассоциаций или определении классов сущностей, вам нужно указать имя плагина с именем класса, разделённым точкой. Например:

// plugins/ContactManager/src/Model/Table/ContactsTable.php:
namespace ContactManager\Model\Table;

use Cake\ORM\Table;

class ContactsTable extends Table
{
    public function initialize(array $config)
    {
        $this->hasMany('ContactManager.AltName');
    }
}

Если вы предпочитаете, чтобы в ключах массива для ассоциации не был установлен префикс плагина, используйте альтернативный синтаксис:

// plugins/ContactManager/src/Model/Table/ContactsTable.php:
namespace ContactManager\Model\Table;

use Cake\ORM\Table;

class ContactsTable extends Table
{
    public function initialize(array $config)
    {
        $this->hasMany('AltName', [
            'className' => 'ContactManager.AltName',
        ]);
    }
}

Вы можете использовать TableRegistry для загрузки таблиц ваших плагиновых, используя знакомый plugin syntax:

use Cake\ORM\TableRegistry;

$contacts = TableRegistry::get('ContactManager.Contacts');

Кроме того, из контекста контроллера вы можете использовать:

$this->loadModel('ContactsMangager.Contacts');

Представления плагина

Представления ведут себя точно так же, как в обычных приложениях. Просто поместите их в нужную папку внутри папки plugins/[PluginName]/src/Template/. Для нашего плагина ContactManager нам понадобится представление для нашего действия ContactsController::index(), поэтому давайте это сделаем:

// plugins/ContactManager/src/Template/Contacts/index.ctp:
<h1>Контакты</h1>
<p>Ниже приведён отсортированный список ваших контактов</p>
<!-- Здесь будет отсортированный список контактов....-->

Плагины могут предоставлять свои собственные макеты. Чтобы добавить плагины, разместите файлы шаблонов внутри plugins/[PluginName]/src/Template/Layout. Чтобы использовать плагин в вашем контроллере, вы можете сделать следующее:

public $layout = 'ContactManager.admin';

Если префикс плагина опущен, файл layout/view (макета/представления) будет нормально расположен.

Примечание

Для получения информации о том, как использовать элементы из плагина, посмотрите Элементы

Переопределение шаблонов плагинов изнутри вашего приложения

Вы можете переопределить любые виды плагинов внутри вашего приложения, используя специальные пути. Если у вас есть плагин с именем „ContactManager“, вы можете переопределить файлы шаблонов плагина с помощью конкретной логики представления, создав файлы, использующие следующий шаблон src/Template/Plugin/[Plugin]/[Controller]/[view].ctp. Для контроллера контактов вы можете сделать следующий файл:

src/Template/Plugin/ContactManager/Contacts/index.ctp

Создание этого файла позволит вам переопределить plugins/ContactManager/src/Template/Contacts/index.ctp.

Если ваш плагин находится в зависимости от composer (т.е. „TheVendor/ThePlugin“), путь к представлению „index“ пользовательского контроллера будет следующим:

src/Template/Plugin/TheVendor/ThePlugin/Custom/index.ctp

Создание этого файла позволит вам переопределить vendor/thevendor/theplugin/src/Template/Custom/index.ctp.

Если плагин реализует префикс маршрутизации, вы должны включить префикс маршрутизации в свои переопределения шаблона приложения. Например, если плагин „ContactManager“ реализовал префикс „admin“, путь должен быть:

src/Template/Plugin/ContactManager/Admin/ContactManager/index.ctp

Ресурсы плагина

Веб-ресурсы плагина (но не файлы PHP) могут быть отправлены через директорию webroot плагина, как и основные ресурсы приложения:

/plugins/ContactManager/webroot/
                               css/
                               js/
                               img/
                               flash/
                               pdf/

Вы можете поместить любой тип файла в любой каталог, как и обычно в webroot.

Предупреждение

Обработка статических активов (таких как изображения, файлы JavaScript и CSS) через Диспетчер очень неэффективна. См. symlink-assets для получения дополнительной информации.

Связывание с активами в плагине

Вы можете использовать plugin syntax при связывании с активами плагина с помощью View\Helper\HtmlHelper скриптов, изображений или css-методов:

// Создаёт URL-адрес /contact_manager/css/styles.css
echo $this->Html->css('ContactManager.styles');

// Создаёт URL-адрес /contact_manager/js/widget.js
echo $this->Html->script('ContactManager.widget');

// Создаёт URL-адрес /contact_manager/img/logo.jpg
echo $this->Html->image('ContactManager.logo');

Активы плагина передаются с использованием фильтра диспетчера AssetFilter по умолчанию. Это рекомендуется только для разработки. В производстве вы должны использовать symlink plugin assets для повышения производительности.

Если вы не используете помощников(helpers), вы можете добавить /plugin_name/ в начало URL-адреса для актива в этом плагине для его обслуживания. Связывание с „/contact_manager/js/some_file.js“ будет служить активу plugins/ContactManager/webroot/js/some_file.js.

Компоненты, Помощники и Поведение

Плагин может содержать компоненты, помощники и поведение, как обычное приложение CakePHP. Вы даже можете создавать плагины, которые состоят только из Компонентов, Помощников или Поведений, которые могут быть отличным способом для создания повторно используемых компонентов, которые можно использовать в любом другом проекте.

Построение этих компонентов точно такое же, как создание его в рамках обычного приложения, т.е производится без специального соглашения об именах.

Обращаясь к вашему компоненту изнутри или снаружи вашего плагина, требуется только указать имя плагина перед именем компонента. Например:

// Компонент, определённый в плагине 'ContactManager'
namespace ContactManager\Controller\Component;

use Cake\Controller\Component;

class ExampleComponent extends Component
{
}

// Внутри ваших контроллеров
public function initialize()
{
    parent::initialize();
    $this->loadComponent('ContactManager.Example');
}

Тот же метод применяется к Помощникам и Поведению.

Расширьте свой плагин

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

Идите дальше - включите некоторые сторонние библиотеки в „vendor“, добавьте новые оболочки в консоль cake и не забудьте создать тестовые примеры, чтобы ваши пользователи плагина могли автоматически протестировать функциональность вашего плагина!

В нашем примере ContactManager мы могли бы добавить действия создания/удаления /редактирования в ContactController, реализовать проверку в модели Contact и реализовать функции, которые можно было бы ожидать при управлении своими контактами. Вам решать, что реализовать в своих плагинах. Просто не забывайте делиться своим кодом с сообществом, чтобы каждый мог воспользоваться вашими удивительными, многоразовыми компонентами!

Опубликуйте свой плагин

Убедитесь, что вы добавили плагин в plugins.cakephp.org <https://plugins.cakephp.org> _. Таким образом, другие люди могут использовать его как зависимость в composer. Вы также можете предложить свой плагин в список awesome-cakephp <https://github.com/FriendsOfCake/awesome-cakephp> _.

Выберите семантически значимое имя для пакета. В идеале это должен быть префикс зависимости „cakephp“ в качестве основы. Имя поставщика обычно будет вашим именем пользователя GitHub. Не используйте пространство имён CakePHP (cakephp), поскольку это зарезервировано для CakePHP, принадлежащих плагинам. Соглашение заключается в использовании строчных букв и тире в качестве разделителя.

Поэтому, если вы создали плагин „Logging“ с вашей учетной записью GitHub „FooBar“, хорошим именем будет foo-bar/cakephp-logging. И CakePHP, принадлежащий плагину „Localized“, можно найти под cakephp/localized соответственно.

Управление плагинами с помощью Микшера

Другой способ обнаружения и управления плагинами в вашем приложении CakePHP - Mixer. Это плагин CakePHP, который помогает вам устанавливать плагины из Packagist. Это также поможет вам управлять существующими плагинами.

Примечание

IMPORTANT: Не используйте это в продакшене.