danielspk / tornado
Reducido núcleo de trabajo para PHP
Requires
- php: >=5.4.0
Requires (Dev)
This package is auto-updated.
Last update: 2024-12-10 03:20:57 UTC
README
TORNADO es un reducido marco de trabajo para PHP que permite implementar el patrón HMVC y/o servicios RESTfull
Puede obtener más información en su web http://tornado-php.com
Filosofia:
TORNADO no intenta ser un framework PHP full-stack. Contrariamente intenta ser
un núcleo de trabajo muy reducido para implementar patrones de arquitectura HMVC
y/o servicios REST, con la menor parametrización y utilización de código
posible, apoyado en un core que organice su proyecto junto a un sistema de
configuración y gestión de errores simple.
TORNADO no incluye librerías de soporte para tareas comunes como acceso a base de datos, gestión de plantillas, envío de mais, etc. Utilice Composer para incluir paquetes de terceros de acuerdo a las necesidades particulares del proyecto a desarrollar.
Inspiración:
TORNADO se inspiro en varios microframeworks PHP, entre ellos cabe mencionar:
- Toro - http://toroweb.org/
- Flight - http://flightphp.com/
- Shield - https://github.com/enygma/shieldframework
- Slim - http://www.slimframework.com/
- AltoRouter - http://altorouter.com/
Metas:
TORNADO se desarrollo tratando de respetar las siguiente metas:
- ser rápido
- fácil de entender (tanto su API como su construcción interna)
- tener la menor cantidad de métodos posibles dentro de su API
- permitir el uso de ganchos para extender el mismo
- incluir librerías/paquetes de terceros con suma facilidad
- tener la menor cantidad de líneas de código posible
- ser un core de trabajo (NUNCA un framework)
Características:
- Enrutamientos para utilizar módulos HMVC y/o servicios REST (apoyado en URL amigables)
- Configuración general de la aplicación
- Ganchos para extender las características del core
- Captura de errores y excepciones
- Inyección de dependencias
Codificación:
TORNADO apoya la iniciativa del PHP Framework Interop Group e implementa los estándares PSR-2 y PSR-4.
Puede obtener más información en http://www.php-fig.org/
Instalación:
La instalación recomendada requiere el uso de Composer.
-
Instale composer ( puede obtener ayuda en https://getcomposer.org/download/ )
-
Cree un archivo composer.json con los paquetes a instalar
{
"require": {
"danielspk/tornado" : "2.*"
}
}
- Inicie la consola de comando y ejecute el siguiente comando:
composer install
Manual de uso:
La versión actual difiere totalmente de la versión inicial 1.0.0
Si va a actualizar su aplicación lea en detalle el archivo de cambios CHANGELOG.md
Uso básico:
Ejemplo de uso básico (con dos tipos de enrutamientos)
<?php // incluir el autoload require 'vendor/autoload.php'; // obtener una instancia del core $app = \DMS\Tornado\Tornado::getInstance(); // enrutamiento a módulo desde raíz $app->route('/', 'demo|demo|index'); // enrutamiento a función anónima $app->route(array( '/saludar/:string' => function($pNombre = null){ echo 'Hola ' . $pNombre; } )); // ejecutar la aplicación $app->run();
API:
Obtener Instancia del core:
$app = \DMS\Tornado\Tornado::getInstance();
Ejecutar el core:
// con una instancia del core en una variable $app = \DMS\Tornado\Tornado::getInstance(); $app->run(); // sin ninguna instancia anterior del core \DMS\Tornado\Tornado::getInstance()->run();
Setear configuraciones:
$app = \DMS\Tornado\Tornado::getInstance(); // configuración simple $app->config('nombre', 'valor del nombre'); $app->config('nombres', array('nombre1'=>'valor1', 'nombre2'=>'valor2')); // configuración múltiple $app->config([ 'clave1' => 'valor uno', 'clave2' => 'valor dos' ]);
Leer configuraciones:
$app = \DMS\Tornado\Tornado::getInstance(); // configuración simple echo $app->config('nombre'); // configuración array $nombres = $app->config('nombres'); echo $nombres[0]['nombre1']; echo $nombres[1]['nombre2'];
Variables de configuración propias de Tornado:
Tornado permite configurar el ambiente de trabajo de la aplicación. De esta forma se puede cambiar el comportamiento interno del core:
// configurar la aplicación para un ambiente de desarrollo // - errores visibles // - parse de anotaciones en módulos HMVC para generar enrutamientos automáticos $app->config('tornado_environment_development', true);
Otras configuraciones:
// - indica si se van a utilizar módulos hmvc $app->config('tornado_hmvc_use', true); // - ruta donde se alojarán los módulos hmvc // (relativa a donde se inicia Tornado) $app->config('tornado_hmvc_module_path', true); // - ruta donde se serializaran las rutas de los módulos hmvc // (relativa a donde se inicia Tornado) $app->config('tornado_hmvc_serialize_path', true);
Uso de Hooks:
Existen 6 tipos de hooks:
- init: antes de parsear la url en busca de una ruta coincidente
- before: antes de ejecutar la ruta coincidente
- after: despues de ejecutar la ruta coincidente
- end: al finalizar la ejecución de la petición
- 404: al no encontrarse una ruta coincidente con la url
- error: al atraparse un error o excepción en aplicación
$app = \DMS\Tornado\Tornado::getInstance(); // utilizando una clase / método / parámetros $app->hook('error', array('ErrorUser', 'display', array())); // utilizando una función anónima $app->hook('404', function(){ echo '404'; });
También es posible crear ganchos personalizados. Ejemplo usando una clase de usuario:
class Saludador { public function persona($nombre, $apellido) { echo 'Hola ' . $nombre . ', ' . $apellido; } } $app->hook('saludar', array('Saludador', 'persona', array('Tornado', 'PHP')));
La forma de ejecutar un gancho por código es la siguiente:
$app = \DMS\Tornado\Tornado::getInstance(); $app->hook('fueraDeLinea');
Pueden crearse n cantidad de hooks con un mismo nombre. Los mismos se ejecutarán secuencialmente en el orden en que fueron definidos. Puede, opcionalmente, alterar este orden indicando explicitamente el orden deseado:
$app = \DMS\Tornado\Tornado::getInstance(); $app->hook('before', function(){ echo 'Declarado primero - ejecutado despues'; }, 1); $app->hook('before', function(){ echo 'Declarado despues - ejecutado primero'; }, 0);
Si declara más de un hook con el mismo nombre puede impedir que se ejecuten los hooks subsiguientes haciendo que el hook devuelva false en su ejecución.
A excepción de los hook init puede consultar que ruta se va o se esta ejecutandose de la siguiente forma:
$app = \DMS\Tornado\Tornado::getInstance(); $app->hook('before', function() use ($app){ $ruta = $app->getRouteMatch() });
Esto devolverá un array con la siguiente información:
- Método de la petición (GET, POST, etc)
- Ruta
- Callback
- Parámetros
Hooks y flujo de ejecución:
La secuencia de ejecución del core es la siguiente:
- se ejecutan los hooks init
- se parsea la url en busca de la ruta coincidente
-
- si no hay coincidencias se ejecuta:
-
-
- hooks 404
-
-
-
- hooks end
-
-
-
- se finaliza la ejecución
-
- se ejecutan los hooks before
-
- si alguno devuelve false se ejecuta:
-
-
- hooks end
-
-
-
- se finaliza la ejecución
-
- se ejecuta la ruta coincidente
- se ejecutan los hooks after
- se ejecutan los hooks end
Definir Enrutamientos:
Los enrutamientos pueden ser:
- (vacio) - cualquier tipo de petición
- GET - RESTfull por método GET
- POST - RESTfull por método POST
- PUT - RESTfull por método PUT
- DELETE - RESTfull por método DELETE
En caso de que el servidor no soporte los métodos PUT y DELETE se pueden simular los mismos enviando una petición POST con una variable "REST_METHOD" cuyo valor sea PUT o DELETE
Existen cuatro tipos de parámetros para enrutar una URL:
- :string - sólo acepta letras
- :number - sólo acepta números
- :alpha - acepta números y letras
- :* - acepta cualquier cantidad y tipo de parámetros (sólo puede incluirse uno solo y al final)
En caso de incluir parámetros opcionales la sintaxis es la siguiente:
- [/:string]
- [/:number]
- [/:alpha]
$app = \DMS\Tornado\Tornado::getInstance(); // utilizando un módulo y cualquier tipo de petición $app->route('/', 'demo|demo|index'); // utilizando una función anónima y cualquier tipo de petición $app->route('/saludar/:alpha', function($pNombre = null) { echo 'Hola ' . $pNombre; }); // utilizando parámetros opcionales y cualquier tipo de petición $app->route('/mostrar[/:alpha][/:number]', function ($pNombre = null, $pEdad = null) { echo 'Hola ' . $pNombre . ', ' . $pEdad; }); // utilizando un comodín (n cantidad de parámetros) y cualquier tipo de petición $app->route('/felicitador/:*', function () { $params = func_get_args(); echo 'Felicitaciones ' . (isset($params[0]) ? $params[0] : ''); }); // utilizando un módulo y petición POST $app->route('POST /', 'demo|demo|guardar'); // utilizando un módulo y petición GET o POST $app->route('GET|POST /', 'demo|demo|listar');
También es posible definir parámetros con nombre. En dicho caso puede omitirse el uso de parámetros de entrada en las funciones anónimas o métodos de los módulos HMVC. Ejemplo:
$app->route('/bienvenida/@nombre:alpha/tornado/@edad:number', function () use ($app) { echo 'Hola ' . $app->param('nombre') . ', Edad: ' . $app->param('edad'); });
Puede agregar tipos de parámetros auxiliares de la siguiente forma:
$app = \DMS\Tornado\Tornado::getInstance(); $app->addTypeParam(':custom', '([123]+)'); $app->route('/personalizado/:custom', function ($pCustom = null) { echo 'Parametro personalizado ' . $pCustom; });
Nota: El único enrutamiento obligatorio es el del nodo raíz ya que indica cuál será el callback a ejecutar por defecto al ingresar a la aplicación.
Delegaciones:
Es posible delegar la acción de un módulo/ruta hacia otro sin necesidad de realizar una redirección por http. Esta delegación invoca al otro módulo/ruta dentro del mismo request original. Ejemplo:
// a módulo sin parámetros $app->forwardModule('modulo|clase|metodo'); // a módulo con parámetros $app->forwardModule('modulo|clase|metodo', array('param1', 'param2')); // a url (parámetros incluidos en la url) $app->forwardUrl('/otra/ruta/1234');
Si se encuentra instalado FPM en el Servidor puede devolver el resultado al cliente y continuar con la ejecución de la petición actual en segundo plano de la siguiente forma:
$app->finishRequest();
Anotaciones:
Algunas acciones pueden ser establecidas mediante anotaciones DocBlocks.
Enrutamientos:
En los controladores de los módulos HMVC puede utilizar el tag @T_ROUTE para setear un enrutamiento. Esto generará un archivo de configuración denominado "route_serialize.php".
Siempre que la aplicación se encuentre en modo de desarrollo (variable de configuración "tornado_environment_development" en true) se recorrerán los métodos de los controladores para actualizar este archivo de configuración.
Ejemplo:
class Demo extends \DMS\Tornado\Controller { /** * Ejemplo de enrutamientos mediante anotaciones * @T_ROUTE /demo/anotacion * @T_ROUTE GET|POST /demo/otra/anotacion */ public function index() { echo 'Hola Mundo Tornado'; } }
Vistas
Puede incluir archivos de vistas/templates dentro de una ruta manejada por clousures de la siguiente forma:
$app = \DMS\Tornado\Tornado::getInstance(); $app->render('ruta/archivo.php'); // vista sin parámetros $app->render('ruta/archivo.php', array('nombre'=>'valor')); // vista con parámetros
Los parámetros pasados a la vista/template se manejan de la misma forma que los parámetros pasados a una vista de un módulo HMVC.
Gestión de errores y excepciones:
El manejo de errores y excepciones viene habilitado por defecto. Puede alterar su comportamiento de la siguiente forma:
$app = \DMS\Tornado\Tornado::getInstance(); $app->error(true); // habilita el manejador $app->error(false); // deshabilita el manejador
Puede acceder a la última excepción lanzada de la siguiente forma:
$app = \DMS\Tornado\Tornado::getInstance(); $exc = $app->error();
Inyección de Dependencias:
Es posible extender el core mediante la inyección de nuevas clases. La forma de registrar una nueva dependencia es:
$app->register('fecha', function($fecha = '2014-12-31'){ return new \DateTime($fecha); });
Este registro creará un dependencia para la clase 'DateTime' denominada 'fecha'. Podrá hacer uso de la misma de la siguiente forma:
$app = \DMS\Tornado\Tornado::getInstance(); echo $app->container('fecha')->format('d/m/Y') . '<br />';
Por defecto todas las dependencias inyectadas crean una nueva instancia de la clase. Puede registrar el servicio como Singleton seteando el tercer parámetro opcional en true:
$app->register('fecha', function(){ return new \DateTime('2014-12-31'); }, true);
Si las dependencias requieren parámetros en sus constructores puede definir los mismos de la siguiente forma:
$app->register('fecha.config', '2014-12-31'); $app->register('fecha', function(\DMS\Tornado\Service $c){ return new \DateTime($c->get('fecha.config')); });
Organización de proyecto:
Existe un proyecto que dispone de un esqueleto para una aplicación base. Puede descargar el mismo desde https://github.com/danielspk/TornadoSkeletonApplication
Módulos:
Tornado PHP permite utilizar módulos HMVC de forma conjunta con las funciones anónimas.
Si utiliza Composer, se recomienda registrar la ubicación de los módulos en el autoload. Ejemplo:
"autoload": {
"psr-4": {
"App\\Modules\\": "app/modules/"
}
},
Controladores:
Todos los controladores deben extender de \DMS\Tornado\Controller y deben definir un namespace que respete la especificación PSR-4. Ejemplo:
Asumiendo que los módulos HMVC se encuentran en App\Modules[Modulo HMVC]\Controller
namespace App\Modules\Demo\Controller; use \DMS\Tornado\Controller; class Demo extends Controller { public function index($param = null){ echo ' Hola ' . $param . '<br>'; } }
Los Controladores poseen una instancia de tornado PHP como propiedad propia. Puede acceder a la misma de la siguiente forma:
// permite acceder a una instancia de Tornado $app = $this->app;
Modelos:
Todos los controladores deben definir un namespace que respete la siguiente jerarquía: App\Modules[Modulo HMVC]\Model
namespace App\Modules\Demo\Model; class Demo { public function getDemos($param = null){ return true; } }
Vistas:
Dado que el controlador posee una instancia de Tornado es posible usar el método render() para invocar a una vista.
Resumen de Métodos:
DMS\Tornado\Tornado
DMS\Tornado\Service
DMS\Tornado\Controller
Licencia:
El proyecto se distribuye bajo la licencia MIT.
Tests unitarios:
Para ejecutar los test es necesario descargar PHPUnit. Sitúese en la carpeta raíz de Tornado y ejecute la siguiente instrucción por línea de comando:
phpunit.phar
Ante errores o sugerencias escriba a la dirección de email de contacto.