Wednesday, July 8, 2015

PHP router with regex - Display individual blog posts

In order to be able to display individual blog posts and have nice and relevant links which can be bookmarked I need to  modify a little bit the routing to recognize paths like /blog/post/post-name-without-spaces

I need a regular expression to match this kind of routes. I do not have too much experience with regexp and it turns out to be difficult to understand in the beginning. An important aspects about regex in PHP:

        - PHP uses another pair of delimiters inside '': "You must specify a delimiter for your expression. A delimiter is a special  character used at the start and end of your expression to denote which part is the expression. This allows you to use modifiers  and the interpreter to know which is an expression and which are modifiers."

         http://stackoverflow.com/questions/7660545/delimiter-must-not-be-alphanumeric-or-backslash-and-preg-match

        -http://www.phpliveregex.com/ this is a website where you can test your regexp with different php functions (preg_match, preg_grep etc)

        - the php manual for regexp is found here:
http://www.php.net/manual/en/reference.pcre.pattern.syntax.php

        -  regexp from "/blog/post/blog-title-here" :  preg_match("/\/blog\/post\/[\w\-]+/i",  $path);

In order to have generic routes I added a new field in the route.xml called <path_regexp>, example below

    <route name="individual blog post">
        <path>/blog/posts/{slug}</path>
        <path_regexp>/\/blog\/post\/[\w\-]+/i</path_regexp>
        <controllerClass>Blog</controllerClass>
        <action>renderPost</action>
    </route>


I am doing a verification using preg_match and the <path_regexp>    to see if it is matching the requested URI from HTTP request.
- if there is a match than a new object of class "controllerClass" is created, and it is called the <action> method with parameter "slug", basically the value after "/blog/post/"

- this triggers a search in the database for a blog post where title is like slug.
What if there are two identical titles? Answer: at this moment all of them are listed.The problems will arises when editing two posts with identical names
- links are added dynamically on the list of all blogs (when clicking Blog button) based on the Title from database in which I replace spaces with hyphen, and make all letters lower-case.

            $slug_from_title=  strtolower(str_replace(' ','-',$row['title']));
            $new_content.= "<tr><a href=/myFrontController/blog/post/$slug_from_title>".$row['title']."</a></tr></br>";


!!! further improvement should be done in for a proper slug generator (treat all signs and also transform language specific signs to the closest ASCII charachter)


P.S. from next day :)

I solved the problems listed above saving in the "blogposts" table the slug for each post in the newly added column "slug". I also added in \model the class SlugGenerator with a static function slugify($title) which treats all the problems with characters which may be included in the title of a post
The above code is now changed to:

                    $slug_from_title=  SlugGenerator::slugify($row['title']);

No comments:

Post a Comment