Create blog post links similar to a folder structure - php

I am currently working on a blog where I would like to create links to my individual articles in the following form:
http://www.mysite.com/health/2013/08/25/some-random-title
------ -----------------
| |
category title
However I have no idea how to achieve this.
I have found something that would give me the URI.
$uri = $_SERVER["REQUEST_URI"];
I would then go ahead and extract the needed parts and make requests against the database.
This may seem a very very dumb question, but I do not know how to look this up on google (I tried...) but how exactly am I going to handle the link ?
I try to explain it step-by-step:
User clicks on article title -> the page reloads with new uri --> Where am I supposed to handle this new uri and how ? If the request path looked like this:
index.php?title=some-random-article-title
I would do it in the index.php and read the $_GET array and process it accordingly. But how do I do it with the proposed structure at the beginning of this question ?

You will need a few things:
Setup an .htaccess to redirect all request to your main file which will handle all that, something like:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
The above will redirect all request of non-existent files and folder to your index.php
Now you want to handle the URL Path so you can use the PHP variable $_SERVER['REQUEST_URI'] as you have mentioned.
From there is pretty much parse the result of it to extract the information you want, you could use one of the functions parse_url or pathinfo or explode, to do so.
Using parse_url which is probably the most indicated way of doing this:
$s = empty($_SERVER["HTTPS"]) ? '' : ($_SERVER["HTTPS"] == "on") ? "https" : "http";
$url = $s . '://' . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
var_dump(parse_url($url));
Output:
["scheme"] => string(4) "http"
["host"] => string(10) "domain.com"
["path"] => string(36) "/health/2013/08/25/some-random-title"
["query"] => string(17) "with=query-string"
So parse_url can easily break down the current URL as you can see.
For example using pathinfo:
$path_parts = pathinfo($_SERVER['REQUEST_URI']);
$path_parts['dirname'] would return /health/2013/08/25/
$path_parts['basename'] would return some-random-title and if it had an extension it would return some-random-title.html
$path_parts['extension'] would return empty and if it had an extension it would return .html
$path_parts['filename'] would return some-random-title and if it had an extension it would return some-random-title.html
Using explode something like this:
$parts = explode('/', $path);
foreach ($parts as $part)
echo $part, "\n";
Output:
health
2013
08
25
some-random-title.php
Of course these are just examples of how you could read it.
You could also use .htaccess to make specific rules instead of handling everything from one file, for example:
RewriteRule ^([^/]+)/([0-9]+)/([0-9]+)/([0-9]+)/([^/]+)/?$ blog.php?category=$1&date=$2-$3-$4&title=$5 [L]
Basically the above would break down the URL path and internally redirect it to your file blog.php with the proper parameters, so using your URL sample it would redirect to:
http://www.mysite.com/blog.php?category=health&date=2013-08-25&title=some-random-title
However on the client browser the URL would remain the same:
http://www.mysite.com/health/2013/08/25/some-random-title
There are also other functions that might come handy into this for example parse_url, pathinfo like I have mentioned early, server variables, etc...

This is called Semantic URLs, they're also referred to as slugified URLs.
You can do this with the .htaccess command RewriteURL
Ex:
RewriteURL ^(.*)$ handler.php?path=$1
Now handler.php gets /health/2013/08/25/some-random-title and this is your entry point.

Related

Is there a function or way to do in PHP similar how this works in Node JS?

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

Extract URL slug using PHP. Building a URL shortener

I'm building a URL shortening web app using PHP. I am able to generate shorter URLs successfully. But I'm not able to redirect the users when they visit the shortened URL.
If the user enters https://example.com/aBc1X, I'd like to capture the aBc1X. I'll then query the database to find the original URL and then redirect.
My question is, how can I extract the aBc1X from the above URL?
P.S. I'll use either Apache or Nginx.
Two things to do for you.
First you have to redirect all traffic to one file which will be your router file. You can do this by placing a few rules in .htaccess file. I will put there some generic rules to start with (this one come from Wordpress):
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^redirect\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /redirect.php [L]
</IfModule>
They tell that everywhere url points to which isn't file or directory will run file redirect.php. You may want to tweak that settings to your needs.
Then in redirect.php you can capture url by looking inside $_SERVER['REQUEST_URI'].
For url http://example.com/any-url-i-want you would have
$_SERVER['REQUEST_URI'] == '/any-url-i-want.
Now the only thing you need is to find the url in database, and do a redirect.
I guess you can handle string operations at this point, either by using parse_url, regular expressions, or simple string cutting.
You want to use;
$_SERVER['REQUEST_URI'];
That will return what you're looking for.
You can see the documentation here
To parse the url
$url = "https://example.com/aBc1X";
$path = ltrim(parse_url($url, PHP_URL_PATH), '/');
Then $path will be aBc1X as desired. Note that any query following a ? will be omitted in this solution. For more details have a look at the documentation of the parse_url function.

PHP File request from url directory

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.

Creating dynamic URLs in htaccess

I'm trying to write an .htaccess file that will make my URLs more attractive to search engines. I know basically how to do this, but I'm wondering how I could do this dynamically.
My URL generally looks like:
view.php?mode=prod&id=1234
What I'd like to do is take the id from the url, do a database query, then put the title returned from the DB into the url. something like:
/products/This-is-the-product-title
I know that some people have accomplished this with phpbb forum URLs and topics, and i've tried to track the code down to where it replaces the actual URL with the new title string URL, but no luck.
I know I can rewrite the URL with just the id like:
RewriteRule ^view\.php?mode=prod&id=([0-9]+) /products/$1/
Is there a way in PHP to overwrite the URL displayed?
At the moment you're wondering how to convert your ugly URL (e.g. /view.php?mode=prod&id=1234) into a pretty URL (e.g. /products/product-title). Start looking at this the other way around.
What you want is someone typing /products/product-title to actually take them to the page that can be accessed by /view.php?mode=prod&id=1234.
i.e. your rule could be as follows:
RewriteRule ^products/([A-Za-z0-9-])/?$ /view.php?mode=prod&title=$1
Then in view.php do a lookup based on the title to find the id. Then carry on as normal.
One way to do it, would be just like most mvc frameworks. You can redirect all your pages to the same index.php file, and you use your script to determine which page to load.
.htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [L]
</IfModule>
and your php file will have a script like this one:
// get the url
$uri = (isset($_SERVER['REQUEST_URI']))?$_SERVER['REQUEST_URI']: false;
$query = (isset($_SERVER['QUERY_STRING']))?$_SERVER['QUERY_STRING']: '';
$url = str_replace($query,'',$uri); // you can edit this part to do something with the query
$arr = explode('/',$url);
array_shift($arr);
// get the correct page to display
$controller =!empty($arr[0])?$arr[0]:'home'; // $arr[0] could be product/
$action = isset($arr[1]) && !empty($arr[1])?$arr[1]:'index'; // $arr[1] can be product-title
}
of course you will have to work this code to fashion your application
I hope this helps
One way would be to output a Location: header to force a redirect to the chosen URL.

how do I create the following .htaccess file

I have written the following code in my .htaccess file
Options +FollowSymLinks
RewriteEngine on
RewriteRule page/(.*)/ index.php?page=$1&%{QUERY_STRING}
RewriteRule page/(.*) index.php?page=$1&%{QUERY_STRING}
The url "xyz.in/index.php?page=home" will look like this in the address bar of browser "xyz.in/page/home"
If I want to pass a variable through URL than I will have to write as "xyz.in/page/home?value=1" or "xyz.in/page/home?value=1&value2=56&flag=true"
The initial part of url (xyz.in/page/home) is clean(search engine friendly), but if I pass some more variables in the url then it doesn't look nice.
I want to make this url like
"xyz.in/page/home/value/4/value2/56" and so on.
The variables value and value2 are not static they are just used for example over here. Name can be anything.
Is it possible to do this ?
Please help me form the ".htaccess" file
(any corrections related to title or language or tags used in this question are welcome)
Thanks
The easiest would be to parse the URL path with PHP. Then you would just need this rule to rewrite the requests to your PHP file:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule !^index\.php$ index.php [L]
The condition will ensure that only requests to non-existing files are rewritten.
Your PHP script could than look like this:
$_SERVER['REQUEST_URI_PATH'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$segments = explode('/', ltrim($_SERVER['REQUEST_URI_PATH']));
for ($i=0, $n=count($segments); $i<$n; $i+=2) {
$_GET[rawurldecode($segments[$i])] = rawurldecode($segments[$i+1]);
}

Categories