0

I've trying to make my own route class - and I've hot problem with parsing valid url's.

This is an example url: http://localhost/app/module/command/i15

And I need every element after slash / to be an additional element in array creating using preg_match in php.

So - for searching of numbers I've got: ([0-9]+) Searching strings that contains letters, signs like - or _ I've got ([^.]+) (here's the problem)

whole regexp looks like this:

(app)\/(module)\/([^.]+)\/i([0-9]+)

i want an array of 5 elements, something like that:

0 => app, 1=> module, 2 => command, 3 => i15

It will be more beauty if preg_match will return only something like that:

0 => app, 1=> module, 2 => command, 3 => 15 (without I as param identifier)

Can anyone quick help me with this ? I stuck 2 days in that, and can't find right solution.

EDIT: I've got some regexp predefined like:

/app/contacts/list => (app)\/(contacts)\/([^.]+)
/app/contacts/edit/i15 => (app)\/(contacts)\/([^.]+)\/i([\d]+)
/app/contacts/view/i15-c2 => (app)\/(contacts)\/([^.]+)\/i([\d]+)-c([\d]+)

And for all of those I prepare different regexp like above. Problem stars when I need to parse something between:

/app/contacts/preview/random-name/i15-c2 

or

/app/contacts/preview/random-name-i15-c2

([^.]+) catches also \ (slash) - and in above first example this slash broke whole regexp :-(

EDIT SECOND TIME :-)

I've got some predefined regexps for some paths. Lets have a look:

$regexp = [
    [0 => '(app)\/([^/]+)'],
    [1 => '(app)\/([^/]+)\/i([0-9]+)']
];

Next i check current url and match the best result - I know what I want, but php doesn't know what user select so:

if I enter url with path:

app/username/i15

System shows me that $regexp[0] is best result - what it is not true, because $regexp[1] are the best.

I hope this explains my problem.

  • Possible duplicate of [How do you parse and process HTML/XML in PHP?](https://stackoverflow.com/questions/3577641/how-do-you-parse-and-process-html-xml-in-php) – Nic3500 Nov 23 '17 at 12:22
  • yeah, dont make your own route class. Just use nikic/fastroute. – Gordon Nov 23 '17 at 12:33
  • @Gordon I make my app not like other MVC (route > controller) - so this could not be helpful. My route redirect to file with special parameters. EDIT: find half solution [^/]+ Maybe I've try to show u all my problem In example. – Grzegorz Miśkiewicz Nov 23 '17 at 12:41

2 Answers2

1

Since you're using groups to capture in your regex, you can use them to create your desired array. Pass a variable to preg_match() to store the groups:

$components = [];
preg_match('#(app)/(module)/([^.]+)/i([0-9]+)#', $uri, $components);

Now the first element of $components is the whole match, and then the groups.

array_shift($components); # discard first element
sidyll
  • 57,726
  • 14
  • 108
  • 151
  • Thank You - I've got this, but in routing I've check also other paths - so if path will be defined for example: app/module/list - this above doesn't work - because on last array element I've gather list/i15 – Grzegorz Miśkiewicz Nov 23 '17 at 12:31
  • You'd need to modify your regex accordingly to make some parts optional, if I got it right. Or, go with a completely different strategy: split the uri on `/` and then analyse each component separately. I've used this in very simple scenarios of custom routers. For anything more complex than that, it's worth investigating how a bigger router works or just use it in your project, like [nikic/FastRoute](https://github.com/nikic/FastRoute) – sidyll Nov 23 '17 at 12:38
  • I analyse code of fast route - and find solution that helps only in half way: [^/]+ - but when I calculate percentage of match - this show's me not right regexp. – Grzegorz Miśkiewicz Nov 23 '17 at 12:44
  • @GrzegorzMiśkiewicz I see the edited content in the question. I'm sorry, it's difficult to me to help in this case without seeing the whole code and situation. But if here goes my 5¢ if I were to implement this myself: split the uri in `/` and grab the first element that changes, like the second or third. Then pass the rest of the components to the proper controller or function call which will analyse the other parameters and decide what to do. This way, step by step, might be easier and more efficient than using regex to parse since the beginning. – sidyll Nov 23 '17 at 12:54
0

Ok heres class for my routing: https://gist.github.com/djmassive/d7487cef92e3adb1abf7ca31d3e96a53

Whole magic are done in method parse()

I've adding routings:

$route->get('(app)\/:string', [ 'schema' => '2', 'module' => 'system', 'file' => 'profile' ]);
$route->get('(app)\/:string\/i:id', [ 'schema' => '2,3', 'module' => 'system', 'file' => 'profile', 'command' => 'view' ]);
  • schema define what I want to be na id - it can be int, string or array.
  • module is folder name
  • file is filename
  • command is command use in file for show directly what I want

If I had url: app/list - system reads it like that: $command is list (schema shows second element) - works

app/username/i15 $command should be view $id should be [ username, 15 ]

in this case, first regexp is showing 66% of match like second one - but second one should be 100%

Have a look at debuging:

Checking regexp: #(app)\/([^/]+)# - to match path: app/username/i15
Results preg_match \$matches array:
Array ( [0] => app/username [1] => app [2] => username )
Percentage match: 66.6666666667%

Checking regexp: #(app)\/([^/]+)\/i([\d]+)# - to match path: app/username/i15
Results preg_match \$matches array:
Array ( [0] => app/username/i15 [1] => app [2] => username [3] => 15 )
Percentage match: 66.6666666667%

we see, that first regexp are not good because there are not third element.

From what I know, the whole problem is mainly to not return what does not meet the full condition.