O CakePHP permite que você configure uma combinação de controllers, models e views, que são os plugins de aplicativo empacotado que outros podem usar em suas aplicações CakePHP.
Se você criou um módulo de gerenciamento de usuários, blog ou serviços da Web em uma das suas aplicações, por que não torná-lo um plugin CakePHP? Desta forma, você pode reutilizá-lo em seus outros aplicativos e compartilhar com a comunidade!
Um plugin do CakePHP é, em última instância, separado do próprio aplicativo host e, geralmente, oferece algumas funcionalidades bem definidas que podem ser embaladas de maneira ordenada e reutilizadas com pouco esforço em outras aplicações. O aplicativo e o plugin operam em seus respectivos espaços, mas compartilham propriedades específicas da aplicação (parâmetros de conectividade de banco de dados) que são definidos e compartilhados através da configuração do aplicativo.
No CakePHP 3.0 cada plugin define seu próprio namespace de nível superior. Por exemplo: DebugKit
.
Por convenção, os plugins usam o nome do pacote como seu namespace. Se você quiser usar um espaço para nome diferente, você pode configurar o espaço para nome do plugin, quando os plugins são carregados.
Muitos plugins estão disponíveis no Packagist <http://packagist.org> _
E podem ser instalados com o Composer
. Para instalar o DebugKit, você
deve fazer assim o assim:
php composer.phar require cakephp/debug_kit
composer require cakephp/debug_kit
Isso instalaria a versão mais recente do DebugKit e atualizaria seus arquivos composer.json, composer.lock, atualiza vendor/cakephp-plugins.php e atualize seu autoloader.
Se o plugin que deseja instalar não estiver disponível em Packagist.org, você pode clonar ou copiar o código do plugin para seu diretório plugins, no raiz do aplicativo. Supondo que você deseja instalar um plugin chamado ‘ContactManager’, você deve ter uma pasta em plugins chamado ‘ContactManager’. Neste diretório existe o src, o plugin, testes e outros diretórios.
Ao instalar plugins através do Composer, você pode notar que
vendor/cakephp-plugins.php é criado. Este arquivo de configuração contém
um mapa de nomes de plugins e seus caminhos no sistema de arquivos. Isso torna possível
que os plugins sejam instalados no diretório padrão do vendor que está fora
dos caminhos de pesquisa normais. A classe Plugin
usará este arquivo para localizar
plugins quando são carregados com load ()
ou loadAll ()
. Você geralmente
não precisará editar este arquivo à mão, com Composer e plugin-installer
O pacote o gerenciará para você.
Depois de instalar um plugin e configurar o autoloader, você deve carregar O plugin. Você pode carregar plugins um a um, ou todos eles com um único método:
// In config/bootstrap.php
// Or in Application::bootstrap()
// Carrega um único plugin
Plugin::load('ContactManager');
// Carrega um plugin com um namespace no nível superior.
Plugin::load('AcmeCorp/ContactManager');
// Carrega todos os plugins de uma só vez
Plugin::loadAll();
loadAll()
carrega todos os plugins disponíveis, permitindo que você especifique determinadas
configurações para plugins. load()
funciona de forma semelhante, mas apenas carrega o
Plugins que você especifica explicitamente.
Nota
Plugin::loadAll()
não irá carregar os plugins vendor namespaced que não sãoDefinido em vendor/cakephp-plugins.php.
Há também um comando de shell acessível para habilitar o plugin. Execute a seguinte linha:
bin/cake plugin load ContactManager
Isso colocará o plugin Plugin::load('ContactManager');
no bootstrap para você.
Ao usar bake
para criar um plugin ou quando instalar um plugin usando o
Composer, você normalmente não precisa fazer alterações em seu aplicativo para
faça com que o CakePHP reconheça as classes que vivem dentro dele.
Em qualquer outro caso, você precisará modificar o arquivo do composer.json do seu aplicativo. Para conter as seguintes informações:
"psr-4": {
(...)
"MyPlugin\\": "./plugins/MyPlugin/src",
"MyPlugin\\Test\\": "./plugins/MyPlugin/tests"
}
Se você estiver usando o vendor namespaces para seus plugins, o espaço para nome para mapeamento de caminho deve se parecer com o seguinte:
"psr-4": {
(...)
"AcmeCorp\\Users\\": "./plugins/AcmeCorp/Users/src",
"AcmeCorp\\Users\\Test\\": "./plugins/AcmeCorp/Users/tests"
}
Além disso, você precisará dizer ao Composer para atualizar o cache de autoloading:
$ php composer.phar dumpautoload
Se você não conseguir usar o Composer por qualquer outro motivo, você também pode usar um recurso alternativo Autoloading para o seu plugin:
Plugin::load('ContactManager', ['autoload' => true]);
Os métodos load()
e loadAll()
podem ajudar na configuração do plugin
E roteamento. Talvez você queira carregar todos os plugins automaticamente enquanto especifica
Rotas personalizadas e arquivos bootstrap para determinados plugins:
// No config/bootstrap.php,
// ou in Application::bootstrap()
// Usando loadAll()
Plugin::loadAll([
'Blog' => ['routes' => true],
'ContactManager' => ['bootstrap' => true],
'WebmasterTools' => ['bootstrap' => true, 'routes' => true],
]);
Ou você pode carregar os plugins individualmente:
// Carregando apenas o blog e inclui rotas
Plugin::load('Blog', ['routes' => true]);
// Inclua o arquivo configuration/initializer do bootstrap.
Plugin::load('ContactManager', ['bootstrap' => true]);
Com qualquer uma das abordagens, você não precisa mais manualmente include()
ou
require()
configuração de um plugin ou arquivo de rotas - acontece
Automaticamente no momento e no lugar certos.
Você pode especificar um conjunto de padrões para loadAll()
que irá
aplicar a cada plugin que não tenha uma configuração mais específica.
O seguinte exemplo irá carregar o arquivo bootstrap de todos os plugins e além disso, as rotas do Blog Plugin:
Plugin::loadAll([
['bootstrap' => true],
'Blog' => ['routes' => true]
]);
Tenha em atenção que todos os arquivos especificados deveriam existir na configuração
o(s) plugin(s) ou PHP dará avisos para cada arquivo que não pode carregar. Você pode evitar
potenciais avisos usando a opção ignoreMissing
:
Plugin::loadAll([
['ignoreMissing' => true, 'bootstrap' => true],
'Blog' => ['routes' => true]
]);
Ao carregar os plugins, o nome do plugin usado deve corresponder ao namespace. Para
por exemplo, se você tiver um plugin com o namespace de nível superior Users
você carregaria
Usando:
Plugin::load('User');
Se você preferir ter seu nome vendor como nível superior e ter um espaço para nome como
AcmeCorp/Users
, então você carregaria o plugin como:
Plugin::load('AcmeCorp/Users');
Isso garantirá que os nomes das classes sejam resolvidos corretamente ao usar sintaxe plugin.
A maioria dos plugins indicará o procedimento adequado para configurá-los e configurar até o banco de dados em sua documentação. Alguns plugins exigirão mais configuração do que outros.
Você pode fazer referência aos controllers, models, components, behaviors, e helpers, prefixando o nome do plugin antes
Por exemplo, vamos supor que você queria usar o plugin do ContactManager
ContactInfoHelper para produzir algumas informações de contato legítimas em
uma das suas opiniões. No seu controller, o $helpers
array
poderia ficar assim:
public $helpers = ['ContactManager.ContactInfo'];
Nota
Esse nome de classe separado por pontos é denominado sintaxe plugin.
Você poderia então acessar o ContactInfoHelper
como
qualquer outro helper em sua view, como:
echo $this->ContactInfo->address($contact);
Apenas como um exemplo, vamos começar a criar o ContactManager plugin referenciado acima. Para começar, vamos configurar o nosso plugin estrutura de diretório básico. Deve ser assim:
/src
/plugins
/ContactManager
/config
/src
/Controller
/Component
/Model
/Table
/Entity
/Behavior
/View
/Helper
/Template
/Layout
/tests
/TestCase
/Fixture
/webroot
Observe o nome da pasta do plugin, ‘ContactManager’. É importante Que esta pasta tem o mesmo nome que o plugin.
Dentro da pasta do plugin, você notará que se parece muito com um aplicativo CakePHP, e é basicamente isso. Você não precisa incluir qualquer uma das pastas que você não está usando, ou seja, pode remover o que não for usar. Alguns plugins podem apenas define um Component e um Behavior, e nesse caso eles podem completamente omitir o diretório ‘Template’.
Um plugin também pode ter basicamente qualquer um dos outros diretórios de seu aplicativo, como Config, Console, webroot, etc.
O processo de criação de plugins pode ser bastante simplificado usando o bake shell.
Nota
Use sempre o bake para gerar código, isso evitará muitas dores de cabeça.
Para criar um plugin com o bake, use o seguinte comando:
bin/cake bake plugin ContactManager
Agora você pode user o bake com as mesmas convenções que se aplicam ao resto do seu aplicativo. Por exemplo - baking controllers:
bin/cake bake controller --plugin ContactManager Contacts
Consulte o capítulo Geração de código com bake se você tiver problemas para usar a linha de comando. Certifique-se de voltar a gerar o seu autoloader uma vez que você criou seu plugin:
$ php composer.phar dumpautoload
Os plugins podem fornecer arquivos de rotas contendo suas rotas. Cada plugin pode conter um arquivo config/routes.php. Este arquivo de rotas pode ser carregado quando o complemento é adicionado ou no arquivo de rotas do aplicativo. Para criar as rotas de plugins do ContactManager, coloque o seguinte 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']);
}
);
O código acima irá conectar as rotas padrão para o seu plugin. Você pode personalizar isso no arquivo com rotas mais específicas mais tarde:
Plugin::load('ContactManager', ['routes' => true]);
Você também pode carregar rotas de plugins na lista de rotas do seu aplicativo. Fazendo isso fornece mais controle sobre como as rotas do plugin são carregadas e permite que você envolva as rotas de plugin em escopos ou prefixos adicionais:
Router::scope('/', function ($routes) {
// Connect other routes.
$routes->scope('/backend', function ($routes) {
$routes->loadPlugin('ContactManager');
});
});
O código acima resultaria em URLs como /backend/contact_manager/contacts
.
Novo na versão 3.5.0: RouteBuilder::loadPlugin()
foi adicionado in 3.5.0
Os Controllers para o nosso plug-in do ContactManager serão armazenados em plugins/ContactManager/src/Controller/. Como a principal coisa que vamos estar fazendo gerenciar contatos, precisaremos de um ContactsController para este plugin.
Então, colocamos nosso new ContactsController em plugins/ContactManager/src/Controller e parece ser assim:
// plugins/ContactManager/src/Controller/ContactsController.php
namespace ContactManager\Controller;
use ContactManager\Controller\AppController;
class ContactsController extends AppController
{
public function index()
{
//...
}
}
Também faça o AppController
se você não possuir um já:
// plugins/ContactManager/src/Controller/AppController.php
namespace ContactManager\Controller;
use App\Controller\AppController as BaseController;
class AppController extends BaseController
{
}
Um AppController
do plugin pode manter a lógica do controller comum a todos os controllers
em um plugin, mas não é necessário se você não quiser usar um.
Se você deseja acessar o que temos chegado até agora, visite
/contact-manager/contacts
. Você deve obter um erro “Missing Model”
porque ainda não temos um model de Contact definido.
Se o seu aplicativo incluir o roteamento padrão do CakePHP, você será capaz de acessar seus controllers de plugins usando URLs como:
// Acesse a rota de índice de um controller de plugin.
/contact-manager/contacts
// Qualquer ação em um controller de plug-in.
/contact-manager/contacts/view/1
Se o seu aplicativo definir prefixos de roteamento, o roteamento padrão do CakePHP também conecte rotas que usam o seguinte padrão:
/:prefix/:plugin/:controller
/:prefix/:plugin/:controller/:action
Consulte a seção em Configuração do Plugin para obter informações sobre como carregar qrquivos de rota específicos do plugin.
Para os plugins que você não criou com bake, você também precisará editar o composer.json para adicionar seu plugin às classes de autoload, isso pode ser feito conforme a documentação Autoloading Plugin Classes.
Os models para o plugin são armazenados em plugins/ContactManager/src/Model. Nós já definimos um ContactsController para este plugin, então vamos criar a tabela e a entidade para esse controlador:
// 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
{
}
Se você precisa fazer referência a um modelo no seu plugin ao criar associações ou definindo classes de entidade, você precisa incluir o nome do plugin com a class name, separado com um ponto. Por exemplo:
// 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');
}
}
Se você preferir que as chaves da array para a associação não tenham o prefixo plugin sobre eles, use a sintaxe alternativa:
// 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',
]);
}
}
Você pode usar TableRegistry
para carregar suas tabelas de plugins usando o familiar
sintaxe plugin:
use Cake\ORM\TableRegistry;
// Prior to 3.6 use TableRegistry::get('ContactManager.Contacts')
$contacts = TableRegistry::getTableLocator()->get('ContactManager.Contacts');
Alternativamente, a partir de um contexto de controller, você pode usar:
$this->loadModel('ContactsMangager.Contacts');
As views se comportam exatamente como ocorrem em aplicações normais. Basta colocá-los na
pasta plugins/[PluginName]/src/Template/
. Para nós
o plugin ContactManager, precisamos de uma view para o nosso ContactsController::index()
action, então incluamos isso também:
// plugins/ContactManager/src/Template/Contacts/index.ctp:
<h1>Contacts</h1>
<p>Following is a sortable list of your contacts</p>
<!-- A sortable list of contacts would go here....-->
Os plugins podem fornecer seus próprios layouts. Para adicionar layouts em plugins, coloque seus arquivos de template dentro
plugins/[PluginName]/src/Template/Layout
. Para usar um layout de plug-in em seu controller
você pode fazer o seguinte:
public $layout = 'ContactManager.admin';
Se o prefixo do plugin for omitido, o arquivo layout/view será localizado normalmente.
Nota
Para obter informações sobre como usar elementos de um plugin, procure Elements
Você pode substituir todas as view do plugin do seu aplicativo usando caminhos especiais. E se você tem um plugin chamado ‘ContactManager’, você pode substituir os arquivos do template do plugin com lógica de visualização específica da aplicação criando arquivos usando o seguinte template src/Template/Plugin/[Plugin]/[Controller]/[view].ctp. Para o controller Contacts você pode fazer o seguinte arquivo:
src/Template/Plugin/ContactManager/Contacts/index.ctp
Criar este arquivo permitiria que você substituir plugins/ContactManager/src/Template/Contacts/index.ctp.
Se o seu plugin estiver em uma dependência no composer (ou seja, ‘TheVendor/ThePlugin’), o caminho para da view ‘index’ do controller personalizado será:
src/Template/Plugin/TheVendor/ThePlugin/Custom/index.ctp
Criar este arquivo permitiria que você substituir vendor/thevendor/theplugin/src/Template/Custom/index.ctp.
Se o plugin implementar um prefixo de roteamento, você deve incluir o prefixo de roteamento em seu O template para substitui.
Se o plugin ‘Contact Manager’ implementou um prefixo ‘admin’, o caminho principal seria:
src/Template/Plugin/ContactManager/Admin/ContactManager/index.ctp
Os recursos da web de um plugin (mas não arquivos PHP) podem ser atendidos através do plugin no
diretório webroot
, assim como os assets da aplicação principal:
/plugins/ContactManager/webroot/
css/
js/
img/
flash/
pdf/
Você pode colocar qualquer tipo de arquivo em qualquer no diretório webroot.
Aviso
Manipulação de assets estáticos (como imagens, JavaScript e arquivos CSS) Através do Dispatcher é muito ineficiente. Ver Aprimorar a performance de sua aplicação Para maiores informações.
Você pode usar o sintaxe plugin ao vincular aos recursos do plugin
usando o View\Helper\HtmlHelper
script, image ou css
methods:
// Gera a URL /contact_manager/css/styles.css
echo $this->Html->css('ContactManager.styles');
// Gera a URL /contact_manager/js/widget.js
echo $this->Html->script('ContactManager.widget');
// Gera a URL /contact_manager/img/logo.jpg
echo $this->Html->image('ContactManager.logo');
Os recursos do plugin são servidos usando o filtro AssetFilter
dispatcher por padrão.
Isso só é recomendado para o desenvolvimento. Na produção, você deve
symlink do plugin symlink para melhorar o desempenho.
Se você não estiver usando os helpers, você pode /plugin_name/ para o início da URL para um recurso dentro desse plugin para atendê-lo. Ligando para ‘/contact_manager/js/some_file.js’ serviria o asset plugins/ContactManager/webroot/js/some_file.js.
Um plugin pode ter Components, Helpers e Behaviors, como uma aplicação CakePHP normal. Você pode até criar plugins que consistem apenas em Componentes, Helpers ou Behaviors que podem ser uma ótima maneira de construir componentes reutilizáveis que pode ser lançado em qualquer projeto.
Construir esses componentes é exatamente o mesmo que construí-lo dentro de uma aplicacao normal, sem convenção de nome especial.
Referir-se ao seu componente de dentro ou fora do seu plugin requer apenas que você prefixa o nome do plugin antes do nome do componente. Por exemplo:
// Component definido no 'ContactManager' plugin
namespace ContactManager\Controller\Component;
use Cake\Controller\Component;
class ExampleComponent extends Component
{
}
// Dentro de seus controllers
public function initialize()
{
parent::initialize();
$this->loadComponent('ContactManager.Example');
}
A mesma técnica se aplica aos Helpers e Behaviors.
Este exemplo criou um bom começo para um plugin, mas há muito mais que você pode fazer. Como regra geral, qualquer coisa que você possa fazer com o seu aplicativo que você pode fazer dentro de um plugin também.
Vá em frente - inclua algumas bibliotecas de terceiros em ‘vendor’, adicione algumas novas shells para o cake console e não se esqueça de criar os testes então seus usuários de plugins podem testar automaticamente a funcionalidade do seu plugin!
Em nosso exemplo do ContactManager, podemos criar as actions add/remove/edit/delete no ContactsController, implementar a validação no model e implementar a funcionalidade que se poderia esperar ao gerenciar seus contatos. Depende de você decidir o que implementar no seu Plugins. Apenas não esqueça de compartilhar seu código com a comunidade, então que todos possam se beneficiar de seus componentes incríveis e reutilizáveis!
Certifique-se de adicionar o seu plug-in para Plugins.cakephp.org. Desta forma, outras pessoas podem Use-o como dependência do compositor. Você também pode propor seu plugin para o Lista de awesome-cakephp list.
Escolha um nome semanticamente significativo para o nome do pacote. Isso deve ser ideal prefixado com a dependência, neste caso “cakephp” como o framework. O nome do vendor geralmente será seu nome de usuário do GitHub. Não não use o espaço de nome CakePHP (cakephp), pois este é reservado ao CakePHP Plugins de propriedade.
A convenção é usar letras minúsculas e traços como separador.
Então, se você criou um plugin “Logging” com sua conta do GitHub “FooBar”, um bom nome seria foo-bar/cakephp-logging.
E o plugin “Localized” do CakePHP pode ser encontrado em cakephp/localized
respectivamente.