Monthly Archives

3 Articles

Validateur de dates

Certains d’entre vous ont voulu à plusieurs reprises faire un formulaire avec différents champs de Dates. L’une devant être inférieure à l’autre comme une date d’emménagement et de déménagement.

Bien évidement, le framework Zend a pensé à tout ceci avec le composant Zend_Date mais n’a pas pensé aux formulaires. Il n’y a pas de validateur connu (pour le moment) servant à ceci.

C’est pourquoi, dans le but d’en avoir un sous la main et aussi car j’en avais surtout besoin, je créai un validateur de dates. Il me permet de différencier deux champs contenant une date (de préférence des datepickers jQuery ou Dojo) et dire si oui ou non la date 1 est plus ancienne que la date 2.

Voici d’ailleurs le code du validateur:
/**
* App_Validate_Date
*
* Classe servant à faire la différene entre 2 dates
*
* Retournera True si valide
* False si faux
*
*/
class App_Validate_Date extends Zend_Validate_Abstract
{
const FALSEDATE = "falseDate";
const ILLEGALDIFF = "illegalDiff";

protected $_messageTemplates = array(
self::FALSEDATE =>
"False Date: L'une des dates est invalide",
self::ILLEGALDIFF =>
"ILLEGAL DIFF: La date d'emmenagement est plus récente que la date de déménagement"
);

/**
* la date de départ
*
* @var unknown_type
*/
protected $_date;

/**
* sert à instancier le validateur
*
* @param unknown_type $date
*/
public function __construct($date)
{
$this->setdate($date);
}

/**
* @return unknown_type
*/
public function getdate()
{
return $this->_date;
}

/**
* Setteur = initialiser la variable avec celle passée en paramètre
* @param unknown_type $_date
*/
public function setdate($_date)
{
$this->_date = $_date;
}

public function isValid($value)
{
$this->_setValue($value); //à laisser obligatoirement

if(Zend_Date::isDate($value, 'dd/mm/yy', 'fr_FR') && Zend_Date::isDate($this->_date, 'dd/mm/yy', 'fr_FR'))
{
$datevalue = new Zend_Date($value, 'fr_FR'); //on instancie une date de la valeur
$datedate = new Zend_Date($this->_date, 'fr_FR'); //on instancie la date

$testdate = $datedate->sub($datevalue);

if($testdate < 0) { return true; } else { $this->_error(self::ILLEGALDIFF);
return false;
}
}
else
{
$this->_error(self::FALSEDATE);
return false;
}

}

}
Pour l’utiliser, je n’ai pu le faire que du côté contrôleur. Il faut bien récupérer les deux valeurs après avoir posté le forum. Et voici donc les étapes à effectuer pour que cela marche.
if($this->_request->isPost())
{
$formdata = $this->_request->getPost();

$validator = new Zend_Validate(); //créer un validateur vide
$validator->addValidator(new Zend_Validate_Date('dd/mm/yy', 'fr_FR')); //ajout du validateur de verif date en 1°
$validator->addValidator(new App_Validate_Date($this->_request->getPost('date_debut'))); //ajoute le validateur de diff date en second

$form->date_fin->addValidator($validator); //ajoute la chaine de validateur afin de tous les verifier

if($form->isValid($formdata)) // ce isvalid appelle le isvalide du formulaire pour exécuter à la chaine tous les validateurs
{
//suite du traitement du formulaire
}
}

J’espère que ce validateur vous aidera dans vos projets. Si vous comptez l’améliorer, prévenez moi en m’envoyant les améliorations apportées.

Headers – Compression CSS

Bonjours, je commence une série d’articles pour vous montrer la solution mise en place pour compresser les en-têtes de votre site.

Attention, pour le moment la solution n’est pas encore 100% fonctionnelle, à l’heure où j’écris ces lignes, sur le site je fonctionne encore avec le Zend_Cache utilisant les fichiers. En local, je travail avec Zend_Cache utilisant le cache APC. Certains problèmes me sont apparus avec les fichiers et ils ont disparus avec APC.

Donc tout d’abord je vais vous présenter le filtre que j’utilise pour compresser le contenu de mes fichiers CSS, ensuite je vous présente la méthode utilisée pour récupérer dans mon layout tous les appels à mes styles et pour finir comment je fais croire qu’il y a qu’un seul fichier CSS.

Attention: dans les exemples que je vais vous montrer, je vais faire appel à la classe App_Cache. Cette classe est donnée dans le livre Zend Framework – Bien développer en php.

Tout d’abord, pour compresser le contenu des fichiers CSS j’utilise le filtre présent ci-dessous. Il permet de supprimer toutes les tabulations, espaces en trop, commentaires présents dans le fichier.

/**
* Filtre servant à compresser des données CSS lors de la mise en cache par exemple.
*
* Supprime les espaces en trop, les commentaires et met tout sur une seule ligne.
*
* @author Throrin
*
*/
class App_Filter_CssCompressor implements Zend_Filter_Interface
{
public function filter($value)
{
$value = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $value);
$value = str_replace(array("\r\n", "\r", "\n", "\t", ' '), '', $value);
$value = str_replace('{ ', '{', $value);
$value = str_replace(' }', '}', $value);
$value = str_replace('; ', ';', $value);
$value = str_replace(', ', ',', $value);
$value = str_replace(' {', '{', $value);
$value = str_replace('} ', '}', $value);
$value = str_replace(': ', ':', $value);
$value = str_replace(' ,', ',', $value);
$value = str_replace(' ;', ';', $value);

return $value;
}
}

Ensuite, nous devons commencer par rajouter certaines lignes dans la partie contenant tous nos appels au CSS. Pour ce faire j’utilise la fonction ob_start() de PHP permettant de stocker ce qui suit dans un buffer et je le récupère avec la fonction ob_get_contents(). Pour finir à la suite de sa je ferais appel aux actions qui serviront à stocker le tout dans le cache grâce à la fonction $this->action().

<

headScript()."\n"; ?>


jQuery()->addStylesheet($this->baseUrl().'/styles/jquery-ui-1.7.2.custom.css')
->setUiLocalPath($this->baseUrl().'/scripts/jquery-ui-1.7.2.custom.min.js')
->setLocalPath($this->baseUrl().'/scripts/jquery-1.3.2.min.js')."\n"; ?>

action('compresscss', 'header', 'compress', array('contenu' => $output));
ob_end_clean();
?>

Voilà pour ici, maintenant on s’attaque à notre contrôleur qui va parcourir le contenu du buffer pour récupérer le lien vers chaque CSS. Ensuite il va lire le contenu des CSS, le compresser grâce à notre filtre et envoyer son contenu en cache. Pour éviter de répéter cette action assez lourde à chaque appel de l’action, on testera si le cache a bien été créé.

class Compress_HeaderController extends Zend_Controller_Action
{
public function compresscssAction()
{
$css = App_Cache::get('csssite');

if(!$css) {
$cssoffset = $this->_request->getParam('contenu');

//on récupère tous les fichiers CSS
preg_match_all('/link rel="stylesheet" href="(.*?)"/', $cssoffset, $matches);
$i = 0;
$n = count($matches[1]);
$contenucss = '';
//on parcour le tableau des fichiers CSS
while($i < $n) { $lienscss = str_replace('//', '/', $_SERVER['DOCUMENT_ROOT']."/zendtuto18/public"); //lien absolu vers votre dossier public $liens = str_replace('/test18', '', $matches[1][$i]); $handle = fopen($lienscss.$liens,'r'); $contenucss .= fread($handle, filesize($lienscss.$liens)); $i++; } $filtrecss = new App_Filter_CssCompressor(); $contenucss = $filtrecss->filter($contenucss);

App_Cache::set($contenucss, 'csssite');
}
}
}

Voilà pour le contrôleur. Le problème c’est qu’il faut bien dire quel CSS on affiche. C’est pourquoi dans la vue de cette action vous allez mettre juste cette ligne:


Maintenant il y a une question qui vous brûle les levres et qui doit être: « Qu’est-ce que ce fichier style.css? ». Ce fichier est en fait un lien vers notre action d’affichage. Pour ce faire nous devons créer la règle de réécriture présente ci-dessous (htaccess et zend_route).

.htaccess :

RewriteRule ^(.*)styles/style.css$ /compress/header/css [L]

bootstrap.php dans l’action _initRoute() :

$router->addRoute(
'manageCSS',
new Zend_Controller_Router_Route('styles/style.css', array('module' => 'compress', 'controller'=>'header','action'=>'css'))
);

Voilà, cette règle a été nécessaire pour pas casser tous les liens relatifs présents dans les fichiers CSS. Ensuite il ne vous reste plus qu’à créer cette action dans le contrôleur header afin d’afficher le style:

public function cssAction()
{
$this->_helper->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
$css = App_Cache::get('css');

$this->getResponse()->setHeader("Content-type","text/css; charset: UTF-8");
$this->getResponse()->setHeader("Cache-Control","must-revalidate");
$offset = 60 * 60 ;
$ExpStr = gmdate("D, d M Y H:i:s",time() + $offset) . " GMT";
$this->getResponse()->setHeader("Expires: ", $ExpStr);
echo $css;
}

Après ceci tout devrai fonctionner comme sur des roulettes. Pour la partie JS tout est à peu près de ce genre. Seules quelques étapes supplémentaires sont nécessaires pour tout récupérer. J’espère que cet article vous aura permi de trouver une méthode pour compresser vos styles. Par contre évitez de l’utiliser pour un site necessitant un fichier CSS différent par pages. Effectivement en cache vous aurez que le contenu des css inclus dans la première page.

Petite classe perso

by Throrïn 1 Comment

Aujourd’hui je vais vous présenter une petite classe que j’ai commencé à créer. Cette classe sert à générer une url du type http://test.fr/index.php?param1=123&param2=AZER…

Pourquoi créer une classe comme ceci ? Et bien pour avoir à éviter de s’embêter à réécrire tout ceci. J’ai préféré faire comme avec l’aide d’action pour les URL. Si on ne passe aucun paramètre, on a l’url actuelle, sinon on a l’url désirée.

Voici le code de cette classe:
/**
* Classe permettant de génerer des Url et de récupérer l'Url courante.
*
* @author Throrin
* @version 0.2
* @copyright Throrïn's Studio
* @license BSD License
*
* @todo
*

    *

  • 0.1 : Création de la classe
  • *

  • 0.2 : Rajout de la fonction Url()
  • *

*
*/
class App_Url_Url
{
private $_baseurl;

public function __construct()
{
$this->_baseurl = $_SERVER["PHP_SELF"];
}

/**
* Permet de créer une adresse formatée.
* @param array $table Un tableau de paramètres.
* @return adresse
*/
public function Url($table = null)
{
if(empty($table))
{
$request_uri = $_SERVER["REQUEST_URI"];
return $request_uri;
}
else
{
$params = '';
$i = 1;
foreach($table as $key => $value)
{
if($i == 1)
{
$params .= '?';
}
$params .= $key.'='.$value;
if($i != count($table))
{
$params .= "&";
}
$i++;
}
return $this->_baseurl.$params;
}
}

public function getBaseurl()
{
return $this->_baseurl;
}
}

Cette classe fait parti d’un petit projet que je me suis lancé. Créer une petite bibliothèque d’applications pas trop lourdes (comparé au framework Zend) mais disposant d’assez d’options pour se révéler très utile.

Si vous souhaitez participer à cela veuillez me contacter depuis la page d’accueil. Si vous redistribuez cette classe, merci de signaler la source.