Regex to capture infinite groups in a URL by separating them by the bar

Asked

Viewed 388 times

4

I wonder how I could do a regex to capture several groups as shown in the string below:

/Controller/Action/Param1/Param2/Param3/...

I want to capture "Controller", "Action", "Param1", "Param2", "Param3" and the more you have separated by bar, each must be a different match so you can use preg_matchPHP and throws them into a vector.

  • If you gave a substring to the first bar and then blew up the bar? It would suit you?

  • Maybe.. but I’m looking for a solution that uses only regex, if any. Otherwise I’ll have to resort to other methods.

4 answers

6

Do you really need to be a regular expression? How about using one explode()?

<?php
$str = 'Controller/Action/Param1/Param2/Param3';

$segments = explode('/', $str));
print_r($segments);

This example will return:

Array ( 
    [0] => Controller 
    [1] => Action 
    [2] => Param1 
    [3] => Param2 
    [4] => Param3 
)

Behold spinning.

If you still want to use a regex, something that can bring you the same result is preg_split() (only slower, compared to the explode)

$str = 'Controller/Action/Param1/Param2/Param3';

$segments = preg_split('/\//', $str);

print_r($segments);

Upshot:

Array ( 
    [0] => Controller 
    [1] => Action 
    [2] => Param1 
    [3] => Param2 
    [4] => Param3 
)

Example spinning.

5

It doesn’t make much sense to use regex for that, but it’s possible:

Regex

$url = 'http://example.com/Controller/Action/Param1/Param2/Param3/...';

preg_match_all( '|/([^\/]+)|', $url, $matches );

var_dump( $matches );

array(2) {
  [0]=>
  array(7) {
    [0]=>
    string(12) "/example.com"
    [1]=>
    string(11) "/Controller"
    [2]=>
    string(7) "/Action"
    [3]=>
    string(7) "/Param1"
    [4]=>
    string(7) "/Param2"
    [5]=>
    string(7) "/Param3"
    [6]=>
    string(4) "/..."
  }
  [1]=>
  array(7) {
    [0]=>
    string(11) "example.com"
    [1]=>
    string(10) "Controller"
    [2]=>
    string(6) "Action"
    [3]=>
    string(6) "Param1"
    [4]=>
    string(6) "Param2"
    [5]=>
    string(6) "Param3"
    [6]=>
    string(3) "..."
  }
}

Regex-free

$url = 'http://example.com/Controller/Action/Param1/Param2/Param3/...';
$split = explode( '/', $url );

var_dump( $split );

array(9) {
  [0]=>
  string(5) "http:"
  [1]=>
  string(0) ""
  [2]=>
  string(11) "example.com"
  [3]=>
  string(10) "Controller"
  [4]=>
  string(6) "Action"
  [5]=>
  string(6) "Param1"
  [6]=>
  string(6) "Param2"
  [7]=>
  string(6) "Param3"
  [8]=>
  string(3) "..."
}

See working

2


Using Regular Expression

Although the easiest way to solve it is with the explode, if you want to use regular expression, here is:

$input = '/Controller/Action/Param1/Param2/Param3/';

preg_match_all("/\/?([^\/]+)/", $input, $output);

var_dump($output[1]);
  • Perfectly solved the problem using Regex. Thank you

0

I find it easier and smarter to make such parameters follow a logic. Make the script smart and do not try to process anything that is not part of the system. ignore or set exception face. A responsive execution.
Like all your controllers start with (Controller_) everything you live after (Controller_) is what we want to pick up to find out which controller and which classes to call this URL.
Now establish that all Actions begin with (Actions_) what comes after (Action_) is what we take to know what action to call in our class and what class to raise. Finally would come the parameters which would be all the parameters:

^(?:/)(?:[/]Action_([a-za-Z]+))(?:/)+(?:[/])?

<?php

preg_match('/^(?:[\/](?:Controller_([a-zA-Z]+)))(?:[\/]Action_([a-zA-Z]+))(?:[\/]([a-zA-Z0-9\/\-\_]+))+(?:[\/])?/', $onde, $matches);

//Analisamos o controller se tiver um controller fazemos algo se
//não houver deixa tudo para lá sem controller não há trabalho a se fazer
if((isset($matches[1]) == true) and ($matches[1] != null) ){

//Já que tem controller na variável $matches[1] seguimos em frente

// Verificamos se há action, pois se não houver paramos
// por aqui e retorna a ação padrão do referido controller
if((isset($matches[2]) == true) and ($matches[2] != null) ){

// Se estamos aqui é por que tem um action a ser executado
// Então proseguimos

//Agora verificamos se tem parâmetros, se não houver essa parte não é executada
// e é executada somente a ação padrão para o referido action

if((isset($matches[3]) == true) and ($matches[3] != null) ){

// Como estamos aqui quer dizer que há parâmetros na variável $matches[3]
// Aplicamos um explode() nele

$pedacos = explode("/", $matches[3]);

//Analisamos cada parâmetros e tomamos decisões

}

}

}
?>

This regular expression accepts:

/Controller_carrinho/Action_pagar/Param1/Param2/Param3/
/Controller_carrinho/Action_pagar/Param1/Param2/Param3
/Controller_carrinho/Action_pagar/Param1/
/Controller_carrinho/Action_pagar/Param1
/Controller_carrinho/Action_pagar
/Controller_carrinho/Action_pagar/
/Controller/
/Controller


The controller can be anything as long as it follows the logic

Controller_buy
Controller_sell
Controller_fazerpao
Controller_listarproducts
Controller_fazercafe
Controller_comerarroz
The variables are:

$Matches[1]
The name of the controller, only what comes after the underline

$Matches[2]
The name of the action, only what comes after the underline

$Matches[3]
All parameters provided they are letters with or without numbers and strokes and underline.
It does not matter if there is a trace at the end, because it is ignored and everything that does not fit into it is also ignored.

Observing:
In the case of missing a piece there are no errors the variable will have the null value.
I use this logic so I don’t have to use $_GET on my website and analyze something that is not part and does not follow the logic of the system.

I hope you help someone!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.