Regular expression for exploding route in Laravel4 - php

How to explode a laravel
Route::getCurrentRoute()->getActionName() // IndexController#getRegister
Into array of: namespace, controller, method, action
I created the expr:
(.*)\\(.*)Controller#(get|post|put|delete|patch)(.*)
But it doesnt work for all of routes
Admin\IndexController#getIndex
Admin\IndexController#postIndex
Other\Namespace\Admin\IndexController#putIndex
Admin\IndexController#deleteGetAjaxSuper
Admin\IndexController#patchIndex
IndexController#getRegister
Other_IndexController#getRegister
IndexController#getRegister
IndexController#getRegister
http://regexr.com?389rh
It doesnt work for last 4 items.

It isn't matching the last 4 items because the items do not contain a \ before the controller. Your regexp requires them to have it, and as such does not match it. The answer is to make the initial slash optional by using a ? (=0 or 1 occurrence), like so:
(.*)\\?(.*)Controller#(get|post|put|delete|patch)(.*)
On a sidenote, are you sure that a Controller have no specific name? ie. a controller just called "Controller" will match your regexp as well. To disallow that (and only allow [something]Controller) you can change the 2nd .* to .+ (so from 0 or more matches to 1 or more matches). Like so:
(.*)\\?(.+)Controller#(get|post|put|delete|patch)(.*)
And the same thing for your method (get|post|etc.):
(.*)\\?(.+)Controller#(get|post|put|delete|patch)(.+)

Assuming you will not have any space around there before the Controller
\S+Controller#(get|post|put|delete|patch)(.*)
using .* instead of \S+ will work as well.

Related

PHP preg match ALL between two strings and return everything but the two string

I have a string like this;
....className="someclass another_class" ... className="someclass1"
I want to capture all class names to end up with something like this.
someclass another_class
someclass1
I tried the following.
preg_match_all('#className="(.*?)"#',$string,$m_6df);
var_dump($m_6df[0]);
But then each class includes "className=" and '"' in it, like
'className="someclass"';
instead of just
'someclass';
You need to check the 1 group, not 0. The zero index is the whole matching pattern. 1 is the first capture group.
preg_match_all('#className="(.*?)"#','className="someclass another_class" ... className="someclass1"',$m_6df);
var_dump($m_6df[1]);
Demo: https://eval.in/534119

regex matching url

In PHP, the klein routing will match as many routes as it can.
2 routes I have set up are conflicting. They are:
$route1: '/websites/[i:websiteId]/users/[i:id]?'
and
$route2: '/websites/[i:websiteId]/users/[a:filename].[json|csv:extension]?'
This is the URL I'm trying to match, which I think should match the first and not the second, is:
/api/v1-test/websites/100/users/4
The regex produced for these two are:
$regex1: `^/api(?:/(v1|v1-test))/websites(?:/(?P<websiteId>[0-9]++))/users(?:/(?P<id>[0-9]++))?$`
$regex2: `^/api(?:/(v1|v1-test))/websites(?:/(?P<websiteId>[0-9]++))/users(?:/(?P<filename>[0-9A-Za-z]++))(?:\.(?P<extension>json|csv))?$`
I mean for it not to match if there is no '.csv' or '.json'. The problem is that it is matching both routes. For the second, the resulting filename is '4' and the extension is blank.
Sending /api/v1-test/websites/100/users/users.csv works correctly and only matches the second route.
I only have control over the route, not the regex or the matching.
Thanks.
This bit here
(?:\.(?P<extension>json|csv))?
at the end of your second regex causes it to match whether or not there's a filename due to the ? at the very end. Question marks mean 0 or 1 of the previous expression. Get rid of that and, at the least, strings will only match this regex when they have the extension.
To make this change, just remove the question mark from your second route, like so:
$route2: '/websites/[i:websiteId]/users/[a:filename].[json|csv:extension]'
The problem is that the match_type is defined really... weirdly:
$match_types = array(
'i' => '[0-9]++',
'a' => '[0-9A-Za-z]++',
[...]
As such, you can't really capture a sequence corresponding to [a-zA-Z] only... The only option I see would be to use 3 routes:
$route1: '/websites/[i:websiteId]/users/[i:id]?'
$route2: '/websites/[i:websiteId]/users/[a:filename]'
$route3: '/websites/[i:websiteId]/users/[a:filename].[json|csv:extension]'
And to assign the same actions for routes 2 and 3. Then you would have this:
/api/v1-test/websites/100/users/ is matched by 1
/api/v1-test/websites/100/users/4 is matched by 1
/api/v1-test/websites/100/users/test is matched by 2
/api/v1-test/websites/100/users/test.csv is matched by 3
Which seems like the behavior you wanted.
Abother (easier) solution would be to take advantage of this bit of the documentation:
Routes automatically match the entire request URI.
If you need to match only a part of the request URI
or use a custom regular expression, use the # operator.
You can then define your routes like this:
$route1: '#/websites/[0-9]+/users/[0-9]*$'
$route1: '#/websites/[0-9]+/users/[a-zA-Z]+(\.[a-zA-Z]+)?$'

RegEx with character set inside positive lookbehind, Is it possible?

I need to match "name" only after "listing", but of course those words could be any url directory or page.
mydomain.com/listing/name
so the only thing I can "REGuest" (request) is to be some parent directory there.
In other words, I want to match the "position" i.e. whatever comes 2nd after the domain.
I'm trying something like
(?<=mydomain\.com/[^/\?&]+/)[^/\?&]+(?:/)?
But the character set won't work inside the positive lookbehind, at least it's setup to match only ONE character. As soon as I try to match other than one (e.g. modify it with +, ? or *) it just stops working.
I'm obviously missing the positive lookbehind syntax and it seems not intended for what I'm trying.
How can I match that 2nd level filename?
Thanks.
Regular-expressions.info states that
The bad news is that most regex flavors do not allow you to use just
any regex inside a lookbehind, because they cannot apply a regular
expression backwards. Therefore, the regular expression engine needs
to be able to figure out how many steps to step back before checking
the lookbehind...
(Read further, they even mention Perl, Python and Java.)
I think the quantifier might be the problem. I found this on stackoverflow and briefly flew over it.
Wouldn't it be possible to just match the whole path, and use a group for the second level filename:
mydomain\.com\/[^\/\?&]+\/([^\/\?&]+)(?:\/)?
(note: I had to escape the / for my tests...)
The result of this would be something like:
Array
(
[0] => mydomain.com/listing/name
[1] => name
)
Now, because I don't know the context of your problem, I just assumed you would be able to postprocess the results and get the group 1 (index 1) from the result. If not, I unfortunately don't know...

getting url to work with or without a subexpression

im trying to rewrite a url like
page.php?sort=66&search=s&category=2,3,4&archive=june&page=3
to
page-sort-1-search(s)-category-1,2,3-archive(june)-page3
but the thing is each of this subexpressions my or may not be in the url every time that this page is called so i had to put each one in the "( )?" so the regex works with or without them
^page
(-sort-([0-9]*))?
(-search\(([a-z]*)\))?
(-category-([0-9][,]?*))?
.............
you get the idea
now the problem is mode rewrite is considering each one of this subexpression in the parenthesis as an actual variable
(-sort-([0-9]*))? this is how mode rewrite interpret this => $1 = -sort-66 , $2 = 66
so for each subexpression i got 2 capture-group and that's more then 10 for a link with 5-6 variable
and there is a 9 match limit in mode rewrite
is there a replacement for "()?"
I have to admit, I'm a bit confused by some parts of your question, so I apologize in advance if my answer is totally off-base . . . but it sounds like what you need is a non-capturing group. This:
(...)
matches ... and creates a capture-group (what you're calling a "variable"); this:
(?:...)
just matches ..., without creating a capture-group. So it's useful if all you want to do is group a subexpression, without saving all of its contents to be used as $1.

Using Regular Expressions in a PHP Framework

I've got a university project to create a site using a framework given to us by the teacher. I've hosted the site at http://daniel-lucas.com so you can see what's happening.
As you can see the address ends with /?index.
In the configuration file I've just used :
new UrlMapping('^index/$', 'musiconlineapp.listeners.MainListener.handle', 'musiconlineapp/views/MainView.php')
The first parameter is the address to map. The second is the controller for the page and the method to load in the controller (handle). The third is the view to display for the page.
However I'm having trouble displaying categories for the site. I was told to use mapping like this:
new UrlMapping('^category/(?P<cat>\w+)/$', 'musiconlineapp.listeners.CategoryTitleListener.handle', 'musiconlineapp/views/CategoryTitleView.php' )
My problem is that I've not done any regex for a while and can't figure out what address I'm supposed to go to when I click on the link.
I've tried /?category&cat=rock and similar variations but none of them work.
That regex looks like it's supposed to match /?category/rock/ or the like.
^ # beginning of string
category/ # literal 'category/'
(?P<cat> # named matching group (named 'cat')
\w+ # one or more word characters a-zA-Z0-9_
) # end the named matching group
/ # literal '/'
$ # end of string

Categories