How to get the last segment of the path?

3
URLs de exemplo:
content/edit
content/edit/
content/edit?q=
content/edit/?q=

I tried to make the code but it always fails when the url does not have "/" or "?" and if you have "/?" in the end. The code I made was:

.*\/([a-zA-Z0-9]*)[\/\?].*

It takes the "edit" value.

    
asked by anonymous 18.09.2017 / 16:25

4 answers

2

The simplest solution is to use PHP, as shown in other answers, but if you just want the regular expression to use with the .htaccess file, see the solution below.

To answer this, we first need to understand the structure of a URI:

  foo://example.com:8042/over/there;param=value;p2;p3?name=ferret#nose
  \_/   \______________/\_________/ \_______________/ \_________/ \__/
   |           |            |              |              |         |
scheme     authority       path          params         query   fragment

We can see that after path there may be param , query and fragment values. We start by analyzing only path :

To get the last segment of path , we use the regular expression:

\/?([a-zA-Z0-9_\-+]+)\/?$
That is, the value can start with a slash, followed by a non-null sequence of letters, numbers or _ , - and + (can freely change that part), followed or not by a slash , ending the value. In this way, the following URLs below will be properly analyzed:

edit
/edit
/edit/
/content/edit
/content/edit/
  

See working at Regex101 .

Now, we must add to the expression the part that will analyze the possible existence of params in the URL. For simplicity, since it is not in our interest to know the parameters of path , let's consider as a parameter any string other than / that follows the ; character. Both the character and the string will be optional, so the regular expression becomes:

\/?([a-zA-Z0-9_\-+]+)\/?(?:\;[^\/]*)?$

So both the URLs above and below will work:

edit
/edit
/edit/
/content/edit
/content/edit/
/content/edit;param=foo
/content;param=foo/edit/
  

See working at Regex101 .

The same logic we will apply to the query of the URL, being defined as any string of characters that follows the character ? . Thus, the regular expression becomes:

\/?([a-zA-Z0-9_\-+]+)\/?(?:\;[^\/]*)?(?:\?.*)?$

So all the URLs below will work:

edit
/edit
/edit/
/content/edit
/content/edit/
/content/edit;param=foo
/content;param=foo/edit/
/content/edit?q=foo
/content/edit/?q=foo
  

See working at Regex101 .

To complete, we need to parse the fragment part of the URL, being defined as any string that follows the # character.

\/?([a-zA-Z0-9_\-+]+)\/?(?:\;[^\/]*)?(?:\?.*)?(?:\#.*)?$

This works for all possible URL variations:

edit
/edit
/edit/
/content/edit
/content/edit/
/content/edit;param=foo
/content;param=foo/edit/
/content/edit?q=foo
/content/edit/?q=foo
/content/edit#foo
/content/edit/#foo

In all, the only group caught will be edit .

  

See working at Regex101 .

The same expression can be simplified to:

\/?([\w+-]+)\/?(?|\;[^\/]*|[?#].*)?$

Guilherme Lautert .

  

See working at Regex101 .

    
18.09.2017 / 19:55
3

A very simple way, without using regular expression:

//Obtenha a URL sem as variáveis
$url = $_SERVER['REDIRECT_URL'];

//exploda 
$array_url = explode('/',$url);

//Caso a URL termine com /, a última posição do array estará em branco, então contorne isso
$array_url=array_filter($array_url);

//A última posição do array equivale à ultima palavra.
$palavra = array_pop($array_url);
    
18.09.2017 / 16:50
1

I think this regex solves your problem:

(\/\w+\/\w+)((\/?$)|(\?.+$))

I created a test on the link below:

link

The content you need is in group 1 (green)

    
18.09.2017 / 16:49
1

You can use preg_split() to capture all values between the bars and call array_reverse() to invert the order of the elements, throwing the last as first. preg_match() checks if the current element starts with some letter otherwise it goes to the next element this treats the case ?Q=abc

function ultimaParteURL($url){
    $segmentos = array_reverse(preg_split('#/#', $url , null, PREG_SPLIT_NO_EMPTY));
    foreach ($segmentos as $item){
        if(preg_match('#^[A-Z]#i', $item)) return $item; 
    }
}

echo ultimaParteURL('content/edit/?Q=abc') .'<br>';
echo ultimaParteURL('content/edit/') .'<br>';
echo ultimaParteURL('content/edit&abc=12015') .'<br>';

Example:

Array
(
    [0] => content
    [1] => edit?q=
)

After the call of array_reverse() it turns:

Array
(
    [0] => edit?q=
    [1] => content
)
    
18.09.2017 / 16:52