Given this path: /page(/:pageID), how can I allow the following variations:
/page and /page/ (even if the pageID part is missing.
/page/1 and /page/1/
Thank you.
You must define your route this way:
$app->get('/page(/:id/?)', function ($id = NULL) use ($app) {
; // your code
});
The answer provided by #inst would not work here (Slim 2.0.0 running on XAMPP): /page/ gives out a 404.
This works in all four cases though:
$app->get('/page(/)(:id/?)', function ($id = NULL) use ($app) {
echo 'success';
});
As stated in the documentation, optional segments may be unstable depending on the usage. For example, with the answer given by Fabien Snauwaert, and the following routes:
/:controller(/)(:action(/)(:overflow+/?))
/:controller(/)(:action(/:overflow+/?))
If not filled all the arguments, when obtain param values, these will be in a position to the right, resulting in action == controller and overflow == action.
To prevent this, a simple solution is to put the optional slash at the end of the route.
/:controller(/:action(/:overflow+))/?
/:controller(/:action(/:overflow+))(/)
And it is more readable, isn't it?
I can not comment on others answers, so I write here a detail concerning the Igor response.
One "problem" with this approach is that if the user tries to access a page that does not exist, and also do with a trailing slash, will be a 301 redirect to display a 404 page. Maybe a little weird.
I found this way to achive this with Apache mod_rewrite enabled. Snippet of .htaccess
RewriteEngine On
# remove trailing slash
RewriteCond %{HTTPS} off
RewriteRule ^(.+[^/])/$ http://%{HTTP_HOST}/$1 [R=301,L]
RewriteCond %{HTTPS} on
RewriteRule ^(.+[^/])/$ https://%{HTTP_HOST}/$1 [R=301,L]
An example for Slim V3:
/[{param1:[0-9]+}[/[{param2:[0-9]+}[/]]]]
This will cover:
/
/1
/1/
/1/2
/1/2/
Related
In Node we can get an url address with a structure like this /example/:page/:id and we can take the page and id params. Is there a possibility to do something similar using PHP? Or is it only possible using the "?" with all the wanted params after the interrogation point?
I searched for a while and I tried some configurations in the htaccess file. All of them gave some kind of error like 403, 404 or in one of the configurations the intentioned page was loaded but it didn't find the css, js and images files.
Thanks
Edit:
I will put the solution I found here because maybe it can be useful for someone someday. After looking for some routers packages, I saw them instructing to put these lines in the htaccess file:
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*)$ index.php [L,QSA]
I've tried something like this before and it was the one that I mentioned in the question that loaded the page but it didn't find the files like css, js, etc.
So I've decide to check the base url and I saw this was the point where the error was coming. After I changed it, the page loaded as the expected and now it's possible to get the value where the users can put a number and redirect to the page that they want (it's something like a magazine).
You can achieve it many ways.
In Laravel (see Documentation). I think every framework now has routing implemented.
Route::get('example/{page}/{id}', function ($page, $id) {
//
})->where(['page' => '[0-9]+', 'id' => '[a-z]+']);
With Mod-rewrite and then with access through $_GET parameters.
RewriteEngine on
RewriteRule ^example/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/?$ index.php?page=$1&id=$2 [NC]
You can also redirect everything to index.php and there implement your own router. See: Redirect all to index.php using htaccess
RewriteEngine on
RewriteRule ^(.*)$ /index.php?path=$1 [NC,L,QSA]
Something like this could work
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$uri = explode( '/', $uri );
// all of our endpoints start with /person
// everything else results in a 404 Not Found
if ($uri[1] !== 'page') {
header("HTTP/1.1 404 Not Found");
exit();
}
For more reference visit this url
https://developer.okta.com/blog/2019/03/08/simple-rest-api-php
have you tried parse_url()?
it will return and associative array which has all the components in your URL
This is probably a very easy question. Anyway how do you use variables from a url without requests. For example:
www.mysite.com/get.php/id/123
Then the page retrieves id 123 from a database.
How is this done? Thanks in advance!
UPDATE
If i have the following structure:
support/
sys/
issue/
issue.php
.htaccess
home.php
etc.....
With .htaccess file containing:
RewriteEngine On
RewriteRule ^/issue/(.*)$ /issue/issue.php?id=$1 [L]
Why do I have to type:
http://www.mysite.com/support/sys/issue/issue/1234
In order to load a file? When I want to type
http://www.mysite.com/support/sys/issue/1234
also, how do I then retrieve the id once the file loads?
Problem
This is a very basic/common problem which stems from the fact that your .htaccess rule is rewriting a url which contains a directory which actually exists...
File structure
>support
>sys
>issue
issue.php
.htaccess
(I.e. the directory issue and the .htaccess file are in the same directory: sys)
Rewrite Issues
Then:
RewriteEngine ON
RewriteRule ^issue/(.*)/*$ issue/issue.php?id=$1 [L]
# Note the added /* before $. In case people try to access your url with a trailing slash
Will not work. This is because (Note: -> = redirects to):
http://www.mysite.com/support/sys/issue/1234
-> http://www.mysite.com/support/sys/issue/issue.php?id=1234
-> http://www.mysite.com/support/sys/issue/issue.php?id=issue.php
Example/Test
Try it with var_dump($_GET) and the following URLs:
http://mysite.com/support/sys/issue/1234
http://mysite.com/support/sys/issue/issue.php
Output will always be:
array(1) { ["id"]=> string(9) "issue.php" }
Solution
You have three main options:
Add a condition that real files aren't redirected
Only rewrite numbers e.g. rewrite issue/123 but not issue/abc
Do both
Method 1
RewriteEngine ON
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^issue/(.*)/*$ issue/issue.php?id=$1 [L]
Method 2
RewriteEngine ON
RewriteRule ^issue/(\d*)/*$ issue/issue.php?id=$1 [L]
Method 3
RewriteEngine ON
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^issue/(\d*)/*$ issue/issue.php?id=$1 [L]
Retrieving the ID
This is the simple part...
$issueid = $_GET['id'];
In your .htaccess you should add:
RewriteEngine On
RewriteRule ^id/([^/]*)$ /get.php/?id=$1 [L]
Also like previous posters mentioned, make sure you have your mod_rewrite activated.
You have to use a file called .htaccess, do a search on Google and you'll find a lot of examples how to accomplish that.
You will need mod_rewrite (or the equivalent on your platform) to rewrite /get.php/id/123 to /get.php?id=123.
I tried and tried the .htaccess method but to no avail. So I attempted a PHP solution and came up with this.
issue.php
<?php
if (strpos($_SERVER['REQUEST_URI'], 'issue.php') !== FALSE){
$url = split('issue.php/', $_SERVER['REQUEST_URI']);
}elseif (strpos($_SERVER['REQUEST_URI'], 'issue') !== FALSE){
$url = split('issue/', $_SERVER['REQUEST_URI']);
}else{
exit("URI REQUESET ERROR");
}
$id = $url[1];
if(preg_match('/[^0-9]/i', $id)) {
exit("Invalid ID");
}
?>
What you're looking for is the PATH_INFO $_SERVER variable.
From http://php.net/manual/en/reserved.variables.server.php:
'PATH_INFO'
Contains any client-provided pathname information trailing the actual
script filename but preceding the query string, if available. For
instance, if the current script was accessed via the URL
http://www.example.com/php/path_info.php/some/stuff?foo=bar, then
$_SERVER['PATH_INFO'] would contain /some/stuff.
explode() it and work on its parts.
EDIT: Use rewrite rules to map the users' request URLs to your internal structure and/or hide the script name. But not to convert the PATH_INFO to a GET query, that's totally unnecessary! Just do a explode('/',$_SERVER['PATH_INFO']) and you're there!
Also, seeing your own answer, you don't need any preg_mathes. If your database only contains numeric ids, giving it a non-numeric one will simply be rejected. If for some reason you still need to check if a string var has a numeric value, consider is_numeric().
Keep it simple. Don't reinvent the wheel!
Just wondering why no answer has mentioned you about use of RewriteBase
As per Apache manual:
The RewriteBase directive specifies the URL prefix to be used for
per-directory (htaccess) RewriteRule directives that substitute a
relative path.
Using RewriteBase in your /support/sys/issue/.htaccess, code will be simply:
RewriteEngine On
RewriteBase /support/sys/issue/
RewriteRule ^([0-9+)/?$ issue.php?id=$1 [L,QSA]
Then insde your issue.php you can do:
$id = $_GET['id'];
to retrieve your id from URL.
I've been searching all over the web and haven't yet found any solution to this issue. I'm hoping you could shed some light on the situation.
I have my index file set up like this:
<header></header>
<div id="main">
<?php
if(isset($_GET["p"])) $p = $_GET["p"];
else $p = "home";
if(file_exists("pages/{$p}.php")) include("pages/{$p}.php");
?>
</div>
which makes me load my pages with a ?p=contact href.
Say I would like to display a users profile. I'd then create a subfolder in my "pages" folder, making the relative path pages/users/profile.php, thus the href ?p=users/profile&uid=5. But that leaves an ugly URL (as well as SEO rating).
How would I rewrite that URL to look like /users/profile/5?
EDIT:
I've tried the following, resulting in HTTP 500:
RewriteRule ^([^/]*)/([^/]*)$ /?p=$1&uid=$2 [L]
EDIT: My .htaccess file, located directly inside root folder: http://pastie.org/2268239
Line 338 is where I want to achieve this (currently just a comment).
Simplest answer for both your situations would be to add this in your .htaccess file
RewriteEngine on
RewriteCond $1 !^(index\.php)
RewriteRule ^(.*)$ /index.php?$1 [L]
This will redirect all traffic on your domain to your index.php file.
You could then determine what to do in your script using the uri in $_SERVER["REQUEST_URI"]
I achieved the desired effect by adding these three lines:
RewriteRule ^([a-zA-Z]+)$ index.php?p=$1 [L]
RewriteRule ^([a-zA-Z]+)/([a-zA-Z]+)$ index.php?p=$1/$2 [L]
RewriteRule ^([a-zA-Z]+)/([0-9]+)$ index.php?p=$1&uid=$2 [L]
This allows me to access /contact, /users/index and /users/profile/5.
I'm not a php guy, but I tried this with my rewrite.
RewriteRule ^/(.+)/([^/]+)$ /index.php?p=$1&uid=$2 [L]
In this case, for the p parameter, you're looking for all chars up to the last slash, so the first part of this takes anything, otherwise it's going to stop at the first slash (users instead of users/profile).
Then it looks for a slash and keep (not-slash). The (.+) will be greedy, so it will go up to the last slash before the end.
Then it occurred to me the last part doesn't need to avoid slashes. Since the first part is greedy, the explicit / slash is going to BE the last slash. So it's even simpler:
RewriteRule ^/(.+)/(.+)$ /index.php?p=$1&uid=$2 [L]
I like the .+ to require something, at least when first figuring these out. If later you know they can be optional, you can do .*, but usually that ends up being a different page or a different rule.
These rules do expect all urls to be in this format, which is what you're asking. But maybe it's a little too grabby, so it could exclude urls that really have a .htm or .php or whatever.
RewriteRule ^/(.+)/([^.]+)$ /index.php?p=$1&uid=$2 [L]
This looks for anything up to the last slash, then anything without a dot in it. If it has a dot, this won't apply. So if it's a "regular" url, this will leave it alone. This might help with the 404 problem, in case the 404 page is getting caught by this.
I am pretty new to using the RewriteRule, so I am likely missing something obvious, but I have a PHP script that takes URL variables like this:
{baseurl}properties.php?prop=Property-Name
I would like to create RewriteRules so that anyone who types in this script name/variable combo would have their URL rewritten to:
{baseurl}/properties/Property-Name
As well as ensuring that anyone who types in the flat-link url, actually calls the script with the right variable name and value.
I have been referring to this link and I have found related threads:
Mod_rewrite flat links
Mod_rewrite trouble: Want to direct from ?= to a flat link, nothing seems to work
But, I am obviously doing something wrong, as I cannot get this URL to work the way I want. I am currently using the following code, which appears to do nothing (aside from rewriting the URL to include the www, and redirect requests for index.php to the site root):
RewriteEngine ON
RewriteCond %{HTTP_HOST} ^baseurl.com$ [NC]
RewriteRule ^(.*)$ http://www.baseurl.com/$1 [R=301,L]
RewriteRule ^index.php / [R=301,L]
RewriteRule ^properties/([0-9A-Za-z]+)/$ /properties.php?prop=$1
The issue is clearly with the last RewriteRule, assuming nothing above is affecting it. Again, I am likely doing something ridiculous. Can someone please explain what I am doing wrong?
Thanks for your help.
At a quick glance, it appears that you forgot to include the dash in your regular expression and you included trailing slash. Use this instead:
RewriteRule ^properties/([0-9A-Za-z-]+)$ /properties.php?prop=$1
If you look at your rule ^properties/([0-9A-Za-z]+)/$ you see that it needs to end with a forward slash. You can either remove that or make it optional like ^properties/([0-9A-Za-z]+)/?$.
Been stuck on this for ages and tried loads of fixes but just can't get my head around it!
I run a site where the content of the pages are generated based upon a URL. For example:
http://www.mysite.com/http://www.supercheese.com
Would generate a mashup of content from mysite.com and supercheese.com
The .htaccess i use for this (at mysite.com) is:
<ifModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule .* - [L]
RewriteRule assets/.* - [L]
RewriteRule ^(.*)$ test.php?url=$1 [NC,L]
</ifModule>
So basically the second URL is passed in a php string.
My question is this, I need to remove the http:// from the address using .htaccess
E.G. If someone types:
http://www.mysite.com/http://www.supercheese.com
I need it to become:
http://www.mysite.com/www.supercheese.com
Many thanks in advance for taking a look at this. You guys rock.
You can simply use a RedirectMatch
http://httpd.apache.org/docs/2.0/mod/mod_alias.html#redirectmatch
Try with :
RedirectMatch ^/https?://(.*)$ http://www.mysite.com/$1
Edit : you have to put this before rewrite rules
Edit : add / before http
Edit : David is right, take a look a his answer and change your way of writing these urls
It looks to me like the url scheme is inherently problematic.
Using an unencoded colon : in the url - other than following the http to specify the access protocol - seems to make the server think that it is doing authentication of the form http://username:password#hostname/.
I know it doesn't directly answer the question, the solution is to change the url-scheme. ;-(