Los componentes son paquetes de logica que es compartida entre controladores. CakePHP incluye un fantastico set de componentes que puedes usar para ayudarte en tareas comunes. También puedes crear tus propios componentes. Si te encontrás queriendo copiar y pegar cosas entre de un controlador a otro, deberias considerar crear tu propio componente para obtener esa funcionalidad. Crear componentes ayuda a mantener el codigo de tus controladores limpio y facilita la reutilización de código entre proyectos.
Cada uno de los componentes principales esta detallado en su propio capítulo. Ver Components. Esta sección describe como configurar y usar los componentes y como crear tus propios componentes.
Mucho de los componentes principales requieren configuración. Algunos ejemplos de
componentes que requieren configuración son
Authentication y Cookie.
La configuración para estos componentes, y para los componentes en general, es realizada
usualmente en el array $components
o en el método beforeFilter()
de tú
controlador:
class PostsController extends AppController {
public $components = array(
'Auth' => array(
'authorize' => array('controller'),
'loginAction' => array(
'controller' => 'users',
'action' => 'login'
)
),
'Cookie' => array('name' => 'CookieMonster')
);
El fragmento de código anterior sería un ejemplo de configuración de un componente
con el array $components
.
Todos los componentes principales permiten que su configuración sea
seteada de ésta forma. A su vez, es posible configurar el componente
a través del método beforeFilter()
de tú controlador.
Esto es útil cuando necesitas asignar los resultados de una función a la propiedad de
un componente. El código anterior también podría ser expresado como:
public function beforeFilter() {
$this->Auth->authorize = array('controller');
$this->Auth->loginAction = array(
'controller' => 'users',
'action' => 'login'
);
$this->Cookie->name = 'CookieMonster';
}
Sin embargo, es posible que un componente requiera que cierta configuración
antes que el método beforeFilter()
del controlador sea ejecutado.
Con éste fin, algunos componentes permiten que las opciones de configuración
sean seteadas en el array $components
:
public $components = array(
'DebugKit.Toolbar' => array('panels' => array('history', 'session'))
);
Consulte la documentación relevante para determinar que opción de configuración provee cada componente.
Una opcion común es el uso de className
, la cual le permite ponerle un alias a un
componente. Esta caracteristica es útil cuando se quiere reemplazar $this->Auth
o la referencia de otro componente común con una implementación propia:
// app/Controller/PostsController.php
class PostsController extends AppController {
public $components = array(
'Auth' => array(
'className' => 'MyAuth'
)
);
}
// app/Controller/Component/MyAuthComponent.php
App::uses('AuthComponent', 'Controller/Component');
class MyAuthComponent extends AuthComponent {
// Add your code to override the core AuthComponent
}
El código anterior aplicaría un alias MyAuthComponent
a $this->Auth
en tús
controladores.
Nota
Usar un alias en un componente reemplaza esa instancia en cualquier lugar que ese componente sea usado, incluyendo dentro de otros componentes.
Una vez que has incluido algunos componentes en tús controladores, usarlos
es bastante sensillo. Cada componente que use es expuesto como una propiedad
en tú controlador. Si ha cargado SessionComponent
y
CookieComponent
en su controlador, accederia a ellos de esta forma:
class PostsController extends AppController {
public $components = array('Session', 'Cookie');
public function delete() {
if ($this->Post->delete($this->request->data('Post.id'))) {
$this->Session->setFlash('Post deleted.');
return $this->redirect(array('action' => 'index'));
}
}
Nota
Ya que tanto modelos como componentes son agregados a los controladores como propiedades, comparten el mismo “namespace”. Asegurese de no darles el mismo nombre a un modelo y componente.
Tal vez no necesite todos los componentes disponibles en cada acción de su controlador. En situaciones como esta puede cargar un componente en tiempo de ejecucion usando Component Collection. Desde dentro de un método de un controlador se puede:
$this->OneTimer = $this->Components->load('OneTimer');
$this->OneTimer->getTime();
Nota
Tenga en cuenta que cargar un componente en tiempo de ejecución no llamara el método initialize de el componente.
Los componentes también ofrecen varios callbacks que permiten aumentar el ciclo del request. Vea API Componentes para más información sobre los callbacks que ofrecen los componentes.
Suponga que nuestra aplicación online necesita llevar a cabo una operación matemática compleja en diferentes partes de la aplicación. En este caso, crearíamos un componente que albergue esta lógica compartida para usar en diferentes controladores.
El primer paso es crear un nuevo archivo y clase de componente.
Cree el archivo en app/Controller/Component/MathComponent.php
. La estructura
básica para un componente es:
App::uses('Component', 'Controller');
class MathComponent extends Component {
public function doComplexOperation($amount1, $amount2) {
return $amount1 + $amount2;
}
}
Nota
Todos los componentes deben extender Component
. Si no lo hacen
se disparará una excepción.
Una vez que nuestro componente está terminado, podemos usarlo en un
controlador agregando el nombre del componente (sin la parte de «Component») en
el array $components
. El controlador recibirá automáticamente un nuevo
atributo llamado como este componente a través del cual podemos acceder a una
instancia del componente:
/* Hacer disponible el nuevo componente $this->Math,
y el standard $this->Session */
public $components = array('Math', 'Session');
Los componentes declarados en AppController
serám combinados con aquellos
en otros controladores. Por lo que no hay necesidad de re-declarar un componente
mas de una vez.
Al incluír componentes en un controlador también podemos declarar un grupo de parametros que serán pasados al constructor del componente. Estos parametros pueden ser manejados por el componente:
public $components = array(
'Math' => array(
'precision' => 2,
'randomGenerator' => 'srand'
),
'Session', 'Auth'
);
El código anterior pasará un array que contiene precision y randomGenerator a
MathComponent::__construct()
como el segundo parámetro. Por convención
si los keys de un array son iguales a las propiedades públicas de un componente,
las propiedades seran actualizadas con los valores de esas keys.
A veces, algunos de tus componentes pueden necesitar usar otros componentes. En estos casos se puede incluir otros componentes en tús componentes de la misma forma que se incluyen en un controlador:
// app/Controller/Component/CustomComponent.php
App::uses('Component', 'Controller');
class CustomComponent extends Component {
// los otros componentes que tu componente usa
public $components = array('Existing');
public function initialize(Controller $controller) {
$this->Existing->foo();
}
public function bar() {
// ...
}
}
// app/Controller/Component/ExistingComponent.php
App::uses('Component', 'Controller');
class ExistingComponent extends Component {
public function foo() {
// ...
}
}
Nota
En contraste con los componentes incluidos en un controlador ningún callback va a ser disparado en el componente de un componente.
La clase base Component ofrece varios métodos para cargar otros componentes
a través de ComponentCollection
así como para tratar con
configuraciones comunes. También provee prototipos para todos los callbacks de los
componentes.
Constructor para la clase base component. Todos los $settings
que
también tengan propiedades públicas serán actualizados para coincidir con
$settings
.
Es llamado antes que el método beforeFilter de un controlador.
Es llamado despues de el método beforeFilter pero antes que el controlador ejecute la actual acción.
Es llamada luego que el controlador ejecute la acción de la vista solicitada, pero antes que el controlador renderice la vista.
Es llamado antes de que el output sea enviado al navegador.
Es llamado cuando el método de redireccion del controlador es llamado, pero antes de acción alguna. Si este método devuelve false el controlador no continuará hacia el redireccionamiento.