Im trying to compile a regular expression to match a URL in the following form:
http://www.example.com/param_1/param_2/.../param_n/?var_1=val_1&var2_=val_2&...val_n=var_n
In other words, the URL would have several subdirectories (param_1 - param_n) that need to be matched explicitly, and an unknown number of GET variables that need to be carried along with the URL without invalidating the match.
(Ive seen other topics for matching one, or two, or three GET variables but none for a general regex expression matching multiple variables who's total number is unknown)
I have the following Regex working for the following URL:
URL: http://www.example.com/users/john/
REGEX: "users\/john\/([a-z|A-Z|0-9|-]+)([\/]{0,1})\/([a-z|A-Z|0-9|-]+)([\/]{0,1})$/"
RESULT: MATCH!! :)
But the addition of "GET" variables (http://www.example.com/users/john/?car=blue) does not lead to a match (obviously).
I am not a regex guru and pretty sure what I have working probably isn't very elegant to begin with, but I have had no luck at all making it work with additional variables.
I am matching patterns in the following way:
$routes = array(~~ REGEX => controller script ~~);
foreach($routes as $pattern=>$ctrl){
if(preg_match($pattern, URI)) {
echo 'MATCH!!';
break;
}
}
First extract all params and all key-vals separately:
key-vals vvvv
^https?:\/\/[^\/]+((?:\/[^?]+)*)?(?:\?(.+))?$
^^^^^^^^^^^^^^^ params
For the example url, params = /param_1/param_2/.../param_n and key-vals = var_1=val_1&var2_=val_2&...val_n=var_n.
If params were extracted, get each individual param (use global to get every one):
\/([^\/]+)
^^^^^^^^ individual param
If key-vals were extracted, get each individual key and value (also use global):
vvvvvvv value
([^=]+)=([^&]+)
^^^^^^^ key
Sorry I can't help with the PHP, but this should point you in the right direction.
Thank you for your replies! The following regex ended up working for me:
/^\/param_1\/param_2\/...\/param_n\/?(\?.*)?$/
Related
I'm having an error I don't understand after searching around the web for a couple hours.
I have an SQL request made through ajax query with POST method, and generated for the different pages of my website, even sometimes with a direct user input.
To avoid SQL injections, I want to check the content of the parameters.
I can't use PDO::quote() because some parameters can contain lists or SQL function : for example : the select parameter can contain c.id_client, c.nom, COUNT(c.id_client)...
To prevent SQL injection I'm blacklisting some SQL keywords and functions with preg_match_all();
$matches = array();
preg_match_all('"[\w% ]*(add|alter|create|delete|drop|exec|insert|set|table|truncate|update|view)[\w% ]*"[^:]', $inputs, $matches);
In the case I'm testing, $inputs is the json_encoded post array :
{"select":"c.id_client, c.prenom, c.nom, c.email, COUNT(t.actif) AS nombre_licences","from":"clients","as":"c","inner":{"1":{"cond":{"1":{"join_in":"cl.id_client","join_out":"c.id_client"}},"table":"clients_licences","as":"cl"},"2":{"cond":{"1":{"join_in":"t.id_client_licence","join_out":"cl.id_client_licence"},"2":{"join_in":"t.actif","join_out":"1"}},"table":"terminaux","as":"t"}},"where":{"1":{"index":"CONCAT_WS('', c.prenom, c.nom, c.email, c.siren)","operand":"LIKE","value":"%necas%"}},"group":{"1":{"index":"c.id_client"}},"order":{"1":{"index":"c.nom"},"2":{"index":"c.id_client"}},"offset":"0","limit":"3","resultFormat":"<tr class=\"result\"><td>$$id_client##<\/td><td>$$nom## $$prenom##<\/td><td>$$email##<\/td><td>$$nombre_licences##<\/td><td><button class=\"btn btn-xs btn-success\" onclick=\"location.href='\/admin\/view\/$$id_client##'\" ><i class=\"fa fa-search\" aria-hidden=\"true\"><\/i> Voir<\/button><\/td><\/tr>"}
And then I get :
$matches = [[], []]
I tested this a couple times on different regex testers like regex101 without getting any match...
Please note that I can't modify this code too much.
Thanks for the help, Jm56Z
_
EDIT:
It seems like preg_match_all() sets $matches to an array containing two times the matches array :
$matches = [[matches], [matches]]
Solution :
preg_match_all() puts all matches in a multidimentional array even if it doesn't find any.
By default :
[[matches of the full regex], [matches of group 1], [matches of group 2]...]
Next time I'll read documentation with more attention.
https://php.net/manual/fr/function.preg-match-all.php
It seems the regex itself is wrong. For the given JSON sample, please try:
"(add|alter|create|delete|drop|exec|insert|set|table|truncate|update|view)[\w% ]*":
I'm building a small restful api and I'm asking if it's possible to seperate the url to php file and the end of the url.
E.g. www.mydomain.com/api/parameter/1/2/
In this case the php file is adressed with www.mydomain.com/api/ or www.mydomain.com/api/index.php and parameter/1/2/ is the parameter.
I want a CRUD interface so that GET without parameter gets a list of all data. To achieve this I need to check if a parameter is attached and to extract the parameter.
Other example
www.mydomain.com/topics/ => gets all topics
www.mydomain.com/topics/1/posts/ => gets all posts of topic 1,
www.mydomain.com/topics/1/posts/2/ => gets post 2 of topic 1
My question is: Is it possible and how?
You would probably have to read the request URI from the end of the URL using $_SERVER['request_uri']. This would return /api/parameter/1/2. You could then substring it if the length is reliable, or use a regex with preg_match to get just the parameter section. e.g.
preg_match("parameter\/.*", $_SERVER['request_uri'], $matches)
would return either the string parameter/1/2 in the $matches variable, or false if no match was found
But yeah like others are saying, you're probably better using GET parameters if you can, and just do a check using isset() to see if there are any parameters.
can anyone help me to piece together the puzzled I'm facing. Lets say I have url's
/some-work/
/store/bread/alloy/
and in both of these cases I wanna fetch the first part from it. i.e. some-work, store.
Now I've used parse_url(get_permalink()) to get the array of the url and then fetch the path index of the array to fetch the above string. Now I have also checked strstr PHP function, but I am unable to make it work. Can anyone help?
You can use explode, array_filter and current function like as
$url = "http://www.example.com/some-work/";
$extracted = array_filter(explode("/",parse_url($url,PHP_URL_PATH)));
echo current($extracted);//some-work
Demo
I have a long PHP file and I want to copy all the variable names only and build an insert sql query. Is there a way where I can search for a pattern using regular expression and concatenate the find result till I collected all the variable and spit it out in a statement?
I am using TextMate and am familiar with regular expression search. Regex search result give $0,$1 and so forth argument. Do not know if this possible though. Solution in any editor will do not just text mate.
I have just too many variable (+100) don't feel like copy every single one. Here my sample file
$ID = $_POST['id'];
$TXN_TYPE = $_POST['txn_type'];
$CHARSET = $_POST['charset']
$CUSTOM = $_POST['custom'];
You could try something with get_defined_vars(). However this function also lists GLOBAL vars. You can use this snippet to remove them if you don't want them and display only the vars you defined
$variables = array_diff(get_defined_vars(), array(array()));
However this snippet generates Notices and I haven't found a way to solve them yet.
If you've only got $_POST variables you can loop through the $_POST array itself
You create the SQL programmatically while looping through the array.
My own solution is, do the inverse. It is not probably possible.
Leave only the variable names Remove all the rest. Use
[space].+ regex to remove everything that is after the variable name.
clean the file so that only variable names are left. then do a couple more find and replace to bring the variable name in the form you want.
If you're looking to match only the variable names (not the $_POST array indices), then the regular expression is pretty much provided in the PHP documentation:
\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*
This will, of course, include $_POST, but that should be easy enough to remove. If not, you could do it with negative lookahead (if TextMate supports it):
\$(?!_POST($|[^a-zA-Z0-9_\x7f-\xff]))[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*
can anyone help me to play with GET urls for example I have a link like this:
?id=5&lang=1
So my question is how can I make this one:
?id=5,1
I don't want to show the &lang, only I want is that the &lang to replace with , "comma" can anyone help me?
You can use mod_rewrite to rewrite ?id=5,1 to ?id=5&lang=1 internally.
Otherwise, the value of id will be 5,1. Your application would then need to know that id contains more than the id. It could then parse out the language from the id. However, this will become confusing when you introduce more parameters.
Assuming you have already built the URL in the way you have specified, you can break the id field based on the comma and extract the real id and lang field
$urlPieces = explode(",", $_GET['id']);
$id = $urlPieces[0];
$lang = $urlPieces[1];
You are able to do this, but it's not very clean, in terms of the proper $_GET variable values. The solution automatically type casts the values to integers:
sscanf($_GET['id'], '%d,%d', $id, $lang);
// $id = int(5)
// $lang = int(1)
Two solutions:
Firstly, you could simply reformat the parameters when they arrive in your PHP program. With ?id=5,1, you'll get a PHP $_GET array with id '5,1'. This you can simply split using the explode() function to get the two values you want.
The second solution is to use the Apache mod_rewrite feature, to modify the URL arguments before they arrive at PHP. For this, you'll need to understand regular expressions (regex), as mod_rewrite uses this for it's work. You should google 'mod_rewrite' and 'regex' to find out more.
However mod_rewrite is typically used to get rid of GET arguments entirely. For example the URLs of the questions on this site do not have any get arguments, but the server translates the arguments between the slashes into GET arguments. This is considered better practice than simply than changing how the arguments look, as it is more user-friendly and SEO friendly.
Hope that helps.
$id = $id . ',' . $lang;
<a href="?<?php echo $id; ?>">