Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
PHP - espressione regolare per fare matching
Forum - PHP - espressione regolare per fare matching

Avatar
TheDarkJuster (Member)
Guru^2


Messaggi: 1620
Iscritto: 27/09/2013

Segnala al moderatore
Postato alle 21:24
Venerdì, 01/04/2016
Buonasera,
sto avendo problemi con l'uso delle espressioni regolari per fare il matching degli URL.

Al momento uso questo codice:
Codice sorgente - presumibilmente Php

  1. /**
  2.          * Set the routing for a given method/URI pair (or group of URI if regex is used).
  3.          * An example of usage can be:
  4.          * <code>
  5.          * use Gishiki\Core;
  6.          *
  7.          * Routing::setRoute(Routing::GET, "/user/{id}", function ($params) {
  8.          *      foreach ($params as $param_name => $param_value) {
  9.          *          echo $param_name." => ".$param_value;
  10.          *      }
  11.          * });
  12.          *
  13.          * //if the framework is installed at https://site.com/ when an user requests
  14.          * //https://site.com/user/5476 the user will see: id => 5476
  15.          * </code>
  16.          *
  17.          * @param integer $Method one request method chosen from GET, POST, HEAD ecc....
  18.          * @param string $URI the URI that will bring to the function execution
  19.          * @param function $function the function executed when the URL is called
  20.          */
  21.         public static function setRoute($Method, $URI, $function) {
  22.             if ((!static::$executed) && (static::getRequestMethod() == $Method)) {
  23.                 //this will contain the matched expressions placeholders
  24.                 $params = array();
  25.  
  26.                 //detect if regex are involved in the furnished URI
  27.                 if (preg_match_all('/\\{[[:alnum:]]+\\}/', $URI, $params)) {
  28.                     //this is the regular expression an URL must match to trigger the function execution
  29.                     $URItoBeMatched = $URI;
  30.                    
  31.                     //sobstitute each virtual param with a regex that matches everything
  32.                     foreach ($params as $param_name => $param_value) {
  33.                         $URItoBeMatched = str_replace($param_value, "(.*)", $URItoBeMatched);
  34.                     }
  35.                    
  36.                     $URI_real_params = array();
  37.  
  38.                     //preg_match_all("@^".$URItoBeMatched."*$@i", static::getRequestURI(), $URI_real_params);
  39.                     preg_match("@^".$URItoBeMatched."*@i", static::getRequestURI(), $URI_real_params);
  40.                    
  41.                     var_dump($URItoBeMatched);
  42.                     var_dump($params);
  43.                     var_dump($URI_real_params);
  44.                    
  45.                 } else {
  46.                     //no regex routing: just check if the current request is done to the given routing
  47.                     if (static::getRequestURI() == $URI) {
  48.                         $function();
  49.                         static::$executed = TRUE;
  50.                     }
  51.                 }
  52.             }
  53.         }



La descrizione dovrebbe essere abbastanza per capire cosa voglio fare, ma lo rispiego comunque.

dato un URI del tipo: /user/{id}/post/{num}
voglio che vangano matchati tutti gli uri del tipo: /user/X1/post/X2 con X1, X2 qualsiasi serie di caratteri.

Fino a qui non c'è alcun problema: tutti gli uri vengono riconosciuti a dovere.

Tuttavia io voglio di più: voglio generare un array costruito nel seguente modo:
Codice sorgente - presumibilmente Plain Text

  1. $param = array(
  2.     "id" => X1,
  3.     "post" => X2,
  4. );


Questo sarebbe semplicissimo se il risultato di preg_match non fosse diverso da ciò che mi aspetto:
imposto il routing nel seguente modo: \Gishiki\Core\Routing::setRoute(\Gishiki\Core\Routing::GET, "/user/{id}/post/{post}", function($params) {});

grazie al primo var_dump so che il risultato della prima preg_match è corretto:
Codice sorgente - presumibilmente PHP

  1.  0 => "{id}",
  2.  1 => "{post}",
  3. );



il risultato del secondo è un vero disastro: provando l'URI /user/45/post/60 ottengo:
Codice sorgente - presumibilmente PHP

  1.  0 => '/user/45/post/60',
  2.  1 => '45',
  3.  2 => ''
  4. );



Va bene, passi il fatto che il primo match è ovviamente la stringa intera.....
il secondo elemento dell'array è corretto.....
ma.... io mi aspettavo un '60' come terzo elemento. Perchè ottengo solo '' anche cambiando il 60 con qualsiasi altra cosa?

PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 17:04
Sabato, 02/04/2016
Ciao, per semplicità ti mostro solo la regex che adopererei io
Codice sorgente - presumibilmente Plain Text

  1. ^\/user\/([^/]+)\/post\/([^/]+)$


Le preg_match restituiscono dovrebbero sempre (se non mi sto confondendo) come primo gruppo rilevato (pre intenderci lo 0) l'intero matching in quanto per definizione i gruppi delle regex sono enumerati partendo da 1, quindi il risultato non è cosi assurdo.
Con la regex che ho postato sopra identifichi qualsiasi cosa per id tranne gli slash cosi da non avere problemi per ogni sorta di codifica.
Ti consiglierei inoltre questo tool che negli anni si è evoluto diventando uno strumento indispensabile per la formulazione di regex http://regexr.com/
Spero di essere stato utile.

Ultima modifica effettuata da Roby94 il 02/04/2016 alle 17:04
PM Quote
Avatar
TheDarkJuster (Member)
Guru^2


Messaggi: 1620
Iscritto: 27/09/2013

Segnala al moderatore
Postato alle 21:50
Sabato, 02/04/2016
Beh per il momento ho risolto senza regex in maniera abbastanza semplice, quindi mi ritengo soddisfatto, ma grazie comunque del consiglio.
Se dovessero servirmi ancora le regex so cosa fare :heehee:

Grazie dei consigli, appena ho un po di tempo provo la regex per sfizio personale

PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 2:47
Domenica, 03/04/2016
Guarda, le regex ti cambiano la vita nel campo dei parser. Tanto da portarti all'odio quando ti trovi su un sistema che non le supporta (vedi microcontrollori a 8bit). Indubbiamente un tassello indispensabile per un buon programmatore general purpose :rofl:

PM Quote
Avatar
TheDarkJuster (Member)
Guru^2


Messaggi: 1620
Iscritto: 27/09/2013

Segnala al moderatore
Postato alle 16:31
Domenica, 03/04/2016
Da quel che vedo ereg_match non funziona: la regex funziona solo su http://regexr.com/, ma non con php.
Ho messo la regex direttamente nel sorgente (non è generata a runtime) quindi non posso averla sbagliata, anche perchè faccio un var_dump ed esce esattamente la query che mi hai dato (con i caratteri di apertura e chiusura)

PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 17:14
Domenica, 03/04/2016
Si, dipende dal implementazione se / deve essere preceduto da carattere di escape.
Codice sorgente - presumibilmente Plain Text

  1. $matches=[];
  2. $subject = "/user/10/post/47";
  3. preg_match("/^\/user\/([^\/]+)\/post\/([^\/]+)$/", $subject, $matches);
  4. var_dump($matches);


Ultima modifica effettuata da Roby94 il 03/04/2016 alle 17:19
PM Quote