Alors, pourquoi j'ai nommé nom blog, "la tribu des mini pouces" ?
Tout commence lorsque ma femme m'a parlé d'une tribu mystérieuse en Corée, la "Tribu des mini pouces" ... J'ai alors pensé d'une tribu autochtone, qui avait la particularité d'avoir des petit pouces, afin de mieux visé à l'arc ...
Mais il n'en était rien ... en fait, ce sont les personnes championnes d'écriture de Texto sur portable ! (ce qui n'est certainement pas mon cas ... )

Apparament, il n'est pas rare de rencontrer des jeunes coréens taper des texto à la vitesse de la lumière ! Voici donc un petit hommage,a tous les Geeks et Geekettes, et surtout aux développeurs dont certains se reconnaitront dans cette tribu ... ^^

dimanche 13 février 2011

Gestion des pages Web sous CodeIgniter

Bonsoir à tous,

Je pense que c'est l'un des tutoriels les plus important de mon blog. Vous devriez gagner en rapidité de développement, car optimiser pour faire les tâche les plus importantes : création de contenu de la page et création de chaque composante de la page. De plus , nous gagnerons en visibilité car les contenus seront stockés dans le répertoire 'controllers' et les composantes dans le répertoire views. Tenez vous prêt, ce tuto est très très long ... Accrochez vous !

Je fais une première annonce, je bascule sur CodeIgniter 2.0. L'arborescence du projet ainsi qu'un certain nombre de fonctionnalités ont été modifié. Tous mes prochain posts prendront en compte ces changements.

Dans ce tutoriel, je souhaite vous montrer comment gérer de pages web, même complexes, dans le processus de création d'un site internet, qu'il soit petit, moyen ou grand...

La problématique aujourd'hui est que un nombre de plus en plus important de technologies s'ajoute au fur et à mesure(Rss, json, Ajax, Rest, Soap, Mail, Atom, Minify, Trackback, Css2/3, HTML4.1/4.4/5, etc ...), et il est de plus en plus difficile de de répondre de manière satisfaisante à ces technologies.

Nous allons structurer un projet web afin de ce concentrer sur l'essentiel, le CONTENU de la page !

Je vous conseille au préalable de lire cet article "Controller de controller", qui est un prérequis à cet article.

Présentation de répertoire controllers


La première chose à vous montrer est le répertoire 'controllers' comme le montre l'image ci dessous


Vous voyez 2 fichiers de configuration _config_html.ini.php et _config_mail.ini.php. Il permettent de configurer un ensemble de pages internet et l'autre configurer un ensemble de mail.

Les fichiers doctype_****.php sont en faire les formats de sorties d'une requête. simplement, si vous souhaitez renvoyer au client une page internet, alors vous utiliserez doctype_html.php. Si vous souhaitez renvoyer un flux RSS, et bien vous utiliserez le fichier doctype_rss.php...

Vous avez aussi le fichier controller.php. Ce fichier permet simplement d'implémenter des fonctionnalités qui peuvent être utiliser par toutes les pages. Cela peut être le cas de service de géolocalisation, WebServices Amazon, ou twitter ...etc... il sera pour l'instant 'vide'.

Enfin, les autres fichiers sont simplement les contrôleurs dans une architecture MVC.

Ficher _config_html.ini.php


Voici le contenu du fichier _config_html.ini.php :

;langue de la page en 2 lettres
lg = jp

;titre de la page
title = My website

;Encodage de la page
charset = UTF-8

;Favicon de la page
;true ou false
favicon = true

;adresse rss
rss =

;css & js
min_css = toto.css
min_js = titi.js

;cdn & host
cdn = cdn.toto.com
host = ceramique-paris.fr

;balises meta_
meta_description = coucou
meta_keywords =
meta_Author =
meta_Copyright =
meta_geo.region =
meta_geo.placename =
meta_geo.position =
meta_ICBM =
meta_DC.Title =
meta_DC.Creator =
meta_DC.Type =
meta_DC.Date =
meta_DC.Format =
meta_google-site-verification =

Vous voyez donc les paramètres de configuration d'une page internet(langue, encodage,balise meta,favicon ...). Si la variable est vide, alors elle ne s'affichera pas dans le code html. Vous pouvez déjà faire une configuration de base pour un ensemble de page internet, et créer une autre configuration pour un autre ensemble: (par exemple: créer un fichier _config_html_content.ini.php pour le contenu et _config_html_user.ini.php pour les pages utilisateurs)

fichier controller.php et doctype_html.php


Vous devez créer ces deux fichier et faire un copy-past sur votre projet.
Voici le fichier controller.php:

class Controller extends CI_Controller{

function __construct()
{
parent::__construct();
}

// Ajouter des fonctionnalité
/*
webservices ...
reporting
mail
*/

}


et ici, le fichier le fichier doctype_html.php

require_once 'controller.php';

class Doctype_html extends Controller{


/*
Attributs interne
*/
public $param = array();


/*
Constructeur
*/
function __construct($config_file="")
{
parent::__construct();

$this->param{'lg'} = 'fr';
$this->param{'title'} = 'Undefined title';
$this->param{'charset'} = 'UTF-8';
$this->param{'favicon'} = true;
$this->param{'js'} = array();
$this->param{'js_ext'} = array();
$this->param{'min_js'} = '';
$this->param{'css'} = array();
$this->param{'min_css'} = '';
$this->param{'rss'} = '';
$this->param{'cdn'} = '';
$this->param{'host'} = '';
$this->param{'meta'}{'description'} = '';
$this->param{'meta'}{'keywords'} = '';
$this->param{'meta'}{'Author'} = '';
$this->param{'meta'}{'Copyright '} = '';
$this->param{'meta'}{'geo.region'} = '';
$this->param{'meta'}{'geo.placename'} = '';
$this->param{'meta'}{'geo.position'} = '';
$this->param{'meta'}{'ICBM'} = '';
$this->param{'meta'}{'DC.Title'} = '';
$this->param{'meta'}{'DC.Creator'} = '';
$this->param{'meta'}{'DC.Type'} = '';
$this->param{'meta'}{'DC.Date'} = '';
$this->param{'meta'}{'DC.Format'} = '';
$this->param{'meta'}{'google-site-verification'} = ''; //google webmastertools
$this->param{'body'} = '';

if(!empty($config_file)){
$fichier = dirname(__FILE__)."/".$config_file;
$tableauIni = parse_ini_file($fichier);
foreach($tableauIni as $k=>$v){
$fn = '_'.$k;
$this->$fn($v);}
}
}

/*
__call
*/
public function __call($methode,$arg){

if($methode=='send')
$this->send();

// méthode ne commencant pas par '_' éliminé
if(substr($methode,0,1)!='_')
return false;

// balise meta
if(substr($methode,0,6)=='_meta_'){
$this->param{'meta'}{str_replace('_meta_','',$methode)} = $arg[0];
return true;
}

// existe dans param, modification de la valeur
if(isset($this->param{substr($methode,1,strlen($methode))}))
$this->param{substr($methode,1,strlen($methode))} = $arg[0];

return true;
}

/*
Envoi du code html
*/
public function send(){
// genere js ... todo

// genere css ... todo

// return code html
echo $this->load->view('tpl_html',$this->param);
}
}

Nous remarquerons que CI_Controller hérite Controller qui lui hérite doctype_html, qui lui héritera le controleur de notre page internet...

Voici le fichier tpl_html.php qu'il faudra mettre dans le répertoire views de votre projet. Ce fichier récupéra les valeurs du fichier _config_html.ini.php, et les utilisera pour générer le code html.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php echo !empty($lg) ? $lg:'fr';?>" lang="<?php echo !empty($lg) ? $lg:'fr';?>" >
<head>
<meta http-equiv="content-type" content="text/html; charset=<?php echo isset($charset) ? $charset:'UTF-8';?>" />
<title><?php echo !empty($title) ? $title:'Undefined title !';?></title>
<?php if(!empty($meta{'description'})):?><meta name="description" content="<?php echo $meta{'description'};?>" />
<?php endif;?>
<?php if(!empty($meta{'keywords'})):?><meta name="keywords" content="<?php echo $meta{'keywords'};?>" />
<?php endif;?>
<?php if(!empty($meta{'geo.region'})):?><meta name="geo.region" content="<?php echo $meta{'geo.region'};?>" />
<?php endif;?>
<?php if(!empty($meta{'geo.placename'})):?><meta name="geo.placename" content="<?php echo $meta{'geo.placename'};?>" />
<?php endif;?>
<?php if(!empty($meta{'geo.position'})):?><meta name="geo.position" content="<?php echo $meta{'geo.position'};?>" />
<?php endif;?>
<?php if(!empty($meta{'ICBM'})):?><meta name="ICBM" content="<?php echo $meta{'ICBM'};?>" />
<?php endif;?>
<?php if(!empty($meta{'DC.Title'})):?><meta name="DC.Title" content="<?php echo $meta{'DC.Title'};?>" />
<?php endif;?>
<?php if(!empty($meta{'DC.Creator'})):?><meta name="DC.Creator" content="<?php echo $meta{'DC.Creator'};?>" />
<?php endif;?>
<?php if(!empty($meta{'DC.Type'})):?><meta name="DC.Type" content="<?php echo $meta{'DC.Type'};?>" />
<?php endif;?>
<?php if(!empty($meta{'DC.Date'})):?><meta name="DC.Date" content="<?php echo $meta{'DC.Date'};?>" />
<?php endif;?>
<?php if(!empty($meta{'DC.Format'})):?><meta name="DC.Format" content="<?php echo $meta{'DC.Format'};?>" />
<?php endif;?>
<?php if(!empty($meta{'google-site-verification'})):?><meta name="google-site-verification" content="<?php echo $meta{'google-site-verification'};?>" />
<?php endif;?>
<?php if(!empty($min_css)):?><link href="<?php echo !empty($cdn) ? 'http://'.$cdn.'/'.$min_css:'http://'.$host.'/'.$min_css;?>" rel="stylesheet" type="text/css" />
<?php endif;?>
<?php if(!empty($js_ext)):foreach($js_ext as $v){?><script type="text/JavaScript" src="<?php echo $v;?>"></script>
<?php }?>
<?php endif;?>
<?php if(!empty($min_js)):?><script type="text/JavaScript" src="<?php echo !empty($cdn) ? 'http://'.$cdn.'/'.$min_js:'http://'.$host.'/'.$min_js;?>"></script>
<?php endif;?>
<?php if($favicon==true):?><link rel="icon" type="image/png" href="<?php echo !empty($cdn) ? 'http://'.$cdn.'/favicon.ico':'http://'.$host.'/favicon.ico';?>" />
<?php endif;?>
</head>
<body>
<?php echo $body;?>
</body>
</html>


Création de votre page monTest/index/


Il faut créer le fichier monTest.php dans le répertoire controllers, et mettre le code suivant

require_once 'doctype_html.php';

class MonTest extends Doctype_html{

function __construct(){
parent::__construct('_config_html.ini.php');
}



public function index(){
//print_r($this->param);
$this->send();

}
}

Vous comprendrez que dans le code précédent, on charge le fichier de configuration '_config_html.ini.php' dans le constructeur du contrôleur monTest qui est hérité de Doctype_html.
Dans la fonction index, vous pourrez visualisez les valeurs des variables de la page, grâce à print_r($this->param);.
De plus, si vous allez dans la page http://localhost/[APP]/monTest/index/, vous verrez une page blanche (parce qu'il n ' a pas de contenu), mais, via firebug, vous aurez le code html suivant:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="jp" lang="jp" >
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>My website</title>
<meta name="description" content="coucou" />
<link href="http://cdn.toto.com/toto.css" rel="stylesheet" type="text/css" />
<script type="text/JavaScript" src="http://cdn.toto.com/titi.js"></script>
<link rel="icon" type="image/png" href="http://cdn.toto.com/favicon.ico" />
</head>
<body>
</body>
</html>

Vous voyez le titre de la page My website.

Modifier les variables dynamiquement


Question, allons nous créer un fichier _config_html.ini.php par page ? et bien non, ce n'est pas obligatoire, et cela est même déconseillé pour du très grand contenu (milliers de pages ^^).
En fait il est possible de modifier tous les valeurs de ces variables dynamiquement, nous allons modifier le title de la page avec le code suivant, à mettre dans la fonction index():

$this->_title('nouveau titre');
$this->send();

Vous devriez voir dans la balise title :'nouveau titre'.
En fait, vous précédez le nom de la variable par le caractère underscore. donc pour le title, faire:
$this->_title('[TITLE]');


pour la langue, faire:
$this->_lg('[LANGUE]');


, pas compliqué ... non ?
et pour le contenu, c'est :
$this->_body('[CONTENU]');

A priori, vous n'aurez pas besoin d'utiliser la variable body dans la méthode index(), nous verrons pourquoi dans la section suivante ...

Pour faire un récap des possibilités de manipulation, d'abord vous charger le fichier de configuration de votre page internet, puis si des paramètres ne vous plaisent pas, comme le titre de la page, vous la modifiez à la volé ! C'est la classe, non ?

Composants d'une page internet


Il y a une chose que nous avons oublié est qu'une page internet est composé d'éléments qui sont placé au même endroit: header en haut, footer en bas, menu à gauche ou sous le header ...

Pour faire simple, nous allons créer une structure simplifié :
header/menu/contenu/extra/footer superposé les uns sur les autres.
extra, situé entre contenu et footer s'affichera uniquement pour la page monTest/index, et non pas sur une autre page.

dans le répertoire views, nous allons 5 fichiers:
gb_content.php:
<div style="border:1px solid blue;margin: 5px;padding :5px;color:blue;"><h2><?php echo $content;?></h2></div>


gb_extra.php:

<?php echo$_SERVER{'REQUEST_URI'};if($_SERVER{'REQUEST_URI'}=='/bimpoo/monTest/index.html'){?><div style="border:1px solid green;margin: 5px;padding: 5px;color:green;"><h2>EXTRA</h2></div><?php }?>


gb_footer.php:

<div style="border:1px solid red;margin: 5px;padding :5px;color:red;"><h2>FOOTER</h2></div>


gb_header.php:

<div style="border:1px solid red;margin :5px;padding :5px;color:red;"><h2>HEADER</h2></div>


gb_menu.php:

<div style="border:1px solid red;margin :5px;padding: 5px;color:red;"><h2>MENU</h2></div>


Nous allons remplacer la méthode index par la suivante:


public function index(){
$this->param{'content'} = 'COUCOU !';
$this->send();
}

Nous ajoutons la variable content qui sera le contenu de la page internet, puis nous appelons la focntion send pour générer la page internet et la renvoyer. Nous allons créer une méthode similaire index2() avec le même contenu que index(). Si nous générons la page monTest/index, il n y aura toujours qui s'affichera car on n' a pas encore chargé les vus... !

pour cela, il faut ouvrir le fichier doctype_html.php et aller à la méthode send()
sur le fichier, il y avait juste:

echo $this->load->view('tpl_html',$this->param);


C'est avant cette ligne de code que nous allons rajouter toutes les autres vues, avec le code suivant:

$html = $this->load->view('gb_header',$this->param,true);
$html .= $this->load->view('gb_menu',$this->param,true);
$html .= $this->load->view('gb_content',$this->param,true);
$html .= $this->load->view('gb_extra',$this->param,true);
$html .= $this->load->view('gb_footer',$this->param,true);
$this->_body($html);
echo $this->load->view('tpl_html',$this->param);

nous chargeons toutes les vues dans la variable $html que nous mettons ensuite dans la variable body ! puis nous générons la page internet.
C'est donc ici que vous allez imposer une structure (ou plusieurs structure si vous répliquez le fonction send()) d'une page internet !
N'oubliez que chaque vu se gérée d'elle même, dans le but de simplifier le traitement du contrôleur et de lui dédier uniquement le contenu principale de la page : par exemple pour activer l'onglet d'un menu en fonction de l'url, il vous suffit de rajouter une variable dans $this->param (par exemple $this->param{'onglet_actif'}) et lui attribuer le nom du contrôleur.

$this->param{'onglet_actif'} = __method__;

ensuite, vous le récupérez dans la vue et faire le traitement adéquate ...

voici le résultat de la page monTest/index :







Et la, le résultat de la page monTest/index2

Si vous avez remarquez le code dans le fichier gb_extra, le code html est entouré de balises php. Ces balisent testent pour savoir si l'url est celle de monTest/index ou pas. Si c'est oui, alors le code html est affiché !

Conclusion


J'espère que vous aurez compris l'intérêt de ce tutoriel : Vous faire gagner du temps et rendre le projet facile à maintenir !
Voilà, si vous êtes arrivé là, alors vous etiez un vrai warior ! N'hésitez pas à me contacter pour plus d'info ou pour des corrections !