Pregunta

Así que estoy escribiendo un marco en el que quiero basar algunas aplicaciones en las que estoy trabajando (el marco está ahí, así que tengo un entorno con el que trabajar y un sistema que me permitirá, por ejemplo, usar un solo iniciar sesión)

Quiero crear este marco y las aplicaciones que tiene utilizan una arquitectura orientada a recursos.

Ahora, quiero crear una clase de enrutamiento de URL que los escritores de aplicaciones puedan expandir (y posiblemente también los usuarios de la aplicación CMS, pero eso está MUY por delante en el futuro) y estoy tratando de descubrir la mejor manera de hacerlo mirando cómo lo hacen otras aplicaciones.

¿Fue útil?

Solución

Prefiero usar reg ex antes que crear mi propio formato, ya que es de conocimiento común.Escribí una pequeña clase que uso y que me permite anidar estas tablas de enrutamiento reg ex.Solía ​​usar algo similar que se implementó por herencia pero no necesitaba herencia, así que lo reescribí.

Hago una expresión regular en una clave y la asigno a mi propia cadena de control.Tome el siguiente ejemplo.yo visito /api/related/joe y mi clase de enrutador crea un nuevo objeto ApiController y llama a su método relatedDocuments(array('tags' => 'joe'));

// the 12 strips the subdirectory my app is running in
$index = urldecode(substr($_SERVER["REQUEST_URI"], 12)); 

Route::process($index, array(
    "#^api/related/(.*)$#Di"    => "ApiController/relatedDocuments/tags",

    "#^thread/(.*)/post$#Di"    => "ThreadController/post/title",
    "#^thread/(.*)/reply$#Di"   => "ThreadController/reply/title",
    "#^thread/(.*)$#Di"         => "ThreadController/thread/title",

    "#^ajax/tag/(.*)/(.*)$#Di"  => "TagController/add/id/tags",
    "#^ajax/reply/(.*)/post$#Di"=> "ThreadController/ajaxPost/id",
    "#^ajax/reply/(.*)$#Di"     => "ArticleController/newReply/id",
    "#^ajax/toggle/(.*)$#Di"    => "ApiController/toggle/toggle",

    "#^$#Di"                    => "HomeController",
));

Para mantener bajos los errores y aumentar la simplicidad, puede subdividir su tabla.De esta manera puedes colocar la tabla de enrutamiento en la clase que controla.Tomando el ejemplo anterior, puede combinar las tres llamadas de subprocesos en una sola.

Route::process($index, array(
    "#^api/related/(.*)$#Di"    => "ApiController/relatedDocuments/tags",

    "#^thread/(.*)$#Di"         => "ThreadController/route/uri",

    "#^ajax/tag/(.*)/(.*)$#Di"  => "TagController/add/id/tags",
    "#^ajax/reply/(.*)/post$#Di"=> "ThreadController/ajaxPost/id",
    "#^ajax/reply/(.*)$#Di"     => "ArticleController/newReply/id",
    "#^ajax/toggle/(.*)$#Di"    => "ApiController/toggle/toggle",

    "#^$#Di"                    => "HomeController",
));

Luego define ThreadController::route para que sea así.

function route($args) {
    Route::process($args['uri'], array(
        "#^(.*)/post$#Di"    => "ThreadController/post/title",
        "#^(.*)/reply$#Di"   => "ThreadController/reply/title",
        "#^(.*)$#Di"         => "ThreadController/thread/title",
    ));
}

También puede definir los valores predeterminados que desee para su cadena de enrutamiento a la derecha.Simplemente no olvides documentarlos o confundirás a la gente.Actualmente estoy llamando a index si no incluye un nombre de función a la derecha. Aquí es mi código actual.Es posible que desee cambiarlo para manejar los errores como desee o las acciones predeterminadas.

Otros consejos

¿Otro marco más?-- de todos modos...

El truco con el enrutamiento consiste en pasarlo todo a su controlador de enrutamiento.

Probablemente quieras usar algo similar a lo que he documentado aquí:

http://www.hm2k.com/posts/friendly-urls

La segunda solución le permite utilizar URL similares a Zend Framework.

Use una lista de expresiones regulares para que coincida con el objeto que debería usar

Por ejemplo

^/users/[\w-]+/bookmarks/(.+)/$
^/users/[\w-]+/bookmarks/$
^/users/[\w-]+/$

Ventajas:Agradable y simple, permítanme definir rutas directamente contras:Tendría que ordenarse, lo que no facilitaría agregar cosas nuevas (muy propenso a errores)

Así es, afaik, cómo lo hace Django.

Creo que muchos marcos usan una combinación de mod_rewrite de Apache y un controlador frontal.Con mod_rewrite, puedes convertir una URL como esta:/people/get/3 en esto:index.php?controller=personas&method=get&id=3.Index.php implementaría su controlador frontal que enruta la solicitud de la página según los parámetros proporcionados.

Como es de esperar, hay muchas formas de hacerlo.

Por ejemplo, en Marco delgado , un ejemplo del motor de enrutamiento puede ser el siguiente (basado en el patrón ${OBJECT}->${REQUEST METHOD}(${PATTERM}, ${CALLBACK}) ):

$app->get("/Home", function() {
    print('Welcome to the home page');
}

$app->get('/Profile/:memberName', function($memberName) {
    print( 'I\'m viewing ' . $memberName . '\'s profile.' );
}

$app->post('/ContactUs', function() {
    print( 'This action will be fired only if a POST request will occure');
}

Entonces, la instancia inicializada ($app) obtiene un método por método de solicitud (p. ej.obtener, publicar, poner, eliminar, etc.) y obtiene una ruta como primer parámetro y una devolución de llamada como segundo.

La ruta puede obtener tokens, que es una "variable" que cambiará en tiempo de ejecución en función de algunos datos (como el nombre del miembro, la identificación del artículo, el nombre de la ubicación de la organización o lo que sea, ya sabes, como en todos los controladores de enrutamiento).

Personalmente, me gusta esta forma, pero no creo que sea lo suficientemente flexible para un marco avanzado.

Como actualmente trabajo con ZF y Yii, tengo un ejemplo de un enrutador que creé como parte de un marco para una empresa para la que trabajo:

El motor de ruta se basa en expresiones regulares (similar a la de @gradbot) pero tiene una conversación bidireccional, por lo que si un cliente suyo no puede ejecutar mod_rewrite (en Apache) o agregar reglas de reescritura en su servidor, él o ella Todavía puedo usar las URL tradicionales con una cadena de consulta.

El archivo contiene una matriz, cada uno de ellos, cada elemento es similar a este ejemplo:

$_FURLTEMPLATES['login']    =   array(
    'i' => array( // Input - how the router parse an incomming path into query string params
        'pattern' => '@Members/Login/?@i',
        'matches' => array( 'Application' => 'Members', 'Module' => 'Login' ),
    ),
    'o' => array( // Output - how the router parse a query string into a route
        '@Application=Members(&|&)Module=Login/?@' => 'Members/Login/'
    )
);

También puedes utilizar combinaciones más complejas, como:

$_FURLTEMPLATES['article']  =   array(
    'i' => array(
        'pattern' => '@CMS/Articles/([\d]+)/?@i',
        'matches' => array( 'Application' => "CMS",
            'Module' => 'Articles',
            'Sector' => 'showArticle',
            'ArticleID' => '$1' ),
    ),
    'o' => array(
     '@Application=CMS(&|&)Module=Articles(&|&)Sector=showArticle(&|&)ArticleID=([\d]+)@' => 'CMS/Articles/$4'
    )
);

La conclusión, en mi opinión, es que las posibilidades son infinitas, sólo depende de qué tan complejo desee que sea su marco y qué desee hacer con él.

Si, por ejemplo, solo pretende ser un servicio web o un simple contenedor de sitio web, simplemente elija el estilo de escritura de Slim Framework: un código muy sencillo y atractivo.

Sin embargo, si desea desarrollar sitios complejos usándolo, creo que regex es la solución.

¡Buena suerte!:)

Deberías echarle un vistazo a Pux https://github.com/c9s/Pux

Aquí está la sinopsis

<?php
require 'vendor/autoload.php'; // use PCRE patterns you need Pux\PatternCompiler class.
use Pux\Executor;

class ProductController {
    public function listAction() {
        return 'product list';
    }
    public function itemAction($id) { 
        return "product $id";
    }
}
$mux = new Pux\Mux;
$mux->any('/product', ['ProductController','listAction']);
$mux->get('/product/:id', ['ProductController','itemAction'] , [
    'require' => [ 'id' => '\d+', ],
    'default' => [ 'id' => '1', ]
]);
$mux->post('/product/:id', ['ProductController','updateAction'] , [
    'require' => [ 'id' => '\d+', ],
    'default' => [ 'id' => '1', ]
]);
$mux->delete('/product/:id', ['ProductController','deleteAction'] , [
    'require' => [ 'id' => '\d+', ],
    'default' => [ 'id' => '1', ]
]);
$route = $mux->dispatch('/product/1');
Executor::execute($route);

El marco MVC de Zend utiliza por defecto una estructura como

/router/controller/action/key1/value1/key2/value2

dónde router es el archivo del enrutador (asignado a través de mod_rewrite, controller es de un controlador de acciones del controlador que está definido por una clase que se deriva de Zend_Controller_Action y action hace referencia a un método en el controlador, llamado actionAction.Los pares clave/valor pueden ir en cualquier orden y están disponibles para el método de acción como una matriz asociativa.

He usado algo similar en el pasado en mi propio código y hasta ahora ha funcionado bastante bien.

Intenta echar un vistazo mvc patrón.
Zend Framework lo usa por ejemplo, pero también CakePHP, CodeIgniter, ...

A mí personalmente no me gusta el modelo MVC, pero la mayor parte del tiempo se implementa como componente "Ver para web".

La decisión depende mucho de las preferencias...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top