How to create a permalink system with PHP and MySQL

So, I was digging up some information on how to create a permalink system with PHP and MySQL to use in my other website and I've found some really interesting information.

I will show you now what I came up with.

The problem

If you use PHP to build your website, chances are that your project has a lot of dynamically generated pages. In my case, I have a website which contains a section to articles written by its users and, to properly put together the page, each address is direct at a php page that receives a number os parameters, such as the article ID which will be sought in my MySQL database.

It is something like this:

http://www.example.com/articles.php?articleID=4

Why would you want a different URL?

First, I personally believe that visitors of my website would rather click on a link with lots of keywords of their interest than clicking on a generic link with some stranger variables and characters. It also seems neater this way.

In addition to that, according to my quick research on the Internet, links that contain keywords are more likely to be better ranked in search engines and, therefore, this could also be a SEO optimization.

If your website is already well ranked in search engines, though, I would not recommend this change, since you will lose your ranking if your URL changes.

The solution

Then, how I can implement this? Follow the step-by-step below:

1. Creating a URL shortening function

First, you will need to have a PHP function to correctly codify the address you will use. In my case, I have used each article title as the new URL, as follows:

http://www.example.com/name-of-my-article-goes-here
I quickly found a great function written in cubiq.org, and adapted it to ISO-8859-1, since my mother language is Brazilian Portuguese. The PHP function follows below:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<?php
function toAscii($str, $replace=array(), $delimiter='-') {
        setlocale(LC_ALL, 'en_US.UTF8');
 if( !empty($replace) ) {
  $str = str_replace((array)$replace, ' ', $str);
 }
 $clean = iconv('ISO-8859-1', 'ASCII//TRANSLIT', $str);
 $clean = preg_replace("/[^a-zA-Z0-9\/_|+ -]/", '', $clean);
 $clean = strtolower(trim($clean, '-'));
 $clean = preg_replace("/[\/_|+ -]+/", $delimiter, $clean);
        setlocale(LC_ALL, 'pt_BR', 'pt_BR.utf-8', 'pt_BR.utf-8', 'portuguese');
 return $clean;
}
?>

This function simply takes a string (say, the article title) and convert it to a human-readable though browser-amicable string.

2. Limiting the number of words that your new address will have

Since I have no control over what other will name their articles, I have decided to impose a 10-word limitation to such new addresses' strings. To do that, I used the PHP function below:


1
2
3
4
5
6
<?php
function limitWords($string, $word_limit){
    $words = explode(' ', $string);
    return implode(' ', array_slice($words, 0, $word_limit));
}
?>

This simple function just get your string and returns it with the proper word count.

3. Generating the correct address

You will need to correctly generate this new address based on the article title (let's call it "alias") and store it somewhere in your database. In my case, I have created a new column in by MySQL article table, called "alias", type TEXT.

In the page in which the user creates the content and then stores the respective value in the MySQL table, I now need to correctly format this string to input it in the alias field. This is what I did:


1
2
3
<?php
$alias = date("Y")."/".date("m")."/".date("d")."/".toAscii(limitWords(utf8_decode($title),10));
?>

In my case, I used the Year, month and date of the article creation (that is, now) and converted the title with the "toAscii" function after limiting my string to 10 words.

After that, I only need to insert this value in my database along with the other elements I was already recording.

4. Preparing the PHP page that will show the article

After this setup, now is time to prepare the page which will show the article (in my case, articles.php). In the articles.php page, I included the following snipped before any other searches:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<?php
$dbhost = "FILL THIS";
$dbuname = "FILL THIS";
$dbpass = "FILL THIS";
$dbname = "FILL THIS";
$connect = mysqli_connect($dbhost,$dbuname,$dbpass, $dbname) or die("Unreacheable Database!");

if($_GET['url'] !== ""){
    $q = "SELECT articleID from articles WHERE art_alias = '".$url."'";
    $query = $connect->query($q);
    $rec = mysqli_fetch_array($q);
    if(isset($rec['articleID'])&&($rec['articleID'] !== "")){
        $aId = $rec['articleID'];
    }
}
?>

Our intention here is to check in our database the corresponding articleID field for the alias we have created. Our alias will be provided as a GET parameter named "url".

In principle, would be the same as calling an address like this:

http://www.example.com/articles.php?url=your-alias-here

5. Finally, the .htaccess

In order to have our webpage correctly showing only your alias and redirecting to the dynamically generated content website, we will need to change the .htaccess file of your server. If you have an external host, chances are that you already have this in place and will only need to adjust it to our code below.

This is what I did in this file:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<?php
# Apache Rewrite Rules
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ^/?article/([a-zA-Z0-9-/]+)$ articles.php?url=$1
  RewriteRule ^/?article/([a-zA-Z0-9-/]+)/$ articles.php?url=$1

# End of Apache Rewrite Rules
 </IfModule>

With this, our url will finally be accessible as in the example below:

http://www.example.com/article/2015/08/22/my-article-title-here

Of course, you will need to update all links to your article to go to such alias structure. Note that I have also included the "article" portion in the path. To use that, note that you can't have a article.php file or something like that or htaccess will conflict with that, not redirecting your page.

And that's how I did it. Do you have any suggestions on how to improve this? Leave your comments below.