klein.php es un enrutador rápido y flexible para PHP 5.3+
php composer.phar require klein/klein
require 'vendor/autoload.php';
Hola Mundo - Ejemplo obligatorio de Hola Mundo
<?php
require_once __DIR__ . ' /vendor/autoload.php ' ;
$ klein = new Klein Klein ();
$ klein -> respond ( ' GET ' , ' /hello-world ' , function () {
return ' Hello World! ' ;
});
$ klein -> dispatch ();
Ejemplo 1 : responder a todas las solicitudes
$ klein -> respond ( function () {
return ' All the things ' ;
});
Ejemplo 2 : parámetros con nombre
$ klein -> respond ( ' /[:name] ' , function ( $ request ) {
return ' Hello ' . $ request -> name ;
});
Ejemplo 3 : tan RESTful
$ klein -> respond ( ' GET ' , ' /posts ' , $ callback );
$ klein -> respond ( ' POST ' , ' /posts ' , $ callback );
$ klein -> respond ( ' PUT ' , ' /posts/[i:id] ' , $ callback );
$ klein -> respond ( ' DELETE ' , ' /posts/[i:id] ' , $ callback );
$ klein -> respond ( ' OPTIONS ' , null , $ callback );
// To match multiple request methods:
$ klein -> respond ( array ( ' POST ' , ' GET ' ), $ route , $ callback );
// Or you might want to handle the requests in the same place
$ klein -> respond ( ' /posts/[create|edit:action]?/[i:id]? ' , function ( $ request , $ response ) {
switch ( $ request -> action ) {
//
}
});
Ejemplo 4 : envío de objetos/archivos
$ klein ->respond( function ( $ request , $ response , $ service ) {
$ service -> xml = function ( $ object ) {
// Custom xml output function
}
$ service -> csv = function ( $ object ) {
// Custom csv output function
}
});
$ klein -> respond ( ' /report.[xml|csv|json:format]? ' , function ( $ request , $ response , $ service ) {
// Get the format or fallback to JSON as the default
$ send = $ request -> param ( ' format ' , ' json ' );
$ response -> $ send ( $ report );
});
$ klein -> respond ( ' /report/latest ' , function ( $ request , $ response , $ service ) {
$ response -> file ( ' /tmp/cached_report.zip ' );
});
Ejemplo 5 : todos juntos
$ klein -> respond ( function ( $ request , $ response , $ service , $ app ) use ( $ klein ) {
// Handle exceptions => flash the message and redirect to the referrer
$ klein -> onError ( function ( $ klein , $ err_msg ) {
$ klein -> service ()-> flash ( $ err_msg );
$ klein -> service ()-> back ();
});
// The fourth parameter can be used to share scope and global objects
$ app -> db = new PDO (...);
// $app also can store lazy services, e.g. if you don't want to
// instantiate a database connection on every response
$ app -> register ( ' db ' , function () {
return new PDO (...);
});
});
$ klein -> respond ( ' POST ' , ' /users/[i:id]/edit ' , function ( $ request , $ response , $ service , $ app ) {
// Quickly validate input parameters
$ service -> validateParam ( ' username ' , ' Please enter a valid username ' )-> isLen ( 5 , 64 )-> isChars ( ' a-zA-Z0-9- ' );
$ service -> validateParam ( ' password ' )-> notNull ();
$ app -> db -> query (...); // etc.
// Add view properties and helper methods
$ service -> title = ' foo ' ;
$ service -> escape = function ( $ str ) {
return htmlentities ( $ str ); // Assign view helpers
};
$ service -> render ( ' myview.phtml ' );
});
// myview.phtml:
<title> <?php echo $ this -> escape ( $ this -> title ) ?> </title>
$ klein -> with ( ' /users ' , function () use ( $ klein ) {
$ klein -> respond ( ' GET ' , ' /? ' , function ( $ request , $ response ) {
// Show all users
});
$ klein -> respond ( ' GET ' , ' /[:id] ' , function ( $ request , $ response ) {
// Show a single user
});
});
foreach ( array ( ' projects ' , ' posts ' ) as $ controller ) {
// Include all routes defined in a file under a given namespace
$ klein -> with ( " / $ controller " , " controllers/ $ controller .php " );
}
Los archivos incluidos se ejecutan en el alcance de Klein ( $klein
), por lo que se puede acceder a todos los métodos/propiedades de Klein con $this
Archivo de ejemplo para: "controladores/proyectos.php"
// Routes to "/projects/?"
$ this -> respond ( ' GET ' , ' /? ' , function ( $ request , $ response ) {
// Show all projects
});
Los servicios se pueden almacenar de forma diferida , lo que significa que solo se crean instancias de ellos en el primer uso.
<?php
$ klein -> respond ( function ( $ request , $ response , $ service , $ app ) {
$ app -> register ( ' lazyDb ' , function () {
$ db = new stdClass ();
$ db -> name = ' foo ' ;
return $ db ;
});
});
//Later
$ klein -> respond ( ' GET ' , ' /posts ' , function ( $ request , $ response , $ service , $ app ) {
// $db is initialised on first request
// all subsequent calls will use the same instance
return $ app -> lazyDb -> name ;
});
Para agregar un validador personalizado use addValidator($method, $callback)
$ service -> addValidator ( ' hex ' , function ( $ str ) {
return preg_match ( ' /^[0-9a-f]++$/i ' , $ str );
});
Puede validar los parámetros usando is<$method>()
o not<$method>()
, por ejemplo
$ service -> validateParam ( ' key ' )-> isHex ();
O puede validar cualquier cadena usando el mismo flujo.
$ service -> validate ( $ username )-> isLen ( 4 , 16 );
Los métodos de validación se pueden encadenar y se puede especificar un mensaje de excepción personalizado si la validación falla.
$ service -> validateParam ( ' key ' , ' The key was invalid ' )-> isHex ()-> isLen ( 32 );
[ tipo_coincidencia : nombre_parámetro ]
Algunos ejemplos
* // Match all request URIs
[i] // Match an integer
[i:id] // Match an integer as 'id'
[a:action] // Match alphanumeric characters as 'action'
[h:key] // Match hexadecimal characters as 'key'
[:action] // Match anything up to the next / or end of the URI as 'action'
[create|edit:action] // Match either 'create' or 'edit' as 'action'
[*] // Catch all (lazy)
[*:trailing] // Catch all as 'trailing' (lazy)
[**:trailing] // Catch all (possessive - will match the rest of the URI)
.[:format]? // Match an optional parameter 'format' - a / or . before the block is also optional
Algunos ejemplos más complicados
/posts/[*:title][i:id] // Matches "/posts/this-is-a-title-123"
/output.[xml|json:format]? // Matches "/output", "output.xml", "output.json"
/[:controller]?/[:action]? // Matches the typical /controller/action format
Nota : se llaman todas las rutas que coinciden con el URI de solicitud; esto le permite incorporar lógica condicional compleja, como autenticación de usuario o diseños de visualización. por ejemplo, como ejemplo básico, el siguiente código envolverá otras rutas con un encabezado y pie de página
$ klein -> respond ( ' * ' , function ( $ request , $ response , $ service ) { $ service -> render ( ' header.phtml ' ); });
//other routes
$ klein -> respond ( ' * ' , function ( $ request , $ response , $ service ) { $ service -> render ( ' footer.phtml ' ); });
Las rutas coinciden automáticamente con el URI de solicitud completo. Si necesita hacer coincidir solo una parte del URI de solicitud o utilizar una expresión regular personalizada, utilice el operador @
. Si necesita negar una ruta, utilice !
operador
// Match all requests that end with '.json' or '.csv'
$ klein ->respond( ' @.(json|csv)$ ' , ...
// Match all requests that _don't_ start with /admin
$ klein ->respond( ' !@^/admin/ ' , ...
Puede enviar propiedades o ayudas a la vista asignándolas al objeto $service
, o usando el segundo argumento de $service->render()
$ service -> escape = function ( $ str ) {
return htmlentities ( $ str );
};
$ service -> render ( ' myview.phtml ' , array ( ' title ' => ' My View ' ));
// Or just: $service->title = 'My View';
mivista.phtml
< title > < ?php echo $this- > escape($this- > title) ? > </ title >
Las vistas se compilan y ejecutan en el alcance de $service
, por lo que se puede acceder a todos los métodos de servicio con $this
$ this -> render ( ' partial.html ' ) // Render partials
$ this -> sharedData ()-> get ( ' myvar ' ) // Access stored service variables
echo $ this -> query ( array ( ' page ' => 2 )) // Modify the current query string
A continuación se muestra una lista de los métodos públicos en las clases comunes que probablemente utilizará. Para obtener una fuente más formal de documentación de clases/métodos, consulte la documentación generada por PHPdoc.
$ request ->
id ( $ hash = true ) // Get a unique ID for the request
paramsGet() // Return the GET parameter collection
paramsPost() // Return the POST parameter collection
paramsNamed() // Return the named parameter collection
cookies() // Return the cookies collection
server() // Return the server collection
headers() // Return the headers collection
files() // Return the files collection
body() // Get the request body
params() // Return all parameters
params ( $ mask = null ) // Return all parameters that match the mask array - extract() friendly
param ( $ key , $ default = null ) // Get a request parameter (get, post, named)
isSecure() // Was the request sent via HTTPS?
ip() // Get the request IP
userAgent() // Get the request user agent
uri() // Get the request URI
pathname() // Get the request pathname
method() // Get the request method
method ( $ method ) // Check if the request method is $method, i.e. method('post') => true
query ( $ key , $ value = null ) // Get, add to, or modify the current query string
<param> // Get / Set (if assigned a value) a request parameter
$ response ->
protocolVersion ( $ protocol_version = null ) // Get the protocol version, or set it to the passed value
body ( $ body = null ) // Get the response body's content, or set it to the passed value
status() // Get the response's status object
headers() // Return the headers collection
cookies() // Return the cookies collection
code ( $ code = null ) // Return the HTTP response code, or set it to the passed value
prepend ( $ content ) // Prepend a string to the response body
append ( $ content ) // Append a string to the response body
isLocked() // Check if the response is locked
requireUnlocked() // Require that a response is unlocked
lock() // Lock the response from further modification
unlock() // Unlock the response
sendHeaders ( $ override = false ) // Send the HTTP response headers
sendCookies ( $ override = false ) // Send the HTTP response cookies
sendBody() // Send the response body's content
send() // Send the response and lock it
isSent() // Check if the response has been sent
chunk ( $ str = null ) // Enable response chunking (see the wiki)
header ( $ key , $ value = null ) // Set a response header
cookie ( $ key , $ value = null , $ expiry = null ) // Set a cookie
cookie ( $ key , null ) // Remove a cookie
noCache() // Tell the browser not to cache the response
redirect ( $ url , $ code = 302 ) // Redirect to the specified URL
dump ( $ obj ) // Dump an object
file ( $ path , $ filename = null ) // Send a file
json ( $ object , $ jsonp_prefix = null ) // Send an object as JSON or JSONP by providing padding prefix
$ service ->
sharedData() // Return the shared data collection
startSession() // Start a session and return its ID
flash( $ msg , $ type = ' info ' , $ params = array() // Set a flash message
flashes ( $ type = null ) // Retrieve and clears all flashes of $type
markdown( $ str , $ args , ...) // Return a string formatted with markdown
escape ( $ str ) // Escape a string
refresh() // Redirect to the current URL
back() // Redirect to the referer
query ( $ key , $ value = null ) // Modify the current query string
query ( $ arr )
layout ( $ layout ) // Set the view layout
yieldView () // Call inside the layout to render the view content
render ( $ view , $ data = array ()) // Render a view or partial (in the scope of $response)
partial ( $ view , $ data = array ()) // Render a partial without a layout (in the scope of $response)
addValidator ( $ method , $ callback ) // Add a custom validator method
validate ( $ string , $ err = null ) // Validate a string (with a custom error message)
validateParam ( $ param , $ err = null ) // Validate a param
<callback>( $ arg1 , ...) // Call a user-defined helper
<property> // Get a user-defined property
$ app ->
< callback >( $ arg1 , ...) //Call a user-defined helper
$ validator ->
notNull() // The string must not be null
isLen ( $ length ) // The string must be the exact length
isLen ( $ min , $ max ) // The string must be between $min and $max length (inclusive)
isInt() // Check for a valid integer
isFloat() // Check for a valid float/decimal
isEmail() // Check for a valid email
isUrl() // Check for a valid URL
isIp() // Check for a valid IP
isAlpha() // Check for a-z (case insensitive)
isAlnum() // Check for alphanumeric characters
contains ( $ needle ) // Check if the string contains $needle
isChars ( $ chars ) // Validate against a character list
isRegex ( $ pattern , $ modifiers = '' ) // Validate against a regular expression
notRegex ( $ pattern , $ modifiers = '' )
is<Validator>() // Validate against a custom validator
not<Validator>() // The validator can't match
<Validator>() // Alias for is<Validator>()
Las pruebas unitarias son una parte crucial del desarrollo de un motor de enrutamiento como Klein. Las funciones agregadas o las correcciones de errores pueden tener efectos adversos que son difíciles de encontrar sin muchas pruebas, de ahí la importancia de las pruebas unitarias.
Este proyecto utiliza PHPUnit como marco de prueba unitaria.
Todas las pruebas se encuentran en /tests
y cada prueba extiende una clase abstracta AbstractKleinTest
Para probar el proyecto, simplemente ejecute php composer.phar install --dev
para descargar una versión común de PHPUnit con compositor y ejecute las pruebas desde el directorio principal con ./vendor/bin/phpunit
Consulte la guía de contribución para obtener más información.
Consulte la wiki para obtener más información.
(Licencia MIT)
Copyright (c) 2010 Chris O'Hara [email protected]
Por el presente se otorga permiso, sin cargo, a cualquier persona que obtenga una copia de este software y los archivos de documentación asociados (el "Software"), para operar con el Software sin restricciones, incluidos, entre otros, los derechos de uso, copia, modificación, fusión. , publicar, distribuir, sublicenciar y/o vender copias del Software, y permitir que las personas a quienes se les proporciona el Software lo hagan, sujeto a las siguientes condiciones:
El aviso de derechos de autor anterior y este aviso de permiso se incluirán en todas las copias o partes sustanciales del Software.
EL SOFTWARE SE PROPORCIONA "TAL CUAL", SIN GARANTÍA DE NINGÚN TIPO, EXPRESA O IMPLÍCITA, INCLUYENDO, PERO NO LIMITADO A, LAS GARANTÍAS DE COMERCIABILIDAD, IDONEIDAD PARA UN PROPÓSITO PARTICULAR Y NO INFRACCIÓN. EN NINGÚN CASO LOS AUTORES O TITULARES DE DERECHOS DE AUTOR SERÁN RESPONSABLES DE NINGÚN RECLAMO, DAÑO U OTRA RESPONSABILIDAD, YA SEA EN UNA ACCIÓN CONTRACTUAL, AGRAVIO O DE OTRA MANERA, QUE SURJA DE, FUERA DE O EN RELACIÓN CON EL SOFTWARE O EL USO U OTRAS NEGOCIOS EN EL SOFTWARE.