Domanda

Quindi sto scrivendo un framework su cui voglio basare alcune app su cui sto lavorando (il framework è lì, quindi ho un ambiente con cui lavorare e un sistema che mi permetterà, ad esempio, utilizzare un unico accesso)

Voglio creare questo framework e le app che ha utilizzato un'architettura orientata alle risorse.

Ora, voglio creare una classe di routing URL che sia espandibile dagli autori di APP (e possibilmente anche dagli utenti dell'app CMS, ma è WAYYYY in futuro) e sto cercando di capire il modo migliore per farlo guardando come lo fanno altre app.

È stato utile?

Soluzione

Preferisco usare reg ex piuttosto che creare il mio formato dato che è una conoscenza comune. Ho scritto una piccola classe che uso che mi consente di nidificare queste tabelle di routing reg ex. Uso qualcosa di simile che è stato implementato per ereditarietà ma non ha avuto bisogno di ereditarietà, quindi lo riscrivo.

Faccio un reg ex su una chiave e mappo sulla mia stringa di controllo. Prendi l'esempio seguente. Visito / api / related / joe e la mia classe di router crea un nuovo oggetto ApiController e chiama il suo metodo relatedDocuments (array ('tags' = > 'joe '));

// the 12 strips the subdirectory my app is running in
$index = urldecode(substr(

Preferisco usare reg ex piuttosto che creare il mio formato dato che è una conoscenza comune. Ho scritto una piccola classe che uso che mi consente di nidificare queste tabelle di routing reg ex. Uso qualcosa di simile che è stato implementato per ereditarietà ma non ha avuto bisogno di ereditarietà, quindi lo riscrivo.

Faccio un reg ex su una chiave e mappo sulla mia stringa di controllo. Prendi l'esempio seguente. Visito / api / related / joe e la mia classe di router crea un nuovo oggetto ApiController e chiama il suo metodo relatedDocuments (array ('tags' = > 'joe '));

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",
));

Al fine di mantenere bassi gli errori e semplificare, è possibile suddividere la tabella. In questo modo è possibile inserire la tabella di routing nella classe che controlla. Prendendo l'esempio sopra puoi combinare le tre chiamate in thread in una sola.

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

Quindi definisci ThreadController :: route per essere così.

<*>

Inoltre puoi definire qualsiasi impostazione predefinita desideri per la tua stringa di routing sulla destra. Basta non dimenticare di documentarli o confonderai le persone. Attualmente sto chiamando indice se non si include un nome di funzione sulla destra. Qui è il mio codice attuale. Potrebbe essere necessario modificarlo per gestire gli errori nel modo desiderato e / o le azioni predefinite.

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", ));

Al fine di mantenere bassi gli errori e semplificare, è possibile suddividere la tabella. In questo modo è possibile inserire la tabella di routing nella classe che controlla. Prendendo l'esempio sopra puoi combinare le tre chiamate in thread in una sola.

<*>

Quindi definisci ThreadController :: route per essere così.

<*>

Inoltre puoi definire qualsiasi impostazione predefinita desideri per la tua stringa di routing sulla destra. Basta non dimenticare di documentarli o confonderai le persone. Attualmente sto chiamando indice se non si include un nome di funzione sulla destra. Qui è il mio codice attuale. Potrebbe essere necessario modificarlo per gestire gli errori nel modo desiderato e / o le azioni predefinite.

Altri suggerimenti

Ancora un altro framework? - comunque ...

Il trucco sta nel routing è di passarlo tutto al controller di routing.

Probabilmente vorresti usare qualcosa di simile a quello che ho documentato qui:

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

La seconda soluzione ti consente di utilizzare URL simili a Zend Framework.

Usa un elenco di Regex per abbinare l'oggetto che dovrei usare

Ad esempio

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

Pro: bello e semplice, mi permette di definire i percorsi direttamente Contro: dovrebbe essere ordinato, non facilitando l'aggiunta di nuove cose in (molto soggetto a errori)

Questo è, a quanto pare, come Django lo fa

Penso che molti framework utilizzino una combinazione di mod_rewrite di Apache e un front controller. Con mod_rewrite, puoi trasformare un URL come questo: / people / get / 3 in questo: Index.php? Controller = persone & amp; method = get & amp; id = 3. Index.php implementerebbe il tuo front controller che instrada la richiesta di pagina in base ai parametri indicati.

Come ci si potrebbe aspettare, ci sono molti modi per farlo.

Ad esempio, in Slim Framework , un esempio del motore di routing potrebbe essere il seguente (basato sul modello $ {OBJECT} - > $ {METODO DI RICHIESTA} ($ {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');
}

Quindi, l'istanza inizializzata ( $ app ) ottiene un metodo per metodo di richiesta (es. get, post, put, delete ecc.) e ottiene una route come primo parametro e callback come seconda .

Il percorso può ottenere token - che è " variabile " che cambierà in fase di esecuzione in base ad alcuni dati (come il nome del membro, l'id articolo, il nome della posizione dell'organizzazione o qualsiasi altra cosa, sai, proprio come in ogni controller di routing).

Personalmente, mi piace in questo modo ma non credo che sarà abbastanza flessibile per un framework avanzato.

Dato che attualmente sto lavorando con ZF e Yii, ho un esempio di router che ho creato come parte di un framework per un'azienda per cui lavoro:

Il motore di route si basa su regex (simile a quello di @ gradbot) ma ha avuto una conversazione a due vie, quindi se un tuo client non può eseguire mod_rewrite (in Apache) o aggiungere regole di riscrittura sul proprio server, lui o lei può ancora usare gli URL tradizionali con stringa di query.

Il file contiene un array, ciascuno di essi, ogni elemento è simile a questo esempio:

Come ci si potrebbe aspettare, ci sono molti modi per farlo.

Ad esempio, in Slim Framework , un esempio del motore di routing potrebbe essere il seguente (basato sul modello $ {OBJECT} - > $ {METODO DI RICHIESTA} ($ {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');
}

Quindi, l'istanza inizializzata ( $ app ) ottiene un metodo per metodo di richiesta (es. get, post, put, delete ecc.) e ottiene una route come primo parametro e callback come seconda .

Il percorso può ottenere token - che è " variabile " che cambierà in fase di esecuzione in base ad alcuni dati (come il nome del membro, l'id articolo, il nome della posizione dell'organizzazione o qualsiasi altra cosa, sai, proprio come in ogni controller di routing).

Personalmente, mi piace in questo modo ma non credo che sarà abbastanza flessibile per un framework avanzato.

Dato che attualmente sto lavorando con ZF e Yii, ho un esempio di router che ho creato come parte di un framework per un'azienda per cui lavoro:

Il motore di route si basa su regex (simile a quello di @ gradbot) ma ha avuto una conversazione a due vie, quindi se un tuo client non può eseguire mod_rewrite (in Apache) o aggiungere regole di riscrittura sul proprio server, lui o lei può ancora usare gli URL tradizionali con stringa di query.

Il file contiene un array, ciascuno di essi, ogni elemento è simile a questo esempio:

Come ci si potrebbe aspettare, ci sono molti modi per farlo.

Ad esempio, in Slim Framework , un esempio del motore di routing potrebbe essere il seguente (basato sul modello $ {OBJECT} - > $ {METODO DI RICHIESTA} ($ {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');
}

Quindi, l'istanza inizializzata ( $ app ) ottiene un metodo per metodo di richiesta (es. get, post, put, delete ecc.) e ottiene una route come primo parametro e callback come seconda .

Il percorso può ottenere token - che è " variabile " che cambierà in fase di esecuzione in base ad alcuni dati (come il nome del membro, l'id articolo, il nome della posizione dell'organizzazione o qualsiasi altra cosa, sai, proprio come in ogni controller di routing).

Personalmente, mi piace in questo modo ma non credo che sarà abbastanza flessibile per un framework avanzato.

Dato che attualmente sto lavorando con ZF e Yii, ho un esempio di router che ho creato come parte di un framework per un'azienda per cui lavoro:

Il motore di route si basa su regex (simile a quello di @ gradbot) ma ha avuto una conversazione a due vie, quindi se un tuo client non può eseguire mod_rewrite (in Apache) o aggiungere regole di riscrittura sul proprio server, lui o lei può ancora usare gli URL tradizionali con stringa di query.

Il file contiene un array, ciascuno di essi, ogni elemento è simile a questo esempio:

Come ci si potrebbe aspettare, ci sono molti modi per farlo.

Ad esempio, in Slim Framework , un esempio del motore di routing potrebbe essere il seguente (basato sul modello $ {OBJECT} - > $ {METODO DI RICHIESTA} ($ {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');
}

Quindi, l'istanza inizializzata ( $ app ) ottiene un metodo per metodo di richiesta (es. get, post, put, delete ecc.) e ottiene una route come primo parametro e callback come seconda .

Il percorso può ottenere token - che è " variabile " che cambierà in fase di esecuzione in base ad alcuni dati (come il nome del membro, l'id articolo, il nome della posizione dell'organizzazione o qualsiasi altra cosa, sai, proprio come in ogni controller di routing).

Personalmente, mi piace in questo modo ma non credo che sarà abbastanza flessibile per un framework avanzato.

Dato che attualmente sto lavorando con ZF e Yii, ho un esempio di router che ho creato come parte di un framework per un'azienda per cui lavoro:

Il motore di route si basa su regex (simile a quello di @ gradbot) ma ha avuto una conversazione a due vie, quindi se un tuo client non può eseguire mod_rewrite (in Apache) o aggiungere regole di riscrittura sul proprio server, lui o lei può ancora usare gli URL tradizionali con stringa di query.

Il file contiene un array, ciascuno di essi, ogni elemento è simile a questo esempio:

<*>

Puoi anche usare combinazioni più complesse, come:

<*>

La linea di fondo, come penso, è che le possibilità sono infinite, dipende solo da quanto complesso desideri che la tua struttura sia e da cosa desideri farne.

Se, ad esempio, è solo destinato a essere un servizio Web o un semplice wrapper di siti Web, basta usare lo stile di scrittura di Slim framework, un codice molto semplice e di bell'aspetto.

Tuttavia, se desideri sviluppare siti complessi utilizzandolo, penso che regex sia la soluzione.

Buona fortuna! :)

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(&|&amp;)Module=Login/?@' => 'Members/Login/' ) );

Puoi anche usare combinazioni più complesse, come:

<*>

La linea di fondo, come penso, è che le possibilità sono infinite, dipende solo da quanto complesso desideri che la tua struttura sia e da cosa desideri farne.

Se, ad esempio, è solo destinato a essere un servizio Web o un semplice wrapper di siti Web, basta usare lo stile di scrittura di Slim framework, un codice molto semplice e di bell'aspetto.

Tuttavia, se desideri sviluppare siti complessi utilizzandolo, penso che regex sia la soluzione.

Buona fortuna! :)

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

Puoi anche usare combinazioni più complesse, come:

<*>

La linea di fondo, come penso, è che le possibilità sono infinite, dipende solo da quanto complesso desideri che la tua struttura sia e da cosa desideri farne.

Se, ad esempio, è solo destinato a essere un servizio Web o un semplice wrapper di siti Web, basta usare lo stile di scrittura di Slim framework, un codice molto semplice e di bell'aspetto.

Tuttavia, se desideri sviluppare siti complessi utilizzandolo, penso che regex sia la soluzione.

Buona fortuna! :)

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(&|&amp;)Module=Login/?@' => 'Members/Login/' ) );

Puoi anche usare combinazioni più complesse, come:

<*>

La linea di fondo, come penso, è che le possibilità sono infinite, dipende solo da quanto complesso desideri che la tua struttura sia e da cosa desideri farne.

Se, ad esempio, è solo destinato a essere un servizio Web o un semplice wrapper di siti Web, basta usare lo stile di scrittura di Slim framework, un codice molto semplice e di bell'aspetto.

Tuttavia, se desideri sviluppare siti complessi utilizzandolo, penso che regex sia la soluzione.

Buona fortuna! :)

Dovresti dare un'occhiata a Pux https://github.com/c9s/Pux

Ecco la sinossi

<?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);

Il framework MVC di Zend per impostazione predefinita utilizza una struttura come

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

dove router è il file del router (mappato tramite mod_rewrite , controller proviene da un gestore di azioni del controller definito da una classe che deriva da Zend_Controller_Action e action fa riferimento a un metodo nel controller, denominato actionAction . Le coppie chiave / valore possono andare in qualsiasi ordine e sono disponibili per metodo di azione come matrice associativa.

Ho usato qualcosa di simile in passato nel mio codice e finora ha funzionato abbastanza bene.

Prova a dare un'occhiata al pattern MVC .
Zend Framework lo utilizza ad esempio, ma anche CakePHP, CodeIgniter, ...

Personalmente non mi piace il modello MVC, ma il più delle volte è implementato come " Visualizza per web " componente.

La decisione dipende praticamente dalle preferenze ...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top