3

I'm building a route system and there's a need for URI segment variables, that match exactly [A-Za-z]

It's very important to note, that a variable can be at any position (not only at the start or at the end),

For example, this could be

/post/(:letter)/comment/(:letter)

or

/user/(:letter)

or

/(:letter)

so that, I cannot rely on ^ and $

The problem is that, it doesn't work as expected === This matches both numbers and letters, which is undesirable. I care about letters and only.

I want this to be able to match only A-Za-z, not digits and anything else, because an URI variable have to contain letters and only.

To demonstrate the problem in action,

$pattern = '~/post/(:letter)/commentid/(:letter)/replyid/(:letter)~';

$pattern = str_replace('(:letter)', '[A-Za-z]+', $pattern);

$uri = '/post/foo/commentid/someid/replyid/someanotherid';

preg_match($pattern, $uri, $matches);

print_r($matches); // Success

Now look at this:

$uri = '/post/foo123/commentid/someid123/replyid/someanotherid123';

preg_match($pattern, $uri, $matches);

print_r($matches); // Also success, I don't want this!

As you can see, this is undesireable because variables, foo123, someid123, someanotherid123 contain numbers as well.

The question is,

$magic_regex = 'What should it be to match exactly [A-Za-z] at any position?';

$pattern = str_replace('(:letter)', $magic_regex, $pattern);
Yang
  • 8,580
  • 8
  • 33
  • 58
  • Do you mean you want each segment (between the slashes) to be only alphabetical? – Matthew Jun 17 '13 at 16:03
  • Duplicate: http://stackoverflow.com/questions/17140393/why-does-a-za-z-match-both-numbers-and-letters?rq=1 – Izkata Jun 17 '13 at 16:08
  • 1
    Actually, your "problem" gives me an empty array; it only gives a match when you append `123` at the end. – Ja͢ck Jun 17 '13 at 16:10
  • @Izkata sorry, It's not. If you'd read carefully you'd have encountered a note, where I was asking about random positions – Yang Jun 17 '13 at 16:10
  • @metal_fan I don't see the difference. Post an example of the "random position" problem mentioned in the comment in the other question (with a `var_dump($matches)`, and explain what's different between it and the output you're expecting). – Izkata Jun 17 '13 at 16:23
  • 1
    @Izkata It cold be argued that this question is more of a continuation of the previous problem rather than the same problem. Also, the accepted answer there wouldn't work here because it would match one slash too many each time it finds one. – Ja͢ck Jun 17 '13 at 16:32

3 Answers3

1

You can append a look-ahead assertion at each replacement:

$pattern = str_replace('(:letter)', '[A-Za-z]+(?=/|$)', $pattern);

The assertion matches either a slash or the end of your URI.

Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
1

The problem example you give is actually not a problem: it doesn't match because the [A-Za-z]+ regex is followed by / in the $pattern string. You probably have problems on the last position. You just need to add something like $ or ([?].*)?$ at the end.

Yang
  • 8,580
  • 8
  • 33
  • 58
ctn
  • 2,887
  • 13
  • 23
0

Have you tried $pattern = /[a-zA-Z]/g

Rachit Doshi
  • 183
  • 1
  • 6