bien structuré son site en php

Mes premiers pas avec PHP remontent à la version 3…il y a bien longtemps! J’ai toujours été fasciné par sa facilité d’accès : pas de longue mise en place, un nombre conséquent de librairies disponibles et une documentation très bien faite (les gens oublient trop souvent php.net).

Malheureusement, ses qualités font aussi ses défauts: beaucoup de sites sont codés “avec les pieds”! Plein de codeurs amateurs se sont attitrés “développeur PHP”. Le résultat est qu’un grand nombre d’applications sont mal développées et très difficilement maintenable.

Depuis PHP5, le modèle objet apporte une toute nouvelle approche et on peut vraiment appliquer des design patterns et avoir un code bien mieux structuré. Mais même sans PHP5 et sans connaître le modèle objet, il est tout à fait possible de faire des choses très propres. Il est donc temps de s’y mettre!

Quand l’on débute en PHP, la structure généralement retenue est la même que pour un site statique sauf que l’on ajoute quelques morceaux de PHP par ci par là pour rendre le tout dynamique. Même si cela pouvait s’avérer tolérable en PHP3 (et je sais de quoi je parle!), ça ne l’est plus du tout avec la version 5. Tout d’abord parce que les possibilités de PHP ont grandement évoluées et deuxièmement parce que la façon de construire des sites en a fait de même. De plus en plus de technologies doivent cohabiter, souvent dans des environnements hétérogènes, et on ne parle plus de site web mais d’application web, ce qui en dit long!

Tout le monde ne peux plus s’improviser développeur web et comme tout développeur web qui se respecte le sait, le contenu DOIT être séparé de la présentation. Pas seulement pour rendre le code plus clair, même si ça y contribue sérieusement, mais pour le rendre plus maintenable, plus accessible et plus modulaire. Qu’est ce que j’entends par là? Et bien avez vous déjà travaillé en équipe, du récupérer le projet de quelqu’un d’autre ou tout simplement reprendre l’un de vos sites après un long moment? vous comprendrez…

Pourtant, il n’est pas difficile de mettre en place de tels mécanismes. Je me pencherai sur les deux approches que j’utilise: une simple, accessible à tous (pas besoin de OO) ou l’approche MVC, très répandue dans les frameworks.

La première ne demande pas de connaissance particulières. Il s’agit donc de séparer la logique applicative de la présentation. Nous allons dans un premier temps garder une approche très conventionnelle. La racine va contenir les pages du site (un fichier php = une page) dans lesquelles seule la logique applicative sera présente.

Dans un dossier que l’on pourra nommer presentation, on créé pour chaque page un fichier php. Ainsi, par exemple, pour la page home, on aura un fichier home.php à la racine et un fichier home.php dans le dossier presentation. On peut aussi créer un dossier includes qui contiendra toutes les fonctions partagées. Disons qu’il contient un fichier common.php.

Voici ce que contient home.php pour rendre la chose fonctionnelle:

<?php
include('includes/common.php');
// logique
include('presentation/home.php');

Ainsi, entre les deux include, on peut réaliser toute la logique. On peut par exemple définir la variable $text. L’affichage de celle ci se passe dans presentation/home.php:

<h1><?php echo $text ?></h1>

On a une séparation claire. On peut rapidement voir l’avantage d’un tel schéma, il est par exemple très facile d’utiliser un moteur de template à la place d’un simple fichier php. On sait aussi exactement où aller chercher si l’on veut rajouter une image par exemple. Pas besoin de scroller à travers 300 lignes de PHP puis de HTML pour trouver une balise!

presentation peut aussi contenir un fichier _header.php et _footer.php à inclure dans chacune de vos pages (pour les scripts situés dans le dossier presentation). Vous pouvez remarquer qu’ils sont préfixés d’un underscore, ceci afin de les différencier d’une page normale.

Cependant on peut rapidement améliorer ce schéma! Créons un dossier logique et déplaçons tous les scripts de la racine dans ce dernier. Retirons aussi les deux includes dans chacun d’entre eux. A présent, créons un script index.php à la racine. Celui-ci va servir de “dispatcher”: c’est lui qui va se charger d’exécuter la logique dans un premier temps puis d’afficher la présentation. La page à afficher lui sera passer en tant que paramètre GET.

<?php
$page = (isset($_GET['page']) ? $_GET['page'] : 'index';
include('logique/' . $page . '.php');
include('presentation/_header.php');
include('presentation/' . $page . '.php');
include('presentation/_footer.php');

Vous pouvez aussi constater que j’inclus le header et le footer pour éviter d’avoir à le faire dans chacune des pages. Pour rendre le tout plus jolie, on peut utiliser un .htaccess:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.+) index.php?page=$1 [L]
</IfModule>

Les pages sont maintenant accessible en utilisant des URLs du type http://localhost/ma_page.

Vous voilà maintenant avec une réelle séparation du fond et de la forme sans résidus du processus (les includes). Cette méthode est celle utilisée (avec des améliorations ;) dans Atomik Framework, mon micro framework. Le tout tient dans un script et s’avère pratique pour les petits sites et les débutants.

Passons à la vitesse supèrieure avec MVC. Ce dernier est un design pattern incontournable en ce moment. C’est un acronyme signifiant Model View Controller (Modèle Vue Contrôleur). Le modèle représente les données, la vue la présentation (l’équivalent de notre dossier presentation de la partie précédente) et le contrôleur la logique applicative (le dossier logique). Ces deux derniers éléments reprennent exactement la même idée que précédemment. Le premier est en revanche nouveau. Malgré qu’il soit possible de reprendre le concept précèdent et de lui intégrer les modèles, je ne le recommanderais pas.

MVC porte donc encore plus loin cette séparation des différentes parties de l’application. Le meilleur moyen d’arriver à un tel résultat est d’utiliser les classes. Le modèle sera une classe et le contrôleur une autre. La vue peut-être un simple script PHP ou utiliser un moteur de template, ceci a peu d’importance. Il est nécessaire d’avoir une organisation stricte avec ces trois composants stockés dans des répertoires différents.

Comme dans la méthode précédente, un “dispatcher” sera utilisé. On l’appel le “Front Controller”. Celui ci sera en charge de charger les classes adéquates et d’exécuter le contrôleur. Ce dernier est généralement divisé en action, chaque action étant représenté par une méthode de la classe. Les contrôleur peuvent éventuellement être organiser sous forme de modules. On a donc ici un système très structuré, facilement maintenable, modulaire et parfait pour le travail en équipe!

Passons à la pratique! Je prendrai pour exemple le Zend Framework. Je le considère comme excellent, tout comme sa documentation. L’exemple suivant restera très simple, le but de ce billet n’étant pas du tout de parler de ce framework. Le pré-requis étant que ce dernier soit installé et accessible depuis un “include path”.

Créons d’abord les répertoires nécessaires: public et application. Le premier contiendra toute la partie “statique” (pages html éventuelles, css, javascript…). Le second nos contrôleurs, modèles et vues. Celui-ci sera divisé en trois sous dossiers: controllers, models et views. Views étant encore une fois divisé en trois sous dossiers: filters, helpers et scripts!

Le framework sera initialisé par le script index.php dans le dossier public.

<?php
include 'Zend/Loader.php';
Zend_Loader::registerAutoload();
Zend_Front_Controller::run('../application/controllers');

Facile! Créons à présent un contrôleur dans application/controllers/IndexController.php

<?php
class IndexController extends Zend_Controller_Action
{
    public function indexAction()
    {
        $this->view->text = 'hello world';
    }
}

Le contrôleur est nommé index ce qui en fait celui par défaut. De même pour l’action.

La vue maintenant. Editons application/views/scripts/index/index.phtml:

<h1><?php echo $this->text ?></h1>

Enfin il reste à éditer le .htaccess:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.+) index.php [L]
</IfModule>

Il ne reste plus qu’à accéder au site à l’adresse http://localhost.

Rajouter un modèle n’est pas plus compliqué que de créer un fichier avec une classe dans le dossier modèle (le fichier ayant le même nom que la classe).

L’objectif d’employer de tels frameworks est de simplifier le développement d’une part en apportant un nombre considérable de classes prêt à l’emploi mais aussi de faciliter l’accès à l’application et sa maintenance. En effet, un framework utilise des conventions et des méthodes qu’il est facile de s’approprier en lisant la documentation. Ainsi n’importe quel développeur ayant connaissance de celui-ci peut immédiatement comprendre l’organisation et la structure de l’application. Il peut réellement se concentrer sur la logique.

Le revers de telles méthodologies est qu’elles nécessitent une formation. Maîtriser un framework entier peut s’avérer être un travail de longue haleine. On voit fleurir des frameworks de tous les côtés et beaucoup de développeur créés le leur. Même si cela a des bons côtés (on peut voir émerger de nouvelles idées par exemple) ça ne simplifie pas forcément la maintenance. Se plonger dans le travail de quelqu’un c’est comme se plonger dans sa tête, il faut en comprendre la logique et les mécanismes. Utiliser un framework reconnu et documenté à l’avantage de simplifier ce travail.

Finalement, même si je passe rapidement sur les différentes façon de faire (et pourtant le billet est long!), j’espère avoir convaincu les non initiés de s’y mettre! Vous trouverez bien plus de documentation sur les sites d’Atomik et de Zend (il y a de très bons articles sur http://developpez.com).


comments powered by Disqus

12/10/2007