Monday, July 27, 2015

Release v0.5

I've added release v0.5 on GitHub containing all the changes presented in the last posts:
-unique point for checking authorization
-TinyMCE integratation
-pagination fixing
-basic data validation and escaping

Friday, July 17, 2015

Unique point of checking authorization

In a previous post I listed "Unique point to check authorization" as @todo.

I will tell you now the reason, while  playing with "myFrontController" I noticed that links like http://myfrontcontroller/admin/new-post can be accessed without being logged in. An unwanted intruder knowing that path can post something like "I hacked your site!"


Solution:
I have verifications of authentication scattered in different places, for this reason I missed to check this situation. It would be nice to have one point where all requests should be checked.
I added in router.xml a new field called "levelOfSecurity". If the value of this field is "all" accessing a certain page does not require authentication. If "levelOfSecurity" is set to "admin" than a verification is made.

A path in router.xml looks now like this:

        <path>/edit/post/{slug}</path>
        <levelOfSecurity>admin</levelOfSecurity>
        <path_regexp>/\/edit\/post\/[\w\-]+/i</path_regexp>
        <controllerClass>Blog</controllerClass>
        <action>editPost</action>

A new static method was added to LoginUser class:

   public static function accessAllowed($levelOfSecurity)
    { 
        $flag=false;
        if ($levelOfSecurity=='all') {
            $flag=true;
            return $flag;
        }else {
            $flag=self::ValidateLoginAdmin();
            return $flag;
        }
       
    }

In FrontController::findPath() method after checking if a path exists also it is verified the access authorisation:

if (($route->path==$path) {
    if (LoginUser::accessAllowed($route->levelOfSecurity)))

TinyMCE integration with PHP

As you could saw my blog posts on the  "myFrontController" platform are like "adadafa fadfadfad". But from now on I want to be able to use text formatting, for this reason I want to integrate a Javascript editor with my code.
After a quick search I picked TinyMCE:

TinyMCE is a platform independent web based Javascript HTML WYSIWYG editor control released as Open Source under LGPL. TinyMCE has the ability to convert HTML TEXTAREA fields or other HTML elements to editor instances.

Installation:

I inserted this code beloe in the <head> of the \template\main_template.php file. As you can see I am using TinyMCE from a CDN.

    <script type="text/javascript" src="//tinymce.cachefly.net/4.0/tinymce.min.js"></script>
    <script type="text/javascript">
       tinymce.init({
      
           selector: "textarea",
       plugins: [
           "advlist autolink lists link image charmap print preview anchor",
           "searchreplace visualblocks code fullscreen",
          "insertdatetime media table contextmenu paste "
        ],
        toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter      alignright alignjustify | bullist numlist outdent indent | link image"
    });


I did some  tests, and it works nicely, I can now insert images or videos hosted somewhere on internet. TinyMCE offers some paid extension for uploading files on the server(with a server side code to handle those) but I am not going to try that.




Wednesday, July 15, 2015

Basic security measures and Apache logs

.htaccess


I checked and I could access the .php files found in base directory or in order sub folders. I added to the .htaccess the following lines:
   
    #redirect all .php files request to index.php
    RewriteRule ^(.*)\.php index.php [NC]


Later edit:  I tried to access http://myFrontController/config/route.xml  and surprise, it was displayed on screen. So now I decided to  redirect to index.php all file request, whatever extension they have

        RewriteRule ^(.*)\.* index.php [NC]


Unique point to check authorization

@todo

Validating and escaping  input data

I 've read some articles on this topic, there different approaches, the one that I liked most was :  Filter Input, Escape Output. From this discussion on stackoverflow:


"Here are the coding conventions I use:
  • values in $_POST, $_GET, $_REQUEST, etc. should not be escaped and should always be considered unsafe
  • values should be validated1 before being written to database or stored in $_SESSION
  • values expected to be numeric or boolean should be sanitized2 before being written to database or stored in $_SESSION
  • trust that numeric and boolean values from database and $_SESSION are indeed numeric or boolean
  • string values should be SQL-escaped before being used directly in any SQL query (non-string values should be sanitized2) or use prepared statements
  • string values should be HTML-escaped before being used in HTML output (non-string values should be sanitized2)
  • string values should be percent-encoded before being used in query strings (non-string values should be sanitized2)
  • use a variable naming convention (such as *_url, *_html, *_sql) to store transformed data
Terminology
For my purposes here, this is how I define the terms used above.
  1. to validate means to confirm any assumptions being made about the data such as having a specific format or required fields having a value
  2. to sanitize means to confirm values are exactly as expected (i.e. $id_num should contain nothing but digits)
Summary
In general (there may be some exceptions), I'd recommend the following:
  • use validate filters on input
  • use sanitize filters on output
  • remember TIMTOWDI - For example, I prefer htmlspecialchars() (which has more options) over FILTER_SANITIZE_FULL_SPECIAL_CHARS or FILTER_SANITIZE_SPECIAL_CHARS (which escapes line breaks)"
What I did

1. Validating data entered in the login form

- new class to store validation methods \validation\Valid.class.php
- use a regex to validate user and password:  '/^[a-zA-Z0-9_-]{3,16}$/i' (white list validation). A resource for validation regex: https://www.owasp.org/index.php/OWASP_Validation_Regex_Repository
- use the validation method in Admin.class.php :

    if (Validation::userAndPass($_POST['username'],$_POST['password']))

If the input is not valid show Javascript pop up message and redirect to login page (I know, I am not checking to see if Javascript is enabled)

    $message = "The entered value is not valid.";
    echo "<script type='text/javascript'>alert('$message');window.location = '/admin';</script>";



I've read about the filter_var() function from PHP and the types of filters available and I feel this regex is doing just fine for the job.
More on this :  http://code.tutsplus.com/tutorials/getting-clean-with-php--net-6732

The other places where data enters in the application are the new entry post/edit post form. I will apply "htmlentities()" function
before saving them on the Database.
-in BlogModel::newPost and BlogModel::updatePost I apply htmlentities()

  $result=$db->newPost(htmlentities($Author), htmlentities($Category), htmlentities($Text), htmlentities($Title), $Slug)

- in Blog::renderPost I decode the content of the post:

$new_content.= "<tr>".html_entity_decode($row['ActualPost'])."</tr></br>";

2. Use prepared statements and parameterized queries. - I am already doing that, I should just set connection attributes as mentioned here: http://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php

"What is mandatory however is the first setAttribute() line, which tells PDO to disable emulated prepared statements and use real prepared statements. This makes sure the statement and the values aren't parsed by PHP before sending it to the MySQL server (giving a possible attacker no chance to inject malicious SQL)."

            $db_conn = new PDO('mysql:host=localhost;dbname=myblog', $user, $pass);
            $db_conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
            $db_conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);



Saving Database user and password somewhere safe

As usually StackOverflow offers the answers: http://stackoverflow.com/questions/97984/how-to-secure-database-passwords-in-php
From the list of answers I picked on the below option:

If you're hosting on someone else's server and don't have access outside your webroot, you can always put your password and/or database connection in a file and then lock the file using a .htaccess:
 
<files mypasswdfile>
order allow,deny
deny from all
</files>

As I am already denying access to any .php file I didn't added anything else to the .htaccess

Also for the future:  "The usual solution is to move the password out of source-code into a configuration file. Then leave administration and securing that configuration file up to your system administrators. That way developers do not need to know anything about the production passwords, and there is no record of the password in your source-control."


 Apache logs


You can find those in the apache \logs on Windows machines.

1. access.log gives you information about whar  URIs were requested, by whom, and the answer from server, so you can see the URLs attacks:

The log file entries produced in CLF will look something like this:

127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 
Each part of this log entry is described below(source http://httpd.apache.org/docs/2.2/logs.html ):
127.0.0.1 (%h)
This is the IP address of the client (remote host) which made the request to the server. 
- (%l)
The "hyphen" in the output indicates that the requested piece of information is not available. In this case, the information that is not available is the RFC 1413 identity of the client determined by identd on the clients machine. This information is highly unreliable and should almost never be used except on tightly controlled internal networks. 
frank (%u)
This is the userid of the person requesting the document as determined by HTTP authentication. This value should not be trusted because the user is not yet authenticated. If the document is not password protected, this part will be "-" just like the previous one.
[10/Oct/2000:13:55:36 -0700] (%t)
The time that the request was received. The format is:
[day/month/year:hour:minute:second zone]
"GET /apache_pb.gif HTTP/1.0" (\"%r\")
The request line from the client is given in double quotes. The request line contains a great deal of useful information. First, the method used by the client is GET. Second, the client requested the resource /apache_pb.gif, and third, the client used the protocol HTTP/1.0. It is also possible to log one or more parts of the request line independently. For example, the format string "%m %U%q %H" will log the method, path, query-string, and protocol, resulting in exactly the same output as "%r".
200 (%>s)
This is the status code that the server sends back to the client. This information is very valuable, because it reveals whether the request resulted in a successful response (codes beginning in 2), a redirection (codes beginning in 3), an error caused by the client (codes beginning in 4), or an error in the server (codes beginning in 5). The full list of possible status codes can be found in the HTTP specification (RFC2616 section 10).
2326 (%b)
The last part indicates the size of the object returned to the client, not including the response headers. If no content was returned to the client, this value will be "-". To log "0" for no content, use %B instead.


2. error.log - in my case was a large file which NotePad++ couldn't open. I used VIM(http://www.vim.org/download.php#pc) and it worked like a charm.

The format of the error log is relatively free-form and descriptive. But there is certain information that is contained in most error log entries. For example, here is a typical message.
[Wed Oct 11 14:32:52 2000] [error] [client 127.0.0.1] client denied by server configuration: /export/home/live/ap/htdocs/test
The first item in the log entry is the date and time of the message. The second item lists the severity of the error being reported. 

Tuesday, July 14, 2015

Fix pagination bugs

Saving the current page on hard disk was a work around solution because at that moment I didn't had implemented URLs with parameters (routing with regex). This work around is OK if there is just one user surfing on the page:), because if there are more than one, they will influencing what page the other ones is seeing, and that is just wrong.

You can do a little test, open two tabs and navigate with Newer and Older buttons to see the issue.

In \config\route.xml I modified the routes to accept  URLs like /blog/3

<route name="blog page older">
        <path>/blog/{number}</path>
        <path_regexp>/\/blog\/[0-9]+$/i</path_regexp>
        <controllerClass>Blog</controllerClass>
        <action>renderPagination</action>
    </route>


    <route name="blog page newer">
        <path>/blog/{number}</path>
       <controllerClass>Blog</controllerClass>
       <action>renderPagination</action>
    </route>


The regexp is '/\/blog\/[0-9]+$/i' . To avoid a partial match,I appended a $ to the end,  '+' means more than one digit

The BlogModel has two new properties, $page_older and $page_newer which will be set after some verification, should not be lower than 1 and bigger than total number of posts divided by posts per page($per_page) .

        public function setPageNumber($current_page)
        {
            $db=new DBCon;
            $totalPostsNo=$db->countBlogPosts();
            if ($current_page<=1){
           
                $this->page_number=1;
               
            }else if ($current_page>=($totalPostsNo/$this->per_page)){
           
                $this->page_number=$current_page;
                $this->page_older=$current_page -1;
                $this->page_newer=$current_page;
           
            }else{
           
                $this->page_number=$current_page;
                $this->page_older=$current_page -1;
                $this->page_newer=$current_page +1;
            }
           
        }


Monday, July 13, 2015

Virtual hosts and relative URLs

As you probably saw, when I started my little front controller project I used absolute URLs because what it matter in the beginning was just to have a  working PHP website on my local computer.
When I copied the project to my computer at work I had to have theh same path "127.0.0.1/myFrontController/" and from this base address it was computed the relative URL to identify the route in router.xml.

As I  am getting closer to version 1.0 I need to make my website independent from where it will be deployed. In order to archive this  I will be using virtual hosts feature.
 
If you are using EasyPHP as I do, Install the module Virtual Host Manager from: http://www.easyphp.org/save-module-virtualhostsmanager-vc9-latest.php  or have look here http://www.apptools.com/phptools/virtualhost.php
 - create a virtual host called as you wish
Do some changes in the code:
- 'Location:http://127.0.0.1/myFrontController/admin/home' changed to "Location: /admin/home" in Admin.class.php 
-  edit all links to be relative
- use directly the $_SERVER['REQUEST_URI'] instead erasing "/myFrontController" in FrontController class constructor.

        $request_uri=$_SERVER['REQUEST_URI'];
        $this->relative_url=substr($request_uri, strpos($request_uri, '/', 1));
       

        replaced with:
       
        $this->relative_url=$_SERVER['REQUEST_URI'];
       

Fixing PSR2 errors with phpcbf and integration with Netbeans 8

I used my own style  formatting the code until now (I  am still using Notepad++ to edit my code, and I hit the TAB to indent  the code). I've read about the PSR-2 coding style guide and I want to follow it from now, but what  about the code already written? There is a solution for that :
PHP Code Sniffer and  PHP Code Beautifier and Fixer. On my home laptop I installed also NetBeans and I made efforts to integrate these static analysis tools with NetBeans 8 on Windows 7.

Some good articles about this topic:

http://blog.florianwolters.de/tutorial/2012/05/03/Integrate-tools-for-static-PHP-code-analyses-into-NetBeans-7.x/
https://blogs.oracle.com/netbeansphp/entry/static_code_analysis
 
 But still the mother fucker "phpcbf" was not fixing my code:

              "diff" is not recognized as an internal or external command....  



On Windows machines there is a problem with the --diff option (another reason to move to Linux), you need to specify  "--no-patch" http://stackoverflow.com/questions/24015486/fixing-psr2-errors-with-phpcbf-phar

I decided to run it form command line and not from NetBeans.  My phpcbf command to fix the errors was:


"..path.. to phpcbf.bat"  "fix" "--no-ansi" "--verbose" "--dry-run" "--no-patch" "--format=xml" "--no-interaction" "--level=psr2" "--config=sf20" "C:\Program Files (x86)\EasyPHP-DevServer-14.1VC9\data\localweb\myFrontController"

Inside the file "phpcbf.bat" you may need to add manually the path to php.exe and to phpcbf (with no extension)








Thursday, July 9, 2015

PHP edit and save posts, delete posts - release v.04 on GitHub

For an Admin dashboard is more relevant to see just the titles (not entire content as in normal view) and have edit / delete buttons :

1. Admin dashboard for editing posts

- in the "render()" method of the class Blog, if the admin is logged, Edit button is displayed otherwise normal listing of posts
- new path /edit/{slug} added to route.xml as a result of the above

2. Edit posts and save them to database

- the edit post page should look exactly like the new post entry just that it should be populated with the values from DB. So I added the file "edit_post_entry.php" under templates.
Inside I added value=<?php echo '"'.$author.'"'; ?> (same for the title and category).
- issue:  I do not want to  take the file edit_post_entry.php and include it directly into the main template, I want first to process it (interpret ) with the local variables  replacing the actual "value=" in the HTML form.
The post "Read echo'ed output from another PHP file" http://stackoverflow.com/questions/631388/read-echoed-output-from-another-php-file showed me the way:

        ob_start(); // begin collecting output
        include 'myfile.php';
        $result = ob_get_clean(); // retrieve output from myfile.php, stop buffering
        //$result will then contain the text.


- as you could see the slug is used to identify  the post.Only for update I am using the post Id as unique identifier and the new slug is saved in database if the title of the blog is changed.

I will put in the form (edit_post_entry.php) a hidden field to store the post Id taken from database which will be used in the SQL update statement:

        $new_slug=SlugGenerator::slugify($Title);
        $stmt = $this->db->prepare("UPDATE blogposts SET Category=:field1, Author=:field2, ActualPost=:field3,title=:field4,slug=:field5 WHERE Id=:field_id;");
        $stmt->bindParam(':field_id',$PostID, PDO::PARAM_INT);
        $stmt->bindParam(':field1', $Category);
        $stmt->bindParam(':field2', $Author);
        $stmt->bindParam(':field3', $Text);
        $stmt->bindParam(':field4', $Title);
        $stmt->bindParam(':field5', $new_slug);
   

    $stmt->execute();


3. Delete posts   

First I get the post using  "getPost($post_slug)" and from the output the post Id is read and the delete is applied to that Id.

The code is available in my first release on GitHub, v0.4:  https://github.com/cristianpana86/myFrontController/releases/tag/v0.4



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']);

PHP basic pagination with MySQL

First step: create new branch in GitHub from the GitHub. Code. Download the code, from the GitHub application on local machines. Modify the code, commit changes to this branch and synchronize with GitHub server.  When I finished with the development I make a Pull Request to merge the branch with the repository.

I will display a certain number of posts per page (now is hard coded to 2), and 2 buttons (links) "Older posts" and "Newer Posts".

I am using MySQL "LIMIT" clause to specify the number of records to be returned. From http://www.w3schools.com/php/php_mysql_select_limit.asp
     
     The SQL query below says "return only 10 records, start on record 16 (OFFSET 15)":
        $sql = "SELECT * FROM Orders LIMIT 10 OFFSET 15";

It seems that the default type for bindParam is string so you will get an error if you do not specify to be an integer:   PDO:PARAM_INT:
    http://stackoverflow.com/questions/4544051/sqlstate42000-syntax-error-or-access-violation-1064-you-have-an-error-in-you
       
        $sth=$this->db->prepare("SELECT * FROM blogposts LIMIT :per_page OFFSET :page_number ;");
        $sth->bindParam(':per_page', $per_page, PDO::PARAM_INT);
        $sth->bindParam(':page_number', $page_numb, PDO::PARAM_INT);
        $sth->execute();



-added pagination.xml file in \model to store current page number and number of posts per page (this should be changed in the future as having one current page for all the users accessing the website is not right.)  Later edit: problem solved in this post http://phpbeginnertoadvanced.blogspot.co.uk/2015/07/fix-pagination.html

-added routes for /blog/older and /blog/newer 

You will have access to the code files when releasing the v0.4

Thursday, July 2, 2015

GitHub


Now that I am preparing to develop the v0.4 I believe I should be using a version control software. After reading about the subject a little, and taking in account that many open source projects use GitHub I decided for it. Next steps were:

1. create account on GitHub
2. install GitHub for Windows
3. make Git work behind firewall at work. In the .gitconfig file, which on computer should be found  at %USERPROFILE% (Windows 7)I added this line:
        [http]
              proxy = http://<your-proxy>:<port>

Here details on how to find your proxy settings:  http://superuser.com/questions/346372/how-do-i-know-what-proxy-server-im-using

You can find my project on GitHub at this link:  https://github.com/cristianpana86/myFrontController

myFrontController v0.3

Note: The blog posts are written based on the notes I make on the readMe.txt file. Some the actions where "to do" items which were implemented later, for this reason you may see text like "I should do that"

Major improvements in v0.3
- autoloading function
- routing
- give up admin/index  (unique point of entry in the application)
- improvements to the login flow

1. Autoloading
 As you could see in the post about version 0.2 there are some issues with the autoloading function. I decided to improve this and even more use a popular standard PSR-4. My autoload function is inspired from this one:  http://www.php-fig.org/psr/psr-4/examples/  - just that I do not have the path  /src/ directory. I  started using also  namespaces in order to  to respects the PSR-4 standard and maybe later I will be able to use packages built by other people together with myFrontController CMS.

My vendor\package combination of namespaces is :  CPANA\myFrontController ,under this I have added :

CPANA\myFrontController\controller
CPANA\myFrontController\model
......

I had to change some code in my FrontController class as it seems there is a known bug (weird behaviour ) :      when I try to dynamically create the name of the class  "new $_GET['controller']()" I get message that the class cannot be found
 Here are some links about this subject:
http://stackoverflow.com/questions/6150703/php-dynamic-instance-with-not-fully-qualified-namespaces
    https://bugs.php.net/bug.php?id=51126
       
This is the code to  solve the problem:
  
                $class_name=__NAMESPACE__ . '\\'. $_GET['controller'];
                $obj= new $class_name();
                $obj->$_GET['action']();

2. Routing

I started reading the Symfony Book and I  implemented a routing system inspired from the one used in Symfony.
The logic to call the correct function will be :
    1. read the requested URL ($_SERVER['REQUEST_URI']), and exclude the /myFrontController
    2. verify in the \config\route.xml if there is any route matching -> if yes than read from \config\route.xml the function and call it.
            -> if no redirect to 404 page - created new controller class called "PageNotFound.class.php"

So I did the following:

1. created \config\route.xml file to store routes and matching class and method to be called
2. modified FrontControll class
3. added .htaccess from Symfony and replaced to redirect to "index"    instead of "app"                                                               

3. Give up admin/index

-in order to use just one front controller (not one for normal user and one for admin user) some changes should be made (also taking in account the new routing system)
-this will involve changing the way the pages are rendered (templating?) maybe request and response objects
---->>>
-new class \view\Render.class.php
    -it contains a static property $content  which is echoed in content.php  and also $menu which depends on being an admin or normal user
    -and a method which renders the main_template.php  (which imports content.php and menu.php or menu_admin.php)
    -each time we want to change the output, I change the value of the $content and call the Render::renderPage()
   
4. Login

I modified the LoginUser.class.php and also the Admin.class.php

-in Admin.class.php the function "renderLogin" it is called both when clicking "Admin" button and also when clicking on the Submit button
-in Login.class.php I added the static function validateLoginAdmin() which is used to check which menu (admin or normal user one) should be displayed. at the moment I call it on each specific class (Home, Blog) but it should be moved in to Render




5. Overview
At this point if you want to see the Home page the flow of the application is the following:
-you are redirected to index.php
-the front controller searches the path in router.xml and calls the controller (the needed method for the job)
-the method getHome() from StaticPages class is called from controllers __contruct(), which furher calles fetchStaticInfo($pagetype) from DBCon class. The information is fetched from database
- the render() function from controller class is called




The files can be downloaded at this link.

Wednesday, July 1, 2015

myFrontController v0.2

Usually the continuation of a good movie is bad, hopefully my version 0.2 of myFrontController is a real progress.


I moved the files inside specific folders like: controllers, model, login, admin etc. Doing this means I need to implement a more complex autoloading function.

$folders=array('\\controller\\','\\model\\','\\login\\','\\view\\');
   
    foreach($folders as $folder){
       
       if(file_exists($dir . $folder . $class . '.class.php')){
            require_once $dir . $folder . $class . '.class.php';
        }


It is not covering some situations for this reason you may see some "include" in some classes, but I promise to solve the issue in v0.3

I am trying to start using comments in the style used by PHP Documentor. Step by step I hope to get used to write them. An  IDE would probably automatically generate the comments skeleton but at the moment I am using Notepad++

In the image below it is more or less described how my website works and a little on how I implemented the separation of concerns following the MVC design pattern ideas.



Changes from version 0.1 of myFrontController:

added DBCon.class.php - handles connection to database and fetching data

added StaticPages.classes.php -
added BlogModel.classes.php

- replace & with &amp; in the links

----------- database --------------------------------
shift from SQLite to MySQL
create database "myblog"
create table  static_pages
alter table blogposts add column title varchar(255)


----------------------------------------------------------------------------------------------------------------------------------------
added basic login module (based on cookies) to the have an Admin view from where you can add new posts
added:
index_admin.php
/controller/Admin.class.php
/login/LoginUser.class.php

--------------------------------------------------
login module explained:
    first I hardcoded the username and passord inside the static function validateUserPass of the class LoginUser
    ---
    static public function validateUserPass($user,$pass){
            if(($user=='admin')&&($pass=='1234')){
                return true;

    ---

    From a form, username and password are sent via POST method using hidden fields (login.php):

            <form action="index.php" method="POST" >
                Username <br>
                <input type="text" name="username">
                <br>Password <br>
                <input type="text" name="password">
                <input type="submit" value="Login">
                <input type="hidden" name="controller" value="Admin">
                <input type="hidden" name="action" value="validateLogin">
            </form>

    ---
    the hidden values indicate controller name "Admin" and action "validateLogin"

    if the user and password match the ones hardcoded than we set a cookie containing an md5 hash of the user name + a secret word.

     setcookie('PageLogin', md5($user.self::$secret_word));
     setcookie('PageLoginUser', $user);


The files can be downloaded from this link:  https://drive.google.com/file/d/0B4lszAGYHn-dTXNOX2psd2QweGc/view?usp=sharing

myFrontController v0.1

NOTE: I am telling here how I got from point A to point B, not that it is the recommended path.

I started thinking on my Front controller based website from the point of view of a link containing a query string, like this one:

 "https://en.wikipedia.org/w/index.php?title=Main_Page&oldid=664887982"



So the query says that the request will be processed by the file index.php and the $_GET['title'] will be set with the value "Main_Page" and the $_GET['oldid'] will be set with value 664887982.

my links will look  like this (under ..\EasyPHP-DevServer-14.1VC9\data\localweb  I created the folder "myFrontController"):

'http://127.0.0.1/myFrontController/index.php?controller=Home&action=render'

You can read this link like this: index.php should process this request and call the method "render()" of the class "Home"

I will create an index file, a FrontController class, and other controller classes for each functionality I want to implement: Home page, Blog listing page. I will add also a folder called "templates" to store... well the templates.
I created a header and a footer and included them in the index.php

include("templates/header.php");

FrontController::set_controller();
 

include("templates/footer.php");


 OK, so let's move on to the actual FrontController class: it contains a static class called  setController() which reads the values for 'controller' and 'action' from $_GET[] and dynamically create an instance of the specified class and calls the method


            if((!isset($_GET['controller']))||(!isset($_GET['action']))){
       
                echo "do nothing GET";
            }else{
       
                //call controller class for GET method
                $obj= new $_GET['controller']();
                $obj->$_GET['action']();

                   


The second functionality that I want to implement is to list the blog post. I am using SQLite to store the information. You should execute the file "initializeSQLite.php" (you can just navigate to it on your browser) to create an SQLite database, create the tables BlogPosts and store information.

In the Blog.class.php is found the code for reading the database and generate the output.

The third functionality is adding a new post, the link is this one:   '?controller=Blog&action=new_post_entry'

The functionality is done it two steps:
- first step include "templates/new_post_entry.php" which contains a form where you can fill the title of the post, author, post content and a Submit button.
-second step when clicking the Submit button the request goes to index.php (again). together with the data the form contains 2 hidden fields :

     <input type="hidden" name="controller" value="Blog">
    <input type="hidden" name="action" value="postOnBlog">


These two values indicate to FrontController which method/class will handle the request.

Below is the list of files at the end.
You can download the code from here:  https://drive.google.com/file/d/0B4lszAGYHn-dVFh0X0E2NV9BLW8/view?usp=sharing

First step

I started learning PHP and I decided to keep a diary of my progress. Also I like the idea of giving back to community. As I learned from other peoples blogs and messages on StackOverflow, maybe one day somebody will find answers to their questions reading my blog.

After reading the about HTML, some CSS and PHP on W3School, I moved to  "PHP Cookbook, 3rd Edition" by David Sklar and Adam Trachtenberg. So I have an idea of the basic staff, what should I do next? How do you get from beginner to advanced? (you can have a look here http://www.sitepoint.com/becoming-php-professional-missing-link/ )


So I moved on reading about MVC,  HMVC and I found out about Front Controller design patten. According to Wikipedia almost everyone uses front controller:


Several web-tier application frameworks implement the Front Controller pattern, among them:

I've read some blog posts on this topic and started building my own.

P.S.

I am working on 2 Windows machines (at work and at home). I installed EasyPHP  which contains  Apache/PHP/MySQL stack +
I am using Notepad++ as text editor.
I have previous experience with programming, data structures, databases but not with PHP and generally with web programming