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.

Accessing appended elements in JQuery

Say that you have just appended an element in JQuery and need to access it. Since your element was non-existent on the page load, you will need to refer the click on an upper existing element with this syntax:

1
2
3
4
5
6
        $(document).on("click", ".targetclass", function(e){ 
        //targetclass is the class of the element you intend to access
            e.preventDefault();
            //do stuff here            
        });

This way, JQuery will access your element regardless it was existent or not on page load.

Preventing a click in beneath element of a link in JQuery

Let's say you have an structure in which an element contains another, and both will trigger a different action when clicked. How do you avoid that the beneath element triggers its action when the above element is clicked?

This div has a click action
This link has a click action

To prevent that, you can assign a class to the inner element, and then adjust your JQuery code as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<script>
$(function(){
    $("#beneathelement").on("click", function(e){
        e.preventDefault();
        if(e.target.className.indexOf("innerclass") < 0){ //this does the trick
            alert('beneath clicked');
        }
    });
    $("#aboveelement").on("click", function(e){
        e.preventDefault();
        alert('above clicked');
    });
});
</script>

<!-- below is the HTML code for the elements -->
<div id="beneathelement">
    <p>This div has a click action</p>
    <a href="#" id="aboveelement" class="innerclass">This link has a click action</a>
</div>

Passing additional variables to ajax with serialize() in JQuery

If you use JQuery and needs to pass a number of variables to a new page by ajax, you are probably familiar with the function serialize(), which gets all inputs in your form and send them to the desired url.

In this post, I will show you how you can add other variables to the data you are sending with serialize.

The snippet below would be my normal approach when using  ajax and serialize:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<script>
$(function() {
    $('#frm').on('submit', function(e){
        if (e.isDefaultPrevented()) return;
        e.preventDefault();
        $.ajax({
            type:"POST",
            url:"/newpage.php",
            data:  $("#frm").serialize(),
            success: function(response){ 
                alert(response);
                break;
                }
        });         
    });
});
</script>

If I need to insert other variables, I would then use serializeArray() instead of serialize, pushing other variables as needed:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<script>
$(function() {
    $('#frm').on('submit', function(e){
        if (e.isDefaultPrevented()) return;
        e.preventDefault();
        var parameters = $("#frm").serializeArray();
        parameters.push({name: 'newvar', value: 'newvalue'}); //insert here what you need       
        $.ajax({
            type:"POST",
            url:"/newpage.php",
            data:  parameters,
            success: function(response){ 
                alert(response);
                break;
                }
        });         
    });
});
</script>

How to create multi language posts in Blogger

Even though Blogger is indeed very user friendly if you need to quickly set up a blog, I was not able to find any plugin or option to have my posts both in English and in my native language (Brazilian Portuguese).

As such, how can you create a multi language post in Blogger?

First, it is worth mentioning that unless you want an automatic half-assed translation, you will need to manually prepare each post in the languages you intend to publish.


Setting up the magic

1. Enable the JQuery support in Blogger, as we mentioned in our post: Adding JQuery support on Blogger

2. As mentioned, you will need to prepare two versions of your post, one for each language. Once you are done, click on the HTML button of your edit post page.



3. You will now divide your post in two sections, using a <div> tag for each block of text, closing the portion of each respective language portion with a </div>. You will also need to include three classes in this <div> tag: a "lang" class, a "lang_" class followed by the letters representing the language you need and, finally, a "posttitle" class which will contain the title of your post in each language. One of such <div> tags will need to have a "display" set to none, or your post will display both languages at once. Complicated? Follow the template below:


1
2
3
4
5
6
<div class="lang lang_EN" posttitle="YOUR POST TITLE IN ENGLISH">
HERE GOES THE ENGLISH PORTION OF YOUR POST
</div>
<div class="lang lang_PT-BR" style="display:none;" posttitle="YOUR POST TITLE IN PORTUGUESE">
HERE GOES THE PORTUGUESE PORTION OF YOUR POST
</div>

4. Go to the "Layout" section of your blog, and add a gadget wherever you want the translate option to appear. Choose the HTML/Javascript option.



5. You can put something like "English - Portuguese" as the gadget title or whatever you want, as long as you add the following as the code content:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<script>
    $(function() {
        $(".multilanguage").on("click", function(){
            var language = $(this).attr("language");
            $(".lang").css("display", "none");
            $(".lang_"+language).css("display", "block");
            $(".post-title").each(function(){
                $(this, 'a').text($(this).siblings(".post-body").find(".lang_"+language).attr("posttitle"));
            });
        });
    });
</script>
<div style="width:100%;text-align:right">
<img class="multilanguage" id="btn_EN" language="EN" src="SOURCE-ADDRESS-FOR-ENGLISH-FLAG-IMAGE" style="cursor: pointer; height: auto; width: 20px;" title="English" />
<img class="multilanguage" id="btn_PT-BR" language="PT-BR" src="SOURCE-ADDRESS-FOR-BRAZIL-FLAG-IMAGE" style="cursor: pointer; height: auto; width: 20px;" title="Portuguese" />
</div>

6. Note that the source path for each image you will use in the code above must be customized. Please refer to our other post on How to host an image at Blogger

7. After that, you will see that we will have a gadget in our blog which can change the post content to show the desired language.

8. With this you should be able to read all your posts in English and your native language. Note that even though your posts will be made in both languages, other elements of your blog will remain in the chosen language according to Blogger configuration.

How to host an image at Blogger

Sometimes you need to use an image in your Blogger page that is not exactly part of the content of your post but, rather, will be needed as a part of a script  or layout of your blog.

This is how you can host such image in Blogger itself, without the need to host it somewhere else.

1. Create a new post, and click in the "Insert image" button, selecting the image you want to use:


2. Once your image is inserted in your post, click in the HTML button of your post edit page:


3. In the HTML code, you will find the source address of your uploaded image. Write it down.


4. Once you got the image address, it is fine to just discard your post. Now you can use the source address of your image where you need it.

Adding JQuery support in Blogger

While I was writing some posts in preparation for this blog, I realized that it would be nice to have JQuery support in Blogger.

To enable JQuery in your Blogger page, go to the "Template" section of your blog and click the "Edit HTML" button.

Right before the </head> tag, paste the following:

1
2
3
<!-- including JQuery support -->
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>

Note that this code will implement the current version of JQuery up to the date of this post. If you want to be sure to be using the latest version, check out this link and update the code above accordingly:

http://jquery.com/download/#using-jquery-with-a-cdn

After that, click the "Save template" button and you are all set.