Controladores

Un controlador es una clase PHP que hereda de Ubiquity\controllers\Controller, proporcionando un punto de entrada en la aplicación.
Los controladores y sus métodos definen URLs accesibles.

Creación de controladores

La forma más sencilla de crear un controlador es hacerlo desde las devtools.

Desde el símbolo del sistema, vaya a la carpeta del proyecto.
Para crear el controlador Products, utilice el comando:

Ubiquity controller Products

El controlador Products.php se crea en la carpeta app/controllers del proyecto.

app/controllers/Products.php
1namespace controllers;
2/**
3 * Controller Products
4 */
5class Products extends ControllerBase{
6
7public function index(){}
8
9}

Ahora es posible acceder a URLs (por defecto se solicita el método index):

example.com/Products
example.com/Products/index

Nota

Un controlador puede crearse manualmente. En este caso, debe respetar las siguientes reglas:

  • La clase debe estar en la carpeta app/controllers.

  • El nombre de la clase debe coincidir con el nombre del archivo php

  • La clase debe heredar de ControllerBase y estar definida en el espacio de nombres controllers.

  • y debe anular el método abstracto index.

Métodos

public

El segundo segmento del URI determina a qué método público del controlador se llama.
El método «index» siempre se carga por defecto si el segundo segmento del URI está vacío.

app/controllers/First.php
1namespace controllers;
2class First extends ControllerBase{
3
4   public function hello(){
5      echo "Hello world!";
6   }
7
8}

El método hello del controlador First pone a disposición la siguiente URL:

example.com/First/hello

argumentos del método

los argumentos de un método deben pasarse en la url, excepto si son opcionales.

app/controllers/First.php
namespace controllers;
class First extends ControllerBase{

public function says($what,$who='world') {
   echo $what.' '.$who;
}

}

El método hello del controlador First pone a disposición la siguiente URL:

example.com/First/says/hello (says hello world)
example.com/First/says/Hi/everyone (says Hi everyone)

private

Los métodos privados o protegidos no son accesibles desde la URL.

Controlador por defecto

El controlador por defecto se puede establecer con el Router, en el archivo services.php.

app/config/services.php
Router::start();
Router::addRoute("_default", "controllers\First");

En este caso, el acceso a la URL example.com/ carga el controlador First y llama al método index por defecto.

carga de vistas

cargando

Las vistas se almacenan en la carpeta app/views. Se cargan desde los métodos del controlador.
Por defecto, es posible crear vistas en php, o con twig.
Twig es el motor de plantillas por defecto para archivos html.

carga de vistas php

Si no se especifica la extensión del archivo, el método loadView carga un archivo php.

app/controllers/First.php
namespace controllers;
class First extends ControllerBase{
   public function displayPHP(){
      //loads the view app/views/index.php
      $this->loadView('index');
   }
}

carga de la vista twig

Si la extensión del archivo es html, el método loadView carga un archivo html twig.

app/controllers/First.php
namespace controllers;
class First extends ControllerBase{
   public function displayTwig(){
      //loads the view app/views/index.html
      $this->loadView("index.html");
   }
}

Carga de la vista por defecto

Si se utiliza el método de nomenclatura de vistas por defecto :
La vista por defecto asociada a una acción en un controlador se encuentra en la carpeta views/nombre-controlador/nombre-acción:

views
           Users
          info.html
app/controllers/Users.php
1 namespace controllers;
2
3 class Users extends BaseController{
4   ...
5   public function info(){
6      $this->loadDefaultView();
7   }
8}

ver parámetros

Una de las misiones del controlador es pasar variables a la vista.
Esto se puede hacer en la carga de la vista, con un array asociativo:

app/controllers/First.php
class First extends ControllerBase{
   public function displayTwigWithVar($name){
      $message="hello";
      //loads the view app/views/index.html
      $this->loadView('index.html', ['recipient'=>$name, 'message'=>$message]);
   }
}

Las claves del array asociativo crean variables del mismo nombre en la vista.
Uso de estas variables en Twig:

app/views/index.html
<h1>{{message}} {{recipient}}</h1>

También se pueden pasar variables antes de cargar la vista:

//passing one variable
$this->view->setVar('title','Message');
//passing an array of 2 variables
$this->view->setVars(['message'=>$message,'recipient'=>$name]);
//loading the view that now contains 3 variables
$this->loadView('First/index.html');

ver resultado como cadena

Es posible cargar una vista, y devolver el resultado en una cadena, asignando true al 3er parámetro del método loadview :

$viewResult=$this->loadView("First/index.html",[],true);
echo $viewResult;

carga de vistas múltiples

Un controlador puede cargar varias vistas:

app/controllers/Products.php
namespace controllers;
class Products extends ControllerBase{
   public function all(){
      $this->loadView('Main/header.html', ['title'=>'Products']);
      $this->loadView('Products/index.html',['products'=>$this->products]);
      $this->loadView('Main/footer.html');
   }
}

Importante

Una vista suele ser parcial. Por lo tanto, es importante no integrar sistemáticamente las etiquetas html y body definiendo una página html completa.

organización de vistas

Es aconsejable organizar las vistas en carpetas. El método más recomendado es crear una carpeta por controlador, y almacenar allí las vistas asociadas.
Para cargar la vista index.html, almacenada en app/views/First:

$this->loadView("First/index.html");

initialize y finalize

El método initialize se llama automáticamente antes de cada acción solicitada, el método finalize después de cada acción.

Ejemplo de uso de los métodos initialize y finalize con la clase base creada automáticamente con un nuevo proyecto:

app/controllers/ControllerBase.php
namespace controllers;

use Ubiquity\controllers\Controller;
use Ubiquity\utils\http\URequest;

/**
 * ControllerBase.
 */
abstract class ControllerBase extends Controller{
   protected $headerView = "@activeTheme/main/vHeader.html";
   protected $footerView = "@activeTheme/main/vFooter.html";

   public function initialize() {
      if (! URequest::isAjax ()) {
         $this->loadView ( $this->headerView );
      }
   }

   public function finalize() {
      if (! URequest::isAjax ()) {
         $this->loadView ( $this->footerView );
      }
   }
}

Control de acceso

El control de acceso a un controlador puede realizarse manualmente, utilizando los métodos isValid y onInvalidControl.

El método isValid debe devolver un booleano que determine si es posible acceder a action pasada como parámetro:

En el siguiente ejemplo, el acceso a las acciones del controlador IndexController sólo es posible si existe una variable de sesión activeUser:

app/controllers/IndexController.php
class IndexController extends ControllerBase{
...
   public function isValid($action){
      return USession::exists('activeUser');
   }
}

Si la variable activeUser no existe, se devuelve un error unauthorized 401.

El método onInvalidControl permite personalizar el acceso no autorizado:

app/controllers/IndexController.php
class IndexController extends ControllerBase{
   ...
   public function isValid($action){
      return USession::exists('activeUser');
   }

   public function onInvalidControl(){
      $this->initialize();
      $this->loadView('unauthorized.html');
      $this->finalize();
   }
}
app/views/unauthorized.html
<div class="ui container">
   <div class="ui brown icon message">
      <i class="ui ban icon"></i>
      <div class="content">
         <div class="header">
            Error 401
         </div>
         <p>You are not authorized to access to <b>{{app.getController() ~ "::" ~ app.getAction()}}</b>.</p>
      </div>
   </div>
</div>

También es posible generar automáticamente el control de acceso a partir de AuthControllers

Reenvío

Una redirección no es una simple llamada a una acción de un controlador.
La redirección implica los métodos initialize y finalize, así como el control de acceso.

El método forward puede invocarse sin utilizar los métodos initialize y finalize:

Es posible redirigir a una ruta por su nombre:

Inyección de dependencia

Ver Dependency injection

namespaces

El namespace del controlador se define por defecto en controllers en el archivo app/config/config.php.

Superclase

La herencia se puede utilizar para factorizar el comportamiento del controlador.
La clase BaseController creada con un nuevo proyecto está presente para este propósito.

Clases base específicas del controlador

Clase de controlador

role

Controller

Clase base para todos los controladores

SimpleViewController

Clase base asociada a un motor de plantillas php (para usar con microservicios)

SimpleViewAsyncController

Clase base asociada a un motor de plantillas php para servidores asíncronos