[php5]classe de template php avec cache

Soyez le premier à donner votre avis sur cette source.

Vue 15 942 fois - Téléchargée 411 fois

Description

Bonjour,
je soumets à votre critique un moteur de template en PHP :
- aucune nouvelle synthaxe à apprendre ;
- aucun traitement supplémentaire ;
- gain de ressource ;
- séparation de la logique et de la présentation ;
- toute la flexibilité et la puissance de PHP peut etre utilisé ;
- ajout d'une simple variable ;
- ajout de plusieurs variables simultanément ;
- ajout de résultat d'une requête SQL ;
- boucle imbriqué illimité ;
- imbrication de template illimité ;
- gestion d'un système de cache pour optimiser l'affichage ;

Mais voilà, j'aimerai avoir votre avis afin de savoir s'il est réellement optimisé ou si on peut encore l'améliorer ;)

Source / Exemple :


<?php

class Template 
{
	private $path = null;
	private $vars = array();

	public function __construct($path = null)
	{
		if (isset($path))
		{
			$this->setPath($path);
		}
	}

	public function setPath($path)
	{
		$path  = trim($path, '/\\');
		$path .= DIR_SEP;

		if (!is_dir($path))
		{
			throw new Exception ('Chemin du dossier template incorrect : `' . $path . '`');
		}

		$this->path = $path;
	}
		
	function setVar($name, $value)
	{
		$this->vars[$name] = $value;
	}

	function setVars($vars, $clear = false)
	{
		if($clear === true)
		{
			$this->vars = $vars;
		}
		else
		{
			if(is_array($vars))
			{
				$this->vars = array_merge($this->vars, $vars);
			}
		}
	}

	function fetch($file)
	{
		extract($this->vars);
		
		ob_start();
		
		include($this->path . $file);
		
		$contents = ob_get_contents();
		
		ob_end_clean();
		
		return $contents;
	}
}

?>

<?php

class Cache
{
	private $path = null;
	
	public function __construct($path = null)
	{
		if (isset($path))
		{
			$this->setPath($path);
		}
	}
	
	public function setPath($path)
	{
		$path  = trim($path, '/\\');
		$path .= DIR_SEP;

		if (!is_dir($path))
		{
			throw new Exception ('Chemin du dossier cache incorrect : `' . $path . '`');
		}

		$this->path = $path;
	}
	
	public function setCache($file, $contents)
	{
		$filename = $this->path . md5($file);
		
		$contents = serialize($contents);
		
		if (!file_put_contents($filename, $contents))
		{
			throw new Exception('Impossible de mettre en cache : `' . $file . '`');
		}
	}
	
	public function getCache($file)
	{
		$filename = $this->path . md5($file);

		if (file_exists($filename))
		{
			$contents = file_get_contents($filename);
			$contents = unserialize($contents);
			return $contents;
		}
		else
		{
			return false;
		}
	}
	
	public function destroy($file)
	{
		$filename = $this->path . md5($file);
		@unlink($filename);
	}
}

?>

Conclusion :


l'exemple :

Code : PHP

// inclusion de la classe template
require('includes/template.php');

// inclusion de la classe Cache
require('includes/cache.php');

// nouvelle instance de la classe Template
$tpl = new Template('templates');

// nouvelle instance de la classe Cache
$cache = new Cache ('cache');

// on assigne une simple variable 'bonjour'
$tpl->setVar('bonjour', 'Bonjour tout le monde !');

// on assigne plusieurs variable simultanément 'hello' et 'salut'
$bonjour = array('hello' => 'hello tout le monde !', 'salut' => 'salut tous le monde !');
$tpl->setVars($bonjour);

// supposons que l'array $user_list provienne d'une base de donnée...
// pour eviter d'utiliser des ressources inutilement, on va mettre
// en cache le résultat de la requête

// les résutats sont-ils en cache ? si oui on les
// récupère à partir du fichier et non de la requête
if (!$user_list = $cache->getCache('user_list'))
{
// mysql_connect, ETC...
$user_list = array(
1 => array(
'id' => 1,
'nom' => 'jean'),
2 => array(
'id' => 2,
'nom' => 'vincent'),
3 => array(
'id' => 3,
'nom' => 'maxime')
);
// on met en cache le résultat
$cache->setCache('user_list', $user_list);
}

// on l'assigne comme variable 'user_list'...
$tpl->setVar('user_list', $user_list);

// on compile le template user_list
$user_list_render = $tpl->fetch('user_list.php');

// et on l'assigne comme variable user_list_render...
$tpl->setVar('user_list_render', $user_list_render);

// on affiche la page entière
echo $tpl->fetch('exemple.php');

l'exemple (exemple.php) :

Code : PHP

<!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>Exemple de la classe template</title>
</head>

<body>
<?php echo $bonjour; ?>
<br />
<?php echo $hello; ?>
<br />
<?php echo $salut ?>
<br />
<?php echo $user_list_render; ?>
</body>
</html>

l'exemple (user_list.php) :

Code : PHP

<table>
<tr>
<th>Id</th>
<th>Nom</th>
</tr>
<?php foreach($user_list as $user): ?>
<tr>
<td><?php echo $user['id'];?></td>
<td><?php echo $user['nom'];?></td>
</tr>
<?php endforeach; ?>
</table>

On aurait pu aussi mettre en cache la page entière, mais vous avez compris le fonctionnement...
L'intérêt d'un tel système de cache et de permettre de générer par exemple un fichier XML à partir des résultats mis en cache par exemple.

!!! ATTENTION !!!

Le cache n'a pas de durée de vie, pour le mettre à jour :

Lors d'une requête d'ajout (vos pages de post/edition de messages, de news, etc.) inclure :

$cache->destroy('nom_du_fichier_ou_vous_avez_mis_le_cache);

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

FhX
Messages postés
2350
Date d'inscription
mercredi 13 octobre 2004
Statut
Membre
Dernière intervention
18 avril 2015
3 -
Je parlais du public/private au départ, mais avec Coucou on parlait du manque niveau POO :)
hametsu21
Messages postés
41
Date d'inscription
mardi 1 novembre 2005
Statut
Membre
Dernière intervention
24 février 2008
-
j'ai pas trop compris vos recommendations. Sont-elles de l'ordre générale sur PHP et ses possibilités en POO ou de la source ?
FhX
Messages postés
2350
Date d'inscription
mercredi 13 octobre 2004
Statut
Membre
Dernière intervention
18 avril 2015
3 -
En effet, ca manque aussi.
D'après ce que j'ai lu, il semblerait que ce soit pour PHP6.

Peut être :)
coucou747
Messages postés
12336
Date d'inscription
mardi 10 février 2004
Statut
Modérateur
Dernière intervention
30 juillet 2012
27 -
et mettre une classe dans un namespace ? :)

je ne parlais pas seulement de l'overloading de functions, mais aussi d'operator, faire :
$a=new Vector(1, 3, 5);
$b=new Vector(5, 3, 1);
$c=$a+$b;
comme on peut le faire en Cpp... moi ca me manque (d'autant plus que j'ai fait quelques classes lignes pour positionner des points en "live")
FhX
Messages postés
2350
Date d'inscription
mercredi 13 octobre 2004
Statut
Membre
Dernière intervention
18 avril 2015
3 -
"Si ce n'est pas le cas, rien ne dit que les évolutions de l'application ou de l'objet n'amèneront pas ces contraintes."

Si on utilise les propriétés publiques, on se doute bien qu'au final il n'y aura pas d'évolution dans ce domaine. Je m'explique.
Prenons le cas d'une propriété de débug. Pas besoin de get/set pour du débug, on s'en carre le cornichon :)
Même si il y a évolution du projet derrière :

class x {
public $debug = false;
//
}
class y extends x {
//
}

$y = new y;
$y->debug = true;

Bon et voila :)
Dans ce cas la, le "public" fonctionne très bien et tu n'as pas besoin de faire :
$y->setDebug(true); ou $y->ActiveDebug();
C'est une perte de temps :o

Comme dit Coucou, ce qui manque, c'est la redéclaration des méthodes. Rien de plus beau (comme en Java) de faire :
public function __construct($var);
public function __construct($var, $truc);
public function __construct(Object $x, Object $y);
Sans avoir à se faire chier avec func_*() et autre fonction de ce genre.
Le namespace, tu peux y arriver via le statissisme :
class x {
static public function x1();
}

x::x1();
Et tu peux très bien arriver à un résultat de ce genre :
x::x1()->...()->...->...::...()->...();
Techniquement, je crois que ca passe.

Pour en revenir plus, chacun est libre de faire comme il veut.
Pour ma part, c'est simple :
abstract class Item {
public $debug = false;
}
abstract class Factory extends Item {
//
}
abstract class Element extends Item {
//
}
class NewsFactory extends Factory {
//
}
class News extends Element {
//
}

Pas besoin de m'ennuyer avec des méthodes qui servent à rien :)

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.