Développement Web, PHP, Zend Framework

Programmer un envoi de SMS avec le Zend Framework et Google Agenda

Posté par seiyar81 le 22 mars 2010 | Laisser un commentaire (5)
Google Agenda

Si vous développez déjà avec le Zend Framework vous devez connaître ou avoir entendu parler de Zend_Gdata. C’est, comme son nom l’indique, un ensemble de classes qui permettent l’accès aux services en ligne de Google (Google Data API). On a ainsi accès à :

Aujourd’hui je vais expliquer comment se servir de Zend_Gdata pour communiquer avec Google Agenda. Si vous en connaissez le fonctionnement, vous savez qu’on peut définir des rappels pour les rendez-vous de trois façons : Email, Pop-up ou SMS.

C’est au SMS que nous nous intéresseront, en effet, utiliser Google Agenda pour l’envoi de SMS ne vous coutera pas un centime !

Pré-requis

Vous devez avant tout disposer de :

  • Un compte Google
  • Un agenda activé dans Google Agenda
  • Un numéro de portable associé au compte Google Agenda et vérifié
  • La dernière version du Zend Framework disponible ici
  • Un serveur HTTP avec le support de PHP (peut-être pas besoin de le préciser mais on ne sait jamais :p )

Mise en situation (enfin essai ^^)

C’est bien joli d’écrire ce tutoriel mais sans un exemple pratique il peut être difficile d’en voir l’intérêt.

Imaginez que vous développez pour une entreprise qui installe et gère le fonctionnement de panneaux solaires (vous pouvez remplacer panneaux solaires par chaudières, fenêtres, voire même par l’adoption de poissons rouges birmans, si si ça marche aussi !).

Imaginez maintenant que vos clients aient la possibilité via une interface web de créer des “tickets”, ou “alertes” comme vous le sentez, dès lors qu’ils rencontrent un problème auquel ils ne peuvent faire face seuls !

C’est alors que par malheur, vous n’êtes pas joignable au bureau et le client n’a pas votre numéro de portable (si si c’est possible) ! Drâme ! Horreur ! Comment faire ?

Et bien tout simplement en créant un évènement sur votre Google Agenda avec l’option “reminder by SMS” !

Formulaire

Vous créez donc un formulaire pour que vos clients puissent expliquer en quelques lignes ce qui se passe avec en bonus une liste pour choisir la priorité du ticket.

class Default_Form_Ticket extends Zend_Form
{
    public function __construct($sitesList, $options = null)
    {
        parent::__construct($options);
        $this->setName('ticket_form');
        $this->setAction('/tickets/new')
     	->setMethod('post');
     	$this->setDecorators(array(
	    'FormElements',
	    array('HtmlTag', array('tag' => 'table')),
	    'Form',
		));

        $title = new Zend_Form_Element_Text('title');
        $title->setLabel('Sujet : ')
        ->setRequired(true)
        ->addFilter('StripTags')
        ->addFilter('StringTrim')
        ->setAttrib('size', '50')
        ->addValidator('NotEmpty');
        $title->setDecorators(array(
	    'ViewHelper',
	    'Errors',
	    array(array('data' => 'HtmlTag'), array('tag' => 'td', 'class' => 'element-input')),
	    array('Label', array('tag' => 'td'), array('tag' => 'td', 'placement' => 'prepend')),
	    array(array('row' => 'HtmlTag'), array('tag' => 'tr')),
		));

        $priority = new Zend_Form_Element_Select('priority');
        $priority->setLabel('Priorité : ')
        ->setRequired(true)
        ->addFilter('StripTags')
        ->addFilter('StringTrim')
        ->addValidator('NotEmpty');
        $priority->addMultiOptions(array('Basse'=>'Basse', 'Normale'=>'Normale', 'Haute'=>'Haute', 'Urgente'=>'Urgente'));
        $priority->setDecorators(array(
	    'ViewHelper',
	    'Errors',
	    array(array('data' => 'HtmlTag'), array('tag' => 'td', 'class' => 'element-input')),
	    array('Label', array('tag' => 'td'), array('tag' => 'td', 'placement' => 'prepend')),
	    array(array('row' => 'HtmlTag'), array('tag' => 'tr')),
		));

        $message = new Zend_Form_Element_Textarea('message');
        $message->setLabel('Message : ')
        ->setRequired(true)
        ->addFilter('StripTags')
        ->addFilter('StringTrim')
        ->setAttrib('cols', '50')->setAttrib('rows', '15')
        ->addValidator('NotEmpty');
        $message->setDecorators(array(
	    'ViewHelper',
	    'Errors',
	    array(array('data' => 'HtmlTag'), array('tag' => 'td', 'class' => 'element-input')),
	    array('Label', array('tag' => 'td'), array('tag' => 'td', 'placement' => 'prepend')),
	    array(array('row' => 'HtmlTag'), array('tag' => 'tr')),
		));

        $submit = new Zend_Form_Element_Submit('Soumettre');
        $submit->setAttrib('id', 'submitbutton');
        $submit->setValue('Soumettre');
        $submit->setDecorators(array(
	    'ViewHelper',
	    array(array('data' => 'HtmlTag'), array('tag' => 'td', 'class' => 'element-submit')),
	    array(array('label' => 'HtmlTag'), array('tag' => 'td', 'placement' => 'prepend')),
	    array(array('row' => 'HtmlTag'), array('tag' => 'tr')),
		));

        $this->addElements(array($title, $priority, $message, $submit));
    }
}

Ensuite dans le contrôlleur on instancie le formulaire et on l’ajoute à la vue et dans le même temps on met en place le code pour la création de l’évènement.

    public function newAction() {
        $form = new Default_Form_Ticket($sitesList);

        if($this->_request->isPost() && $form->isValid($_POST)) {
            try {
	    /*
		Vous pouvez enregistrer le ticket dans une base de données.
		Nous nous contenterons simplement de l'ajout de l'évènement.
	    */

            $title = 'New Ticket - '.$this->view->user->mail.' - ' . $_POST['title'];
            $message = $_POST['message'];

            $this->createAgendaEvent($title, $message);

            $this->_redirect('/tickets');
            } catch(Exception $e) {
                $this->view->error = 'Une erreur est survenue pendant la création du ticket.';
            }

        }
        $form->populate($_POST);
        $this->view->form = $form;
    }

Il ne nous reste plus qu’à implémenter la fonction createAgendaEvent. Un petit détail toutefois avant de commencer, le reminder se déclenche au minimum 5 min avant le début de l’évènement. Nous créerons donc un évènement à H+6min.

    public function createAgendaEvent($title, $message) {
	// On charge toutes les classes qui vont nous servir
        Zend_Loader::loadClass("Zend_Gdata");
        Zend_Loader::loadClass("Zend_Gdata_ClientLogin");
        Zend_Loader::loadClass("Zend_Gdata_Calendar");
        // On récupère le nom du service
        $service = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;

        // On s'authentifie
        $client = Zend_Gdata_ClientLogin::getHttpClient('IDENTIFIANT_COMPTE_GOOGLE', 'PASSWORD_COMPTE_GOOGLE', $service);

        // On crée un nouvel objet Calendar
        $calendar = new Zend_Gdata_Calendar($client);

        // On lui ajoute un évènement
        $event = $calendar->newEventEntry();

        // On met en place le reminder
        $reminder = $calendar->newReminder();
        $reminder->method = "sms";
        $reminder->minutes = "5";

        // Date de début à H+6min
        $startDate     = date("Y-m-d");
        $startTime     = date("H:i", time() + 6*60);
        // Date de fin à H+7min
        $endDate     = date("Y-m-d");
        $endTime     = date("H:i", time() + 7*60);
        // Offset GMT+01 pour Paris
        $tzOffset     = "+01";

        // On assigne tout ça au calendrier
        $when = $calendar->newWhen();
        $when->startTime = "{$startDate}T{$startTime}:00.000{$tzOffset}:00";
        $when->endTime = "{$endDate}T{$endTime}:00.000{$tzOffset}:00";
        $when->reminders = array($reminder);
        $event->when = array($when);

        // Enfin on ajoute le titre et le message
        $event->title = $calendar->newTitle($title);
        $event->content = $calendar->newContent($message);

        // Et on envoit le tout à Google Calendar
        $newEvent = $calendar->insertEvent($event, "http://www.google.com/calendar/feeds/IDENTIFIANT_COMPTE_GOOGLE/private/full");
    }

Et là, comme par magie vous recevrez une minute plus tard (oui H+6min – 5min = 1min !) un gentil SMS de Google avec le titre de l’évènement.
Si c’est pas beau ça :)

J’espère que ce tutoriel vous aura plu et/ou servi, je continue avec d’autres articles sur le Zend Framework très bientôt.

Catégorie: Développement Web, PHP, Zend Framework | Laisser un commentaire (5)

jQuery : poster un formulaire simplement avec AJAX

Posté par seiyar81 le 18 mars 2010 | Laisser un commentaire (2)

jQuery, ce merveilleux framework qui nous permet de faire tellement de choses … Bien souvent je suis passé à côté de fonctionnalités on ne peut plus simple à utiliser mais tellement utiles.

Du genre, je dois envoyer ce formulaire avec AJAX, il contient plein de champs différents, comment faire pour que ce soit le plus simple et rapide possible ?

Tout d’abord imaginons un formulaire regroupant plusieurs champs sur toute la page.

Coordonnées

... ...

Rien de bien compliqué jusque là mais n’oubliez pas d’inclure la librairie jQuery !
On créé ensuite la page qui va traiter nos données, appelons-la post.php :

    <?php foreach($_POST as $key => $value) echo "
  • $key => $value
  • "; ?>

Il ne nous reste plus que la partie qui nous intéresse ici, le code javascript :

$(document).ready(function(){
	$("#formulaire").submit(function(){
		$.ajax({type:"POST", data: $(this).serialize(), url:"post.php",
			success: function(data){
				$("#post").html(data);
			},
                        error: function(){
			        $("#post").html('Une erreur est survenue.');
			}
		});
		return false;
	});
});

Tout ce qu’on a à faire c’est ré-implémenter la fonction submit du formulaire et sérialiser ses champs avec la fonction ‘serialize()’ pour envoyer les données.
C’est tout bête mais je ne connaissais pas cette fonction et on ne développe pas toujours avec un IDE qui liste pour nous les fonctions à utiliser !
Enfin comme dit le vieil adage : RTFM !

Catégorie: Développement Web, Javascript, PHP | Laisser un commentaire (2)

Accélerer et optimiser son intallation PHP avec eAccelerator

Posté par seiyar81 le 12 février 2010 | Laisser un commentaire (0)

Quand on doit gérer un serveur Web, on doit s’occuper avant tout de la sécurité de l’installation, de sa stabilité, etc mais il ne faut pas pour autant négliger les performances. Car oui l’utilisateur final ne se préoccupe pas vraiment de savoir si le serveur risque de tomber à la moindre attaque, et si l’application est trop longue à répondre il ira voir ailleurs s’il peut ou alors va commencer à s’énerver.

J’ai déjà présenté quelques modules pour accélérer Apache, mais aujourd’hui je vais expliquer comment installer très simplement un système de cache d’opcode : eAccelerator.
Avant cela quelques explications.

Qu’est-ce que l’opcode ?

Comme vous le savez tous sûrement, PHP n’est pas un langage compilé, mais interprété. C’est à dire qu’à chaque exécution le code est parcouru puis PHP génère ce qu’on appelle l’opcode qui est en réalité un code compréhensible par la machine qui pourra donc l’exécuter.
Ce processus peut très vite devenir lourd pour la machine dès lors que l’application fait face à un nombre important de clients et les temps de réponses n’en sont que plus long.

Quelles solutions ?

C’est pourquoi on va s’intéresser aux systèmes de cache d’opcode. Ces derniers améliore grandement les performances de PHP en plaçant dans un système de cache ces fameux opcodes.
Il existe plusieurs solutions dont voici une courte liste (non exhaustive) :

  • IonCube: http://www.ioncube.com/sa_encoder.php
  • Zend Platform: http://www.zend.com/en/products/platform/
  • XCache: http://xcache.lighttpd.net/
  • APC: http://pecl.php.net/packages/APC
  • EAccelerator: http://www.eaccelerator.net/

Nous nous intéresserons ici à eAccelerator.
Attention toutefois, eAccelerator ne fonctionne pas si PHP est CGI, il est seulement utilisable avec mod_php ou PHP en FastCGI.

On commence par récupérer la dernière version :

cd /usr/src
wget http://bart.eaccelerator.net/source/0.9.6/eaccelerator-0.9.6.tar.bz2
tar -xf eaccelerator-0.9.6.tar.bz2
cd eaccelerator-0.9.6

Ensuite il nous faut compiler les sources, donc dans le dossier entrez les commandes suivantes :

phpize
./configure
make

Si le programme phpize n’est pas trouvé, il faut le télécharger :

sudo apt-get install php5-dev

Si tout s’est bien passé, on lance l’installation :

make install

Il nous faut maintenant configurer PHP pour qu’il charge l’extension, on modifie donc le fichier /etc/php5/conf.d/eaccelerator.ini :

zend_extension="/usr/lib/php4/eaccelerator.so"
eaccelerator.shm_size="16"
eaccelerator.cache_dir="/tmp/eaccelerator"
eaccelerator.enable="1"
eaccelerator.optimizer="1"
eaccelerator.check_mtime="1"
eaccelerator.debug="0"
eaccelerator.filter=""
eaccelerator.shm_max="0"
eaccelerator.shm_ttl="0"
eaccelerator.shm_prune_period="0"
eaccelerator.shm_only="0"
eaccelerator.compress="1"
eaccelerator.compress_level="9"

Enfin on créé le dossier dans lequel eAccelerator va stocker son cache :

mkdir /tmp/eaccelerator
chmod 0777 /tmp/eaccelerator

Enfin on vérifie que tout fonctionne bien :

/etc/init.d/apache2 reload
php5 -v
...
Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies
    with eAccelerator v0.9.6, Copyright (c) 2004-2010 eAccelerator, by eAccelerator
...

Et voilà votre installation de PHP est maintenant plus rapide et plus stable.
J’expliquerais prochainement comment mettre en place très simplement un reverse proxy afin de soulager le serveur Web.

Catégorie: Apache, Développement Web, PHP | Laisser un commentaire (0)

Zend Framework : Détails de la version 1.10.0

Posté par seiyar81 le 3 février 2010 | Laisser un commentaire (0)

Sortie depuis quelques jours la toute dernière version du framework apporte son lot de nouveautés. Ainsi la documentation a été réorganisée de façon a être plus accessible et plus claire, avec un « Quick Start« , une section « Reference Guide » qui permet de découvrir le framework et d’apprendre à programmer avec.

De plus la documentation est maintenant propulsée par le même moteur que Php.net : PhD. Le rendu de la documentation est ainsi simplifié pour les différentes versions du framework.
La page de téléchargement a également été revue est propose maintenant directement le téléchargement de différent packages : Zend Framewrok + Zend Server CE, Zend Framework Complet, Zend Framework Minimal, Documentation etc.

Enfin pour ce qui est des nouveautés on notera :

  • Zend_Barcode : création de code barre
  • Zend_Cache_Manager : gestion avancée du cache
  • Zend_Feed_Writer : génération de flux RSS et Atom
  • Zend_Oauth : authentification avec Oauth
  • Nouveaux Zend_Service : Zend_Service_LiveDocx, Zend_Service_WindowsAzure, Zend_Service_DeveloperGarden
  • Zend_Markup : faciliter l’intégration et l’édition de langages types BBCode et Textile
  • Plusieurs améliorations sur diverses classes et sur le Zend_Tool

Aller, direction la page de téléchargement !

Catégorie: Développement Web, PHP, Zend Framework | Laisser un commentaire (0)

DataTables : base de données, traduction et jQuery-UI

Posté par seiyar81 le 2 février 2010 | Laisser un commentaire (13)

J’avais présenté ce fabuleux plugin pour jQuery qu’est Datatables et expliqué rapidement ce dont il est capable.
Aujourd’hui je vous propose une mise en situation, avec comme objectif l’interaction avec une base de données, une traduction en français (ou une autre langue parmi les 29 disponibles), la mise en forme avec l’aide jQuery-UI, et d’autres fonctionnalités.

Tout d’abord si vous ne possédez pas encore le plugin téléchargez-le ici.
Ensuite nous allons placer le code de notre tableau dans notre page, imaginons que l’on souhaite afficher des utilisateurs :

<table id="datatable" >
  <thead>
       <tr>
            <th>Nom</th>
            <th>Prénom</th>
            <th>Inscription</th>
            <th>Mail</th>
            <th></th>
        </tr>
  </thead>
 <tbody>
       <tr>
            <td colspan="4">Chargement des données...</td>
        </tr>
  </tbody>
</table>

Maintenant le code Javascript. Nous allond indiquer que l’on souhaite récupérer les données via un fichier côté serveur :

$(document).ready(function() {
	$('#datatable').dataTable( {
		"bProcessing": true,
		"bServerSide": true,
		"sAjaxSource": "get_data.php"
	} );
} );

Le plugin ira donc récupérer le fichier get_data.php pour remplir le tableau. Les données renvoyées par le fichier php doivent être au format JSON.
Voici un exemple du contenu de get_data.php inspiré de la documentation de Datatables mais vous êtes libre de modifier le code pour utiliser PDO, ou une autre méthode d’accès à la base de données si vous utilisez un autre SGBD que MySQL.

<?php
  /* MySQL connection */
	$gaSql['user']       = "username";
	$gaSql['password']   = "password";
	$gaSql['db']         = "mydb";
	$gaSql['server']     = "localhost";
	$gaSql['type']       = "mysql";

	$gaSql['link'] =  mysql_pconnect( $gaSql['server'], $gaSql['user'], $gaSql['password']  ) or
		die( 'Could not open connection to server' );

	mysql_select_db( $gaSql['db'], $gaSql['link'] ) or
		die( 'Could not select database '. $gaSql['db'] );

	/* Paging */
	$sLimit = "";
	if ( isset( $_GET['iDisplayStart'] ) )
	{
		$sLimit = "LIMIT ".mysql_real_escape_string( $_GET['iDisplayStart'] ).", ".
			mysql_real_escape_string( $_GET['iDisplayLength'] );
	}

	/* Ordering */
	if ( isset( $_GET['iSortCol_0'] ) )
	{
		$sOrder = "ORDER BY  ";
		for ( $i=0 ; $i<mysql_real_escape_string( $_GET['iSortingCols'] ) ; $i++ )
		{
			$sOrder .= fnColumnToField(mysql_real_escape_string( $_GET['iSortCol_'.$i] ))."
			 	".mysql_real_escape_string( $_GET['sSortDir_'.$i] ) .", ";
		}
		$sOrder = substr_replace( $sOrder, "", -2 );
	}

	/* Filtrage - Remplace le filtrage côté client, peut donc être long si la base de données est importante
	 */
	$sWhere = "";
	if ( $_GET['sSearch'] != "" )
	{
		$sWhere = "WHERE nom LIKE '%".mysql_real_escape_string( $_GET['sSearch'] )."%' OR ".
		                "prenom LIKE '%".mysql_real_escape_string( $_GET['sSearch'] )."%' OR ".
		                "inscription = '".mysql_real_escape_string( $_GET['sSearch'] )."' OR ".
		                "mail = '".mysql_real_escape_string( $_GET['sSearch'] )."'";
	}

	$sQuery = "SELECT id, nom, prenom, inscription, mail FROM users $sWhere $sOrder $sLimit";
	$rResult = mysql_query( $sQuery, $gaSql['link'] ) or die(mysql_error());

	$sQuery = "SELECT FOUND_ROWS()";

	$rResultFilterTotal = mysql_query( $sQuery, $gaSql['link'] ) or die(mysql_error());
	$aResultFilterTotal = mysql_fetch_array($rResultFilterTotal);
	$iFilteredTotal = $aResultFilterTotal[0];

	$sQuery = "SELECT COUNT(id)	FROM users";
	$rResultTotal = mysql_query( $sQuery, $gaSql['link'] ) or die(mysql_error());
	$aResultTotal = mysql_fetch_array($rResultTotal);
	$iTotal = $aResultTotal[0];

	$sOutput = '{';
	$sOutput .= '"sEcho": '.intval($_GET['sEcho']).', ';
	$sOutput .= '"iTotalRecords": '.$iTotal.', ';
	$sOutput .= '"iTotalDisplayRecords": '.$iFilteredTotal.', ';
	$sOutput .= '"aaData": [ ';
	while ( $aRow = mysql_fetch_array( $rResult ) )
	{
		$sOutput .= "[";
		$sOutput .= '"'.addslashes($aRow['nom']).'",';
		$sOutput .= '"'.addslashes($aRow['prenom']).'",';
		$sOutput .= '"'.addslashes(date(H:i d/m/Y'', $aRow['inscription'])).'",';
		$sOutput .= '"'.addslashes($aRow['mail']).'"';
		$sOutput .= '"Détails"';
		$sOutput .= "],";
	}
	$sOutput = substr_replace( $sOutput, "", -1 );
	$sOutput .= '] }';

	echo $sOutput;

	function fnColumnToField( $i )
	{
		if ( $i == 0 )
			return "nom";
		else if ( $i == 1 )
			return "prenom";
		else if ( $i == 2 )
			return "inscription";
		else if ( $i == 3 )
			return "mail";
	}
?>

Et voilà notre tableau se remplit automatiquement avec les données renvoyées par le fichier get_data.php.
La méthode utilisée dans l’exemple pour renvoyer les données au format JSON est un peu barbare, utiliser json-encode sur un array serait à mon humble avis plus approprié, à vous de voir.

  intval($_GET['sEcho']),
				  'iTotalRecords'=>$iTotal,
				  'iTotalDisplayRecords'=>$iFilteredTotal);
 $aaData = array();        

	while ( $aRow = mysql_fetch_array( $rResult ) )
	{
            $tmp = array();
	    $tmp[] = addslashes($aRow['nom']);
		$tmp[] = addslashes($aRow['prenom']);
		$tmp[] = date(H:i d/m/Y'', $aRow['inscription']);
		$tmp[] = addslashes($aRow['mail']);
		$tmp[] = '<a href="user.php?id='.$aRow['id'].'">Détails</a>';

		$aaData[] = $tmp;
	}
   $sOutput['aaData'] = $aaData;

   echo json_encode($sOutput);

Je n’ai pas testé le code mais cela devrait fonctionner.

Bon tout ça c’est bien beau mais on aimerait bien avoir une traduction en français plutôt que d’avoir Show 10 entries, Search ect, car même si on comprend ça fait tâche.
Et bien le plugin nous offre la possibilité de traduire le plugin dans pas moins de 29 langues dont l’anglais, l’allemand, l’espagnol, le portugais, le chinois etc.
Pour mettre en place la traduction il n’y a rien de plus simple, on va rajouter une option dans la déclaration de notre tableau :

$(document).ready(function() {
	$('#datatable').dataTable( {
		"bProcessing": true,
		"bServerSide": true,
		"sAjaxSource": "get_data.php",
                "oLanguage": { "sUrl": "datatable_fr.txt" }
	} );
} );

Il suffit ensuite de placer la traduction correspondante dans le fichier datatable_fr.txt. La liste des codes à placer est disponible ici.
Vous pouvez modifier les traductions ou bien créer les vôtres très simplement. Pour éviter un appel du fichier sur le serveur vous pouvez également faire comme ceci :

$(document).ready(function() {
	$('#datatable').dataTable( {
		"bProcessing": true,
		"bServerSide": true,
		"sAjaxSource": "get_data.php",
                "oLanguage": { "sProcessing":   "Traitement en cours...",
                   "sLengthMenu":   "Afficher _MENU_ éléments",
	           "sZeroRecords":  "Aucun élément à afficher",
	           "sInfo": "Affichage de l'élement _START_ à _END_ sur _TOTAL_ éléments",
	           "sInfoEmpty": "Affichage de l'élement 0 à 0 sur 0 éléments",
	           "sInfoFiltered": "(filtré de _MAX_ éléments au total)",
	           "sInfoPostFix":  "",
	           "sSearch":       "Rechercher:",
	           "sUrl":          "",
	           "oPaginate": {
		        "sFirst":    "Premier",
		        "sPrevious": "Précédent",
		        "sNext":     "Suivant",
		        "sLast":     "Dernier"
	               }
                }
	} );
} );

Enfin on aimerait styliser notre tableau et donc utiliser la puissance de jQuery-UI. Pour cela rien de plus simple, il suffit de posséder les fichiers de jQuery-UI (.js, .css et les images) et de les avoir inclus. Comme pour la traduction une simple ligne suffit :

       ...
       "bJQueryUI": true,
       ...

Vous pouvez voir encore plus d’exemple sur cette page.

Catégorie: Développement Web, Javascript | Laisser un commentaire (13)

Zend Framework : Authentification avec Zend_Auth_Adapter_DbTable

Posté par seiyar81 le 27 janvier 2010 | Laisser un commentaire (12)

Aujourd’hui je vais expliquer comment réaliser simplement avec le Zend Framework une authentification avec la classe Zend_Auth_Adapter_DbTable.

Cette classe va grandement nous simplifier la vie puisqu’elle va comparer pour nous le couple username/password dans une table dont on lui fournira les champs.
Autrement dit, plus besoin de s’embêter à sélectionner et comparer les valeurs à la main.

Pour commencer nous allons créer notre model pour la table qui stocke nos utilisateurs. Imaginons qu’elle s’appelle ‘users‘.

<?php 

class Default_Model_DbTable_Users extends Zend_Db_Table
{
    protected $_name = 'users';

}

La classe est ici déclarée sans autres méthodes pour l’exemple mis vous pouvez très bien en ajouter. De plus j’ai nommé ma classe de telle sorte qu’elle est déclarée dans le fichier : ‘application/models/DbTable/Users.php‘. Libre à vous de faire autrement.

Ensuite vous pouvez créer un formulaire en héritant la classe Zend_Form :

<?php

class Default_Form_Login extends Zend_Form
{
    public function __construct($options = null)
    {
        parent::__construct($options);
        $this->setName('login_form');
        $this->setAction('/auth/login')
     	->setMethod('post');

        $login = new Zend_Form_Element_Text('login');
        $login->setLabel('Login : ')
        ->setRequired(true)
        ->addFilter('StripTags')
        ->addFilter('StringTrim')
        ->addValidator('NotEmpty');

        $password = new Zend_Form_Element_Password('password');
        $password->setLabel('Mot de passe : ')
        ->setRequired(true)
        ->addFilter('StripTags')
        ->addFilter('StringTrim')
        ->addValidator('NotEmpty');

        $submit = new Zend_Form_Element_Submit('Login');
        $submit->setAttrib('id', 'submitbutton');
        $submit->setValue('Login');

        $this->addElements(array($login, $password, $submit));
    }
}

De même, j’ai ici fait au plus simple. La classe est déclarée dans le fichier ‘application/forms/Login.php‘.
Il ne vous reste plus qu’a déclarer le formulaire dans le contrôleur gérant l’authentification. Par exemple :

<?php

class AuthController extends Zend_Controller_Action
{

    public function init()
    {
        $this->initView();
	$this->view->baseUrl = $this->_request->getBaseUrl();
    }

    public function loginAction()
    {
    	$this->view->title="Mon Site Web - Login";
        $form =  new Default_Form_Login();
        $this->view->form = $form;
    }

}

On affiche le formulaire dans notre fichier vue :


<?php
    echo $this->form;
    echo '<br />';
    echo $this->error;
?>

Voilà tout est en place pour nous permettre maintenant d’utiliser Zend_Auth_Adapter_DbTable.
On va donc ajouter dans l’action login de notre contrôleur :


    public function loginAction()
    {
        // Si l'utilisateur est déjà loggué on le redirige à l'accueil
    	if(Zend_Auth::getInstance()->hasIdentity()) $this->_redirect('/index');

    	$this->view->title="Mon Site Web - Login";

		$form = new Default_Form_Login();
		$this->view->form = $form;
                $formData = $_POST;

		if($this->getRequest()->isPost()) {
	            if ($form->isValid($formData)) {
					$f = new Zend_Filter_StripTags();
					$username = $f->filter($form->getValue('login'));
					$password = $f->filter($form->getValue('password'));

					$dbAdapter = Zend_Db_Table_Abstract::getDefaultAdapter();
					$authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);
					$authAdapter->setTableName('users');
					$authAdapter->setIdentityColumn('username');
					$authAdapter->setCredentialColumn('password');

					// On assigne les valeurs pour que l'authentification s'effectue
					$authAdapter->setIdentity($username);
					$authAdapter->setCredential(sha1($password)); // On a pris la précaution d'au moins chiffrer les mdp

					// On tente l'authentification
					$auth = Zend_Auth::getInstance();
					$result = $auth->authenticate($authAdapter);
                         // On test si tout s'est bien passé
	                if($result->isValid())
	                	{
	                		$data = $authAdapter->getResultRowObject(null, 'password');
					$auth->getStorage()->write($data);
					$this->_redirect('/admin');
	                	}
	                	else
	                	{
	                	$this->view->error = 'Mauvais login ou mauvais mot de passe.';
                    		$form->populate($formData);
	                	}
				    }
		    	else {
	                $this->view->error = 'Vous devez remplir tous les champs.';
                        $form->populate($formData);
		    	}
		}
    }

Et voilà ZF a automatiquement géré l’authentification pour nous. On peut maintenant accéder au données de l’utilisateur via Zend_Auth::getInstance()->getIdentity().
Ainsi si on veut afficher le nom de l’utilisateur :

<?php
     $auth = Zend_Auth::getInstance()->getIdentity();
     echo $auth->username;
?>

Et voilà, bientôt de nouveaux articles sur l’utilisation du Zend Framework.

Catégorie: Développement Web, PHP, Zend Framework | Laisser un commentaire (12)

<div> arrondies en CSS compatibles IE

Posté par seiyar81 le 18 janvier 2010 | Laisser un commentaire (1)

Un problème qui revient souvent pour les développeurs Web : écrire un code CSS compatible avec tous les navigateurs. Enfin quand on dit tous ça sous-entend bien évidemment Internet Explorer et sa gestion foireuse du CSS3…

De plus en cette période où le Web est « 2.0″, on aime bien mettre des arrondis partout.
Un problème se pose toutefois : comment éviter d’utiliser des images ? Sous Firefox/Gecko on possède la propriété -moz-border-radius, sous Webkit(Safari, Chrome etc…) -webkit-border-radius, sous KHTML(Konqueror) -khtml-border-radius, sous Opera une propriété sera disponible sous Presto 2.3 (actuellement 2.2), et sous IE : rien.

Malheureusement, la solution proposée ci dessous n’est pas compatible avec Opera, cependant, comme indiqué plus haut la nouvelle version de Presto, qui devrait arriver courant 2010, va arranger cela.

Le problème concerne donc IE, et Microsoft pour palier aux manques de son navigateurs a créé en 1998 les fichiers HTC. Mélange d’HTML et de balises HTA, les fichiers HTC peuvent contenir du code JScript ou VBScript. Ils disposent également de fonctionnalités comme la possibilité de permettre à IE d’afficher la couche alpha des images PNG (via AlphaImageLoader), ou d’appliquer un comportement :hover sur d’autres balises que <a>.

Le code suivant utilise justement un fichier HTC via la propriété behavior :

-moz-border-radius: 5px;
-webkit-border-radius: 5px;
-khtml-border-radius: 5px;
behavior:url('./border-radius.htc');

Vous pouvez télécharger le fichier HTC à cette adresse.
Sachez toutefois que ce code n’est pas conforme aux normes CSS3 établies par le W3C, néanmoins il permet de combler certains manques sur IE.

Catégorie: Développement Web | Laisser un commentaire (1)

Pavé numérique avec Putty et Vi/Vim

Posté par seiyar81 le 12 janvier 2010 | Laisser un commentaire (0)

Si comme moi vous utilisez Putty en client SSH, et que vous disposez d’un clavier numérique, vous avez sûrement remarqué qu’il est non seulement inutilisable mais en plus qu’il provoque des insertions foireuses de caractères ainsi que des retours à la ligne.

Un simple réglage dans la configuration de Putty permet d’endiguer le problème :

Putty > Terminal > Feature > Cocher Disable application keyboard mode

Catégorie: Développement Web | Laisser un commentaire (0)

Gears This Blog : Mise à jour 0.3

Posté par seiyar81 le 20 décembre 2009 | Laisser un commentaire (0)
news-gtb

Version 0.3 :
- Les pages sont stockées
- Le fichier manifest est reconstruit à chaque sauvegarde pour éviter les doublons
- A chaque modification/ajout d’un post/page le fichier manifest est reconstruit
- Divers corrections de bugs

A venir :
- Ajout de fichiers manuellement
- Personnalisation du CSS
- Exclure certains posts/pages
- D’autres traductions

Catégorie: Développement Web, PHP, Wordpress | Laisser un commentaire (0)

Gears This Blog : Mise à jour 0.2

Posté par seiyar81 le 7 décembre 2009 | Laisser un commentaire (0)
news-gtb

Maj 22H :
- Version 0.2 du plugin corrigeant définitivement un bug dû à WordPress (bouh :p) qui changeait le dossier du plugin.
- Le plugin peut maintenant sauvegarder les catégories et les tags

A faire :
- Correction de quelques bugs de traduction / affichage dans l’administration
- Ajout de fichiers pouvant être choisis dans l’admnistration
- Correction / Amélioration du javascript

Rien de bien excitant dans cette mise à jour si ce n’est tout de même la traduction du plugin, disponible en Anglais par défaut et avec une traduction Française.
Si certains se sentent de traduire le plugin dans d’autres langues, leur aide est plus que bienvenue^^
Car l’espagnol et l’italien ça fait un bail et l’allemand à par Ich Liebe Dich :(
Correction également de quelques bugs dans la partie admin.

Catégorie: Développement Web, PHP, Wordpress | Laisser un commentaire (0)