Front Controller

Online demo (username : p ; password : (leave empty))

Download version 0.4

What is Front Controller ?

Front Controller (FC) is a collection of PHP scripts meant to create portals.

It allows you to create many pages, protected by login and with database access.

It is 520 lines of PHP, HTML and CSS code across 15 files.

It has no JavaScript code.

Structure

The application starts with app.php (the single controller).

  1. app.php first registers an autoload (so no need for includes anywhere)

  2. it then parses the URL for the page name

  3. app.php uses a custom session handler to save the session data in the database (table 'session')

  4. it then verifies if the user is logged in (and shows a login page if not)

  5. the view is then loaded

To find a view, app.php loads the view class by prepending 'Vue' to it.

So URL /app.php/Bonjour/ loads class VueBonjour from the app/vue/VueBonjour.php file.

Features

When the user logs out, the URL is unchanged (so when logging back in, the user will be where he was before logging out).

In fact, the login page does not have its own URL.

Resubmission : If the user was filling a form and was logged out when submitting it, the login page allows him to resend the form data.

Installation

FC requires a MySQL database to save session data and users.

  1. First create the database and the user PHP will access it with :
    1. 1 create.txt (create database 'fc' with user 'fc' and password '1qaz2wsx')
    2. 2 dump.txt (create 'session' and 'user' tables)
    3. 3 create.txt (add user 'admin' (password empty) to the 'user' table)

  2. Copy the app/ and style/ folders and the app.php file to where you want the application to be installed.

  3. You may rename the app.php script to something else ('index.php' for example).

  4. Do not forget to block access to the app/ folder by either moving it outside of the document root (and modifying app.php to point to its new location) or by adding this to an app/.htaccess file :
    Require all denied
    

  5. To customize the connection to the database, edit the app/modele/Mdl.php script.

  6. You may now login as user 'admin' with an empty password (do not forget to change it).

Examples

Look at the VueUsers.php view and the MdlUser.php model for an example.

Creating a new page

Creating a new page is simple.

First create a class named VueBonjour and save it in app/vue/VueBonjour.php

<?php
	class VueBonjour extends Vue {
		protected function render() {
			$this->renderTitle('Bonjour');
?>
<p>Bienvenue.
<?php
		}
	}
?>

It will then be accessible at the /app.php/Bonjour/ URL.

Every view inherits from the abstract Vue class.

By default, every class must implement the abstract 'render()' method.

It is called whenever the vue must be rendered.

Vue.php also provides a renderTitle($title) function to render the page title and optionally the navigation menu at the top.

Adding it to the navigation menu

To add the page to the navigation menu, edit the $pages array in the app/vue/Vue.php file.

Extra methods

Look inside Vue.php for method signatures. (all the following functions are protected)

Creating a new model

When creating a new view, you may want to access the database.

Do so using a model.

In the app/modele/ folder, model classes inherit from the abstract Mdl class.

Example model :

<?php
	class MdlBonjour extends Mdl {
		function getAllBonjours($id = 0) {
			$sth = $this->pdo()->prepare('SELECT name FROM bonjour WHERE id = :id');
			$sth->execute(array('id' => $id));
			return $sth->fetchAll();
		}
	}
?>

Mdl.php provides a pdo() method which gives you access to the PDO object.

It is recommended to create one model per database table.

Dealing with sessions

FC uses sessions exclusively to handle logins.

If you wish to save user-related data, do so in the database instead of in $_SESSION.

Global constants

PAGE
The name of the page from the URL.
SUBPAGE
The name of the subpage from the URL.
SUBSUBPAGE
The name of the subsubpage from the URL.
USER
The username of the logged-in user.
USERID
The unique ID of the logged-in user.
USERNAME
The full name of the logged-in user.

Customization

Utilities

URL::FullURL()

Returns a root relative URL.

URL::FullURL('Bonjour', 123, array('s' => 456))
returns /app.php/Bonjour/123/?s=456

URL::FullURLHTML()

Same as URL::FullURL() but for an HTML context :

<a href="<?= URL::FullURLHTML('Bonjour') ?>">Bonjour</a>

URL::DomainURL()

Returns a full URL (with host name).

URL::DomainURL('Bonjour')
returns http://fc.philippe97.ca/app.php/Bonjour/

URL::DomainURLHTML()

Same as URL::DomainURL() but for an HTML context.

URL::Relative($base, $url)

Resolves a relative URL to a base URL.

$base is the full base URL (http://...).

$url is the relative URL (http://... or //... or /... or ...).

URL::RelativeHTML($base, $url)

Same as URL::Relative() but for an HTML context.

HTTP::Reload()

Reloads the current URL.

Useful in handlePOST() to change the POST request into a GET.

(if not called, the user will be prompted to resubmit if the reload button is clicked)

HTTP::ReloadURL()

Redirects to another URL.

Accepts the same arguments as URL::FullURL()

Example : HTTP::ReloadURL('Bonjour', 456)

HTTP::Resubmit()

Resubmits the current URL (with 307 code).

Tells the browser to resend the POST request.

HTTP::ResubmitURL()

Resubmits to another URL.

Accepts the same arguments as URL::FullURL()

Example : HTTP::ResubmitURL('Bonjour', 456)

Tips and tricks

Sub-pages (i.e. /app.php/Bonjour/SubPage/)

There are many ways to implement sub-pages in FC.

One of them is to create a view for the parent page which includes the child pages.

To simplify things, you may want to give SUBPAGE a default value of 'Index' in app.php:

define('SUBPAGE', $subpage ?: 'Index');

The view (app/vue/VueBonjour.php) may then load a separate PHP file for every sub page :

<?php
	class VueBonjour extends Vue {
		protected function render() {
			$file = __DIR__ . '/Bonjour/' . SUBPAGE . '.php';
			if (file_exists($file))
				include $file;
			else
				(new Vue404())->handle();
		}
	}
?>

Every PHP file in the Bonjour/ folder may start like this (app/vue/Bonjour/Index.php in this case) :

<?php $this->renderTitle('Index'); ?>
<p>This is the Index page.</p>
<ul>
	<p><li><a href="<?= URL::FullURLHTML(PAGE, 'AAA') ?>">AAA</a></li>
</ul>

app/vue/Bonjour/AAA.php may contain :

<?php $this->renderTitle('AAA'); ?>
<p>This is the AAA page.</p>

Public pages

Sometimes, you may want to make a page accessible to all without having to log in.

To do that, you have to edit the app.php script.

Replace the if (!USER) line with this :

if (!USER && !in_array($page, array('PublicPage')))

You may add more pages in the array().