Séparer le code PHP du HTML : besoin d'avis / conseils

Mammouth du PHP | 531 Messages

17 mai 2008, 23:50

Bonjour,

Etant sur un projet personnel que je m'efforce de coder le mieux possible... avec les connaissances et l'expérience que j'ai bien entendu, ça ne veut donc pas dire que c'est bien codé. Mais bon j'essaye :D

Le point qui me tarode en ce moment c'est ma façon de faire pour essayer de séparer le code PHP du reste, donc du HTML et de la mise en page. Je procède de cette façon :
- Tout ce qui est traitement, requêtes et action se situe en haut de page.
- J'évite de mettre du code HTML dans mes variables mais quelques fois je n'ai pas le choix...
- Je me sert de la concaténation pour éviter de faire des boucles en pleins millieu du HTML
- Je n'affiche pas le code HTML via php, mais je fais plutôt plusieurs <?php ?> dans le HTML ( Un mauvais point au passage puisque niveau optimisation c'est bof... ).

Voilà dans les grandes lignes. J'aurais bien voulu avoir quelques avis de codeurs plus expérimentés pour savoir si je ne suis pas trop à coté de la plaque. :roll:

Voici un exemple complet puisque j'ai dans mon code les choses que j'utilise fréquemment : Constantes, résultat de requêtes, includes, concaténation
<?php
include 'inc_php/common.php';
#### Initialisation variables
$MenuPrincipal = NULL;
#### Construction du menu
$ReqSections = "SELECT id_sections, nom 
FROM zcms_sections 
WHERE etat = 1 
ORDER BY ordre";
$ResSections = mysql_query( $ReqSections ) or die( mysql_error());
while( $ValSections = mysql_fetch_array( $ResSections ) )
{
	$section = $ValSections['id_sections'];
	$MenuPrincipal .= '<h2>'.$ValSections['nom'].'</h2>'; // Titre de la section
	$ReqPages = "SELECT id_pages, nom 
	FROM zcms_pages 
	WHERE id_sections = $section AND etat = 1 
	ORDER BY ordre";
	$MenuPrincipal .= '<ul class="menu">';
	$ResPages = mysql_query( $ReqPages ) or die( mysql_error());
	while( $ValPages = mysql_fetch_array( $ResPages ) ) // Liens de la section
	{
		$MenuPrincipal .= '<li><a href="index.php?page='.$ValPages['id_pages'].'">'.$ValPages['nom'].'</a></li>';
	}
	$MenuPrincipal .= '</ul>';
}
#### Si $page est posté en GET
if ( isset( $_GET['page'] ) )
{
	// Récupération contenu page selectionée
	$IdPage = mysql_real_escape_string( $_GET['page'] );
	$ReqPage = "SELECT nom, description, contenu, mod_news 
	FROM zcms_pages  
	WHERE id_pages = $IdPage AND etat = 1";
	$ResPage = mysql_query( $ReqPage ) or die(mysql_error());
	$ValPage = mysql_fetch_array( $ResPage );
}
#### Si $page est pas posté en GET
else
{
	// Récupération page par défaut, par rapport à l'ordre de sa section et à son propre ordre
	$ReqPage = "SELECT nom, description, contenu, mod_news 
	FROM zcms_pages 
	WHERE etat = 1 
	ORDER by ordre LIMIT 0,1";
	$ResPage = mysql_query( $ReqPage ) or die(mysql_error());
	$ValPage = mysql_fetch_array( $ResPage );
}
#### Options affichage page
if ( AFFICHER_TITRE == 1 )
{
	$TitrePage = $ValPage['nom'];
}
else
{
	$TitrePage = NULL;
}
if ( $ValPage['description'] == NULL )
{
	$DescriptionPage = DESCRIPTION_SITE;
}
else
{
	$DescriptionPage = $ValPage['description'];
}
$ContenuPage = $ValPage['contenu'];
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title><?php echo NOM_SITE.' : '.$TitrePage; ?></title>
<meta name="description" content="<?php echo $DescriptionPage; ?>" />
<meta name="keywords" content="<?php echo MOTSCLES_SITE; ?>" />
<style>
@import"<?php echo THEME_SITE; ?>";
@import"utilisateur/styles.css";
</style>
</head>
<body>
<div id="containeur">
<div id="header">
<h1><a title="<?php echo DESCRIPTION_SITE; ?>" href="<?php echo URL_SITE; ?>"><?php echo NOM_SITE; ?></a></h1>
</div>
<div id="colonne">
<?php echo $MenuPrincipal; ?>
</div>
<div id="block_principal">
<?php include 'news_liste.php'; ?>
<div id="page">
<h1><?php echo $TitrePage; ?></h1>
<?php echo $ContenuPage; ?>
</div>
</div>
<?php include 'inc_pages/footer.php'; ?>
</div>
</body>
</html>

Mammouth du PHP | 881 Messages

18 mai 2008, 04:27

Je fais ainsi aussi quand je n'ai pas beaucoup de PHP à insérer dans le HTML, mais parfois ça devient tellement lourd que je passe à autre chose: un immense echo qui englobe tout et qui passe les codes HTML.

À mon avis, ça dépend toujours du ration PHP / HTML
Soyez artisans de paix

Eléphant du PHP | 224 Messages

18 mai 2008, 05:34

Bonjour :)

Il y a aussi la méthode du modèle, ou template, qui consiste à préparer le maximum possible son code Html en y insérant des balises personnalisées qui seront ensuite remplacées, juste avant l'affichage, par les contenus dynamiques générés par le Php.

Voici un exemple minimaliste :
<?php
// Modele de page Html avec balisage du contenu
$modele = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 TRANSITIONAL//EN">
<html>
	<head>
		<title><!--titre--></title>
	</head>
	<body>
		<div>
			<p><!--texte_01--></p>
			<p><!--texte_02--></p>
		<div>
	</body>
</html>';

// Tableau des balises a remplacer
$recherche[] = '<!--titre-->';
$recherche[] = '<!--texte_01-->';
$recherche[] = '<!--texte_02-->';

// Tableu des contenus de remplacement
$remplace[] = 'Un joli titre !';
$remplace[] = 'Non equidem insector delendave carmina Livi esse reor, 
memini quae plagosum mihi parvo Orbilium dictare; 
sed emendata videri pulchraque et exactis minimum distantia miror.';
$remplace[] = 'Inter quae verbum emicuit si forte decorum, 
et si versus paulo concinnior unus et alter, 
iniuste totum ducit venditque poema.';

// Remplacement des balises par les contenus correspondants avant affichage
$affichage = str_replace($recherche, $remplace, $modele);

// Affichage
echo $affichage;
?>
Le principe de cet exemple est relativement simple : un modèle Html avec des balises personnalises, un tableau reprenant l'ensemble des balises personnalisées et, enfin, un autre tableau avec les données correspondantes de remplacement... un simple "str_replace" juste avant affichage, et le tour est joué... ;)

Évidemment, il faut trouver un système de balisage suffisamment souple et précis pour être utilisé dans des projets de différente envergure... Ici, j'ai opté par un balisage sous forme de commentaires Html, qui a l'avantage de rester invisible en cas de mauvais traitement lors du rechercher/remplacer...

D'autres méthodes de travail avec les modèles existent bien-sûr, on peut même trouver des projets assez puissants et aboutis sur le net.

Bon, cette technique ne fait pas totalement l'économie du Html dans le Php, certaines choses sont plus simples à réaliser sans passer par des modèles, comme les listes ou tableaux, mais on peut déjà imaginer des modèles pour le gros du code Html, et le reste est fait dans le Php...

Perso, je n'ai pas encore une préférence marquée pour une méthode ou l'autre, je les mélange allègrement d'ailleurs, mais je me doute que pour des projets un peu ambitieux, il faut choisir une méthode et l'utiliser sans trop faire des mélanges pour essayer de trouver une certaine cohérence dans le code, ce qui est toujours plus facile à faire évoluer ou entretenir...

Bref, c'est une question de choix finalement...

à+ :)
Fredo d;o)
"Un pas à la fois me suffit..." (Gandhi)

Mammouth du PHP | 531 Messages

18 mai 2008, 11:50

Merci pour vos réponses.
Bon je suis rassuré dans le sens ou je ne suis pas seul à faire comme ça.
Sinon les templates c'est surement une solution plus propre mais il faut que j'étudie un peu des projets existants pour comprendre comment organiser tout ça ^^

Autre question qui n'a rien à voir :
Faut-il laisser les or die dans les requêtes ou doit-on s'en servir uniquement au stade du développement ?
Car si on réfléchis bien un or die peut donner des informations à une personne ma intentionnée...

d0m
Mammouth du PHP | 1141 Messages

18 mai 2008, 12:03

il vaut mieux enlever les messages d'erreurs de ce type, c'est surtout pour toi en phase de développement.

Après tu peux gérer les erreurs toi même et mettre des messages appropriés.

Mammouth du PHP | 1668 Messages

18 mai 2008, 14:29

Y a une autre méthode aussi, c'est la POO, qui permet de séparer la logique de l'affichage...
"À ceux qui poursuivent leurs rêves et se spécialisent dans l'impossible" Joseph Kong

10 ans de PHP, déjà.

"moi jtrouve que katagoto il déchire!" Nagol

Eléphant du PHP | 224 Messages

18 mai 2008, 15:52

Re...
Y a une autre méthode aussi, c'est la POO, qui permet de séparer la logique de l'affichage...
Je ne suis nullement spécialiste, mais je ne crois pas que la POO (Programmation Orientée Objet), soit en soi une méthode qui permette à elle seule de résoudre les problèmes inhérents à l'intégration Html<->Php, on a déjà tous vu des codes basés sur la POO et qui, pourtant, utilisent amplement du Html dans leur classes et méthodes... bref, ce que je veux dire, c'est que développer en POO n'est pas forcément une garantie d'une architecture d'intégration Html<->Php réussie...

En revanche, puisque j'en ai pas mal entendu parler, il me semble que ce qui se rapproche d'avantage à une séparation claire et "propre" entre logique, données et présentation, est l'architecture MVC (Modèle Vue Contrôleur), où, grosso-modo, le Modèle représente les données à traiter et à exploiter, la Vue est l'affichage ou représentation de ces données, et le Contrôleur est le programme à proprement parler qui gère tout ce petit monde...

Dans le cadre d'un développement sous architecture MVC, que ce soit en POO ou pas (même si la POO semble justement bien indiquée pour ce type de développement), on peut bien séparer tout ce qui est l'affichage Html du code d'exécution en Php (c'est d'ailleurs un peu le but quand-même) et, le plus souvent, le solutions basées sur ce type d'architecture, utilisent des systèmes de gabarits ou templates pour construire les pages Html à publier...

Enfin, tout ceci reste encore au stade de la pure théorie en ce qui me concerne, n'ayant absolument aucune expérience en développement POO ou en architecture MVC, je ne parle donc pas en véritable connaissance de cause, mais suite aux quelques lectures faites ci-et-là sur le net... mais il me semble en tout cas très utile que nous puissions en parler librement, afin de clarifier au mieux ces concepts et éviter ainsi les confusions qui peuvent parfois enduire en erreur...

Bref, en deux mots et suivant mes connaissances actuelles, je dirais, le plus simplement possible, que la POO est une méthode de développement alors que la MVC est une architecture d'application. Les deux pouvant bien-sûr cohabiter, mais pas nécessairement.

Maintenant, pour revenir au sujet principal de cet échange, je suis plutôt d'accord avec Patriboom, le choix du type d'intégration Html<->Php doit répondre à plusieurs critères, dont l'importance et la complexité du projet et le ratio de code de chaque langage, car toutes les solutions, aussi pertinentes soient-elles, ne peuvent répondre à tous les cas de figure (on va rarement recourir à un système complexe de gabarits Html pour afficher un simple compteur dynamique en bas de page... non ? :shock: :D )...

à+ :)
Fredo d;o)
"Un pas à la fois me suffit..." (Gandhi)

ViPHP
AB
ViPHP | 5818 Messages

18 mai 2008, 19:58

@supercanard

Sur le principe ça à l'air correct. Quelque soit la méthode que tu emploies, le principal est que tu puisse gérer facilement l'ensemble de ton code. Apparemment ça à l'air d'être le cas dans ce que tu nous montre.
Juste une petite critique concernant la présentation du code. En faisant quelques indentations et sauts de lignes ce serait un plus facile à lire et à comprendre.

lux
Eléphant du PHP | 372 Messages

18 mai 2008, 20:21

Au début, pour mes premiers sites, je codais comme supercanard.

Par la suite, j'ai eu des pages de plus en plus complexes, et je suis passé au templates, smarty en l'occurrence. Depuis je ne peux plus m'en passer :wink:

Mammouth du PHP | 531 Messages

18 mai 2008, 21:07

Merci à tous pour vos réponses =)

Bon pour commencer à m'habituer aux templates j'ai suivis la méthode de FredoMkb.
Le tout avec une avec un index qui contient le doctype et tout ça, ça me parrait beaucoups mieux :
<?php
#### Initialisation variables
#### Si $page est posté en GET
if ( isset( $_GET['page'] ) )
{
	// Récupération contenu page selectionée
	$IdPage = mysql_real_escape_string( $_GET['page'] );
	$ReqPage = "SELECT nom, description, contenu, mod_news 
	FROM zcms_pages  
	WHERE id_pages = $IdPage AND etat = 1";
	$ResPage = mysql_query( $ReqPage );
	$ValPage = mysql_fetch_array( $ResPage );
}
#### Si $page est pas posté en GET
else
{
	// Récupération page par défaut, par rapport à l'ordre de sa section et à son propre ordre
	$ReqPage = "SELECT nom, description, contenu 
	FROM zcms_pages 
	WHERE etat = 1 
	ORDER by ordre LIMIT 0,1";
	$ResPage = mysql_query( $ReqPage );
	$ValPage = mysql_fetch_array( $ResPage );
}
#### Options affichage page
if ( AFFICHER_TITRE == 1 )
{
	$TitrePage = '<h1>'.$ValPage['nom'].'</h1>';
}
else
{
	$TitrePage = NULL;
}
### Template
// Ouverture template
$template = 'tpl/pages.htm';
$fichier = fopen( $template, 'r' );
$html = fread( $fichier, filesize( $template ) );
fclose ( $fichier );
// Tableau des éléments à remplacer
$recherche[] = '%%TITRE_PAGE%%';
$recherche[] = '%%CONTENU_PAGE%%';
// Eléments de remplacement
$remplacement[] = $TitrePage;
$remplacement[] = $ValPage['contenu'];
// Remplacement
$html = str_replace( $recherche, $remplacement, $html );
// Affichage
echo $html;
?>

Eléphant du PHP | 224 Messages

19 mai 2008, 00:41

Re...
Bon pour commencer à m'habituer aux templates j'ai suivis la méthode de FredoMkb.
Oui... bon, n'exagérons rien non plus :shock: ... ce n'est pas "ma" méthode, disons que c'est une de celles que j'utilise, mais je ne suis en rien l'inventeur (manquait plus que ça :D )...
... ça me parrait beaucoups mieux :


Oui, je trouve ton code un peu plus clair désormais, et j'imagine c'est la cas pour toi aussi... ça a l'air d'être une piste intéressante dans le cadre de ton projet donc... en avant toutes alors ! ;)

à+ :)
Modifié en dernier par FredoMkb le 19 mai 2008, 09:45, modifié 1 fois.
Fredo d;o)
"Un pas à la fois me suffit..." (Gandhi)

Eléphant du PHP | 145 Messages

19 mai 2008, 09:29

Merci pour ce topic très enrichissant.
En effet, il y a beaucoup de façon pour développer une page, et la mienne je l'a trouve un peu Barbare et lorsque que je code des pages énormes, on pourrais croire qu'elle sont crypter :P.

Cependant, je vais essayer de m'orienter vers une de vos technique ;)

Albat90 ;)
La culture, c'est comme la confiture, moins on en a, plus on l'étale.

Mammouth du PHP | 531 Messages

19 mai 2008, 23:47

J'ai une petite question interessante pour en revenir aux templates. En tous cas elle m'intéresse car si le but et de séparer le code de la mise en forme elle est intéressante ;)

Imaginons que le but est de récupérer une liste de nom, et de l'afficher sous forme de liste. Et surtout qu'aucune balise <li></li> n'apparaisse donc dans le tableau stockant ces noms ( $nom[] )
$ReqPage = "SELECT nom FROM zcms_pages";
$ResPage = mysql_query( $ReqPage );
while ( $ValPage = mysql_fetch_array( $ResPage ) )
{
$nom[] = $ValPage['nom'];
}
### Template
// Ouverture template
$template = 'tpl/pages.htm';
$fichier = fopen( $template, 'r' );
$html = fread( $fichier, filesize( $template ) );
fclose ( $fichier );
// Tableau des éléments à remplacer
$recherche[] = '%%NOM%%';
// Eléments de remplacement
$remplacement[] = $nom[];
// Remplacement
$html = str_replace( $recherche, $remplacement, $html );
// Affichage
echo $html;
Dans ma template j'ai ceci et le hic c'est que je ne connais pas à l'avance le nombre de noms... :

Code : Tout sélectionner

<ul> <li>%%NOM%%</li> </ul>
La je suis bien bloqué :D

Mammouth du PHP | 881 Messages

20 mai 2008, 00:24

Simple remarque comme ça, l'utilisation de % comme marqueur de balise peut facilement porter à confusion avec du code MySQL, puisque % est le jocker MySQL. La proposition qui est faite en début de discussion me semble plus pratique ( <!-- ) car c'est un marqueur de remarque en HTML ce qui fait en sorte que si tu loupes ton code d'interprétation, ta balise reste cachée (en remarque) dans le HTML, reste présente, reste inerte, reste repérable et tout cela sans entrer en conflit avec un autre langage fort utile.
Soyez artisans de paix

Eléphant du PHP | 224 Messages

20 mai 2008, 00:30

Bonsoir :)
Imaginons que le but est de récupérer une liste de nom, et de l'afficher sous forme de liste. Et surtout qu'aucune balise <li></li> n'apparaisse donc dans le tableau stockant ces noms ( $nom[] )
[...]
Dans ma template j'ai ceci et le hic c'est que je ne connais pas à l'avance le nombre de noms... :
[...]
La je suis bien bloqué :D
Et oui... ça devait arriver :D ... c'est pourquoi lors de ma première intervention je notais :
Bon, cette technique ne fait pas totalement l'économie du Html dans le Php, certaines choses sont plus simples à réaliser sans passer par des modèles, comme les listes ou tableaux, mais on peut déjà imaginer des modèles pour le gros du code Html, et le reste est fait dans le Php...
On peut aussi ajouter les "select" et leurs "options" dans les formulaires... bref, tout ce qui fonctionne sous forme de liste ou tableau de données, est assez difficile à "modéliser" ou "templater", car, fatalement, on doit insérer des balises entre les items, dont on ne connaît pas forcément le nombre au départ, et que ceci serait bien trop laborieux à faire avec notre première approche des templates...

C'est aussi la raison pour laquelle les gros système de templates ont imaginé des solutions en intégrant des balises qui déclenchent des boucles pour pouvoir construire ces contenus Html dynamiques difficilement réalisables autrement...

Moralité, soit le projet est important et mérite qu'on prenne une solution de templates pro, Smarty étant un des plus populaires et aboutis, mais il y en a d'autres, soit on bricole une solution fait maison mais alors on doit se résoudre à faire quelques concessions pour que ça ne devienne pas rapidement une véritable usine à gaz... :shock:

C'est toujours une question de choix... et les critères peuvent être si nombreux et variés, qu'il faudra adapter son choix en conséquence... pas toujours évident... je sais ;)

à+ :)
Fredo d;o)
"Un pas à la fois me suffit..." (Gandhi)