Espressione regolare per effettuare match con URI

JackIlPazzo

Utente Attivo
25 Lug 2014
69
0
6
Ciao a tutti, ho scritto un piccolo sistema di routing che permette di definire la logica strutturale degli URL sulla mia Rest API. Di seguito il funzionamento:

PHP:
$listUri = "transaction/.+";
$uri = isset($_REQUEST['uri']) ? $_REQUEST['uri'] : '/'; // transaction/19-02-2016

if(preg_match("#^$listUri$#", $uri)) 
{
    echo "done!";
}

Come si può vedere `$listUri` contiene tutti gli url mappati (quelli accettabili dal sistema), in modo che io possa iterarli per fare match con l'url corrente. Abbiamo poi la variabile `$uri` che preleva l'url corrente dal browser, ora io utilizzo una semplice espressione regolare per effettuare match con l'url e dall'esempio mostrato in alto tutto funziona correttamente. Mettiamo però che si verifichi una situazione del genere:

PHP:
$listUri = "transaction/.+";
$uri = isset($_REQUEST['uri']) ? $_REQUEST['uri'] : '/'; // transaction/19-02-2016/user

if(preg_match("#^$listUri$#", $uri)) 
{
    echo "done!";
}

La variabile `$listUri` contiene un "/.+" il ché significa che l'url mappato può accettare un solo parametro dopo "transaction" (come tra l'altro già mostrato nel primo esempio). Questa volta la variabile `$uri` contiene una richiesta sbagliata, come mostrato nel primo esempio infatti la richiesta è corretta, ma questa volta c'è un `user` dopo il parametro il ché è sbagliato. Perché è sbagliato? Perché in `$listUri` l'url è mappato come "transaction/.+", questo significa che se io metto ".+/user" l'echo non deve essere stampato.
Dovrei fare in modo di realizzare un'espressione regolare che mi permetta di riconoscere se ci sono ".+/" e se fanno match con l'url corrente. Ovviamente l'url è dinamico quindi bisogna creare un pattern che vada bene per tutto.

In parole povere (con un esempio):

$listUri => "transaction/.+"

Funzionamento

$uri => "transaction/19-02-2016/" (corretto)
$uri => "transaction/19-02-2016/user/prova/dd" (sbagliato - la mappatura accetta solo transaction/.+ altri parametri non devono essere presi in considerazione)"

Non so se ho reso l'idea. Spero che qualcuno mi aiuti a realizzare la regex, diciamo che non è il mio forte.
 
Dopo qualche ora di sbattimento ho quasi risolto il problema creando una funzione:

PHP:
function matchRoute($url, $pattern) 
{	
        $urlParts = array_filter(explode('/', $url));
        $patternParts = array_filter(explode('/', $pattern)); 
        
        if (count($urlParts) != count($patternParts)) 
	{
            return false;
        }

		
        for ($i = 0 ; $i < count($urlParts); $i++) 
        {
            if(!preg_match('/^' . $patternParts[$i] .'$/', $urlParts[$i]))
	    {
                return false;
            }
        }

        return true;

}

$testUri = 'transaction/19-02-2016/SomeWrongUrlRequest';
$matchUri = 'transaction/getTest/.+/categoria/.+';

echo "FALSE <BR>";
var_dump(matchRoute($testUri, $matchUri));  
echo "<br>TRUE <br>";
var_dump(matchRoute('transaction/getTests/9/categorias/5/', $matchUri));

Ora diciamo che ho raggiunto il mio scopo ma non è ancora del tutto funzionante per i seguenti motivi:

1. Se inserisco "categorias" invece di categoria l'espressione regolare va a buon fine e questo è sbagliato, dovrei fare in modo che caratteri finali che non corrispondono alla stringa facciano cadere la funzione in false e non in true. [FIXATO]
: Per risolverlo ho agginuto nel pattern "/^" e "$/"

2. array_filter comporta che se io passo come parametro lo 0 quindi: getTests/0/.. io otterrò automaticamente false

Qualche buon samaritano che mi aiuta a risolvere?

:mexican:
 
Ultima modifica:

Discussioni simili