On continue dans la série Zend Framework (je suis à fond dessus en ce moment, donc il y aura surement d’autres articles) avec les modèles de données. Beaucoup d’articles parle déjà de la mise en place de Zend_Db_Table, je passerais donc rapidement dessus. Ce billet sera plus focalisé sur la création d’un helper (pour action) pour faciliter l’accès aux modèles.

Dans le fichier de bootstrap (ou dans un module si vous utilisez la classe App du billet précédent) commençons par initialiser la connexion.

require_once 'Zend/Db.php';
$db = Zend_Db::factory('pdo_mysql', array(
    'host' => 'localhost',
    'username' => 'root',
    'password' => '',
    'dbname' => 'db'
));

Il est évidemment conseiller de transférer les paramètres de connexion dans un fichier de configuration… Il nous faut à présent configurer Zend_Db_Table pour utiliser cette connexion

require_once 'Zend/Db/Table.php';
Zend_Db_Table::setDefaultAdapter($db);

On peut maintenant créer nos classes. Dans le dossier /application/models créez par exemple le fichier MaTable.php avec:

<?php
class MaTable extends Zend_Db_Table
{
}

Je vous laisse lire la doc très complète de ZF pour plus d’info.

Créons à présent le helper. Le but de ce dernier est de faciliter l’accès aux modèles. Il permettra depuis le contrôleur de faire quelque chose comme:

$this->models->MaTable;

Pour créer ce helper, nous devons créer une classe héritant de Zend_Controller_Action_Helper_Abstract

<?php
require_once 'Zend/Controller/Action/Helper/Abstract.php';
class App_Helper_Models extends Zend_Controller_Action_Helper_Abstract
{
}

Le constructeur va être en charge de trouver le dossier où sont stockés les modèles.

<?php
require_once 'Zend/Controller/Action/Helper/Abstract.php';
class App_Helper_Models extends Zend_Controller_Action_Helper_Abstract
{
    protected $_modelDirectory = null;
 
    protected $_loadedModels = null;
 
    public function __construct()
    {
         $module  = $this->getRequest()->getModuleName();
         $dirs    = $this->getFrontController()->getControllerDirectory();
         if (empty($module) || !isset($dirs[$module])) {
             $module = $this->getFrontController()->getDispatcher()->getDefaultModule();
         }
         $baseDir = dirname($dirs[$module]) . DIRECTORY_SEPARATOR . 'models';
 
         if (!file_exists($baseDir) || !is_dir($baseDir)) {
             throw new Zend_Controller_Exception('Missing model directory ("' . $baseDir . '")');
         }
 
         $this->_modelDirectory = $baseDir;
         $this->_loadedModels = array();
    }
}

Ici, on récupère d’abord le module courant ainsi que les dossiers où sont stockés les contrôleurs. Remarquez qu’il faut gérer le cas où c’est le module par défaut. A partir de cela on détermine le chemin du dossier de stockage des modèles.

Finalement, ont utilise la méthode magique __get() pour charger un modèle:

    public function __get($name)
    {
         if (!array_key_exists($name, $this->_loadedModels)) {
            if (!class_exists($name)) {
                require_once 'Zend/Loader.php';
                Zend_Loader::loadClass($name, $this->_modelDirectory);
            }
 
            $this->_loadedModels[$name] = new $name();
        }
 
        return $this->_loadedModels[$name];
    }
}

Dans cette méthode, on vérifie d’abord que le modèle n’est pas déjà chargé. Si ce n’est pas le cas, on charge éventuellement la classe à l’aide de Zend_Loader puis on créer une instance.

Finalement, il ne nous reste plus qu’a charger le helper dans le broker. Pour cela, la meilleure méthode consiste probablement à créer une classe App_Controller. Tous les contrôleurs devront hériter de celle-ci.

<?php
require_once 'Zend/Controller/Action.php';
abstract class App_Controller extends Zend_Controller_Action
{
    protected $models = null;
 
    public function init()
    {
        require_once 'App/Helper/Models.php';
        Zend_Controller_Action_HelperBroker::addHelper(new App_Helper_Models());
 
        $this->models = $this->_helper->getHelper('Models');
    }
}

Dans notre contrôleur:

<?php
require_once 'App/Controller.php';
class IndexController extends App_Controller
{
    public function indexAction()
    {
        $this->view->data = $this->models->MaTable->fetchAll();
    }
}

Vous pouvez aussi améliorer la classe pour ajouter le support de dossier de modèles multiples par exemple…

Voili voilou

Posted in Development, PHP, Zend Framework at February 11th, 2008. Comments.

Il existe un paquet d’exemples expliquant comment créer un fichier de bootstrap pour le Zend Framework. En revanche, je n’en ai croisé aucun présentant une manière élégante de le faire. Au fil du temps je me suis fait une petite classe en charge du process.

Cette classe, que j’ai appelée App, permet de modulariser le bootstrap. J’ai par exemple créé les modules config, router et dispatch. Le premier charge la config, le deuxième le router et le dernier exécute le dispatch du front controller. Dans le fichier index.php, il ne me reste plus qu’a charger ces trois modules. Ce qui donne:

App::load(array('config', 'router', 'dispatch'));

Il faut avant cela définir le dossier où sont stocké ces modules:

App::setBootstrapDirectory('../bootstrap');

Le fichier index.php ne contient donc plus que quelques lignes (la définition du include path, le require de la classe App et les deux lignes précédentes). Tout le reste se passe dans les modules.

La classe App est bien évidemment stockée dans /libraries/App.php. Dans l’exemple précédent, les modules sont stockés dans /bootstrap. Le module config sera par exemple dans /bootstrap/config.php.

Les modules sont donc réutilisables d’application en application. Il suffit d’activer ceux nécessaires. On peut même avoir un dossier bootstrap partagé par plusieurs applications!

Ci dessous vous trouverez un petit zip avec la classe et un exemple d’utilisation dans index.php. Pour ce qui est des modules, à vous de les imaginer! Il suffit de découper le process de bootstrap classique et on trouve des exemples de celui-ci un peu partout…
Télécharger La classe App

Posted in Development, PHP, Zend Framework at February 9th, 2008. Comments.

Pour ceux qui ont testé ronchon.fr vous avez pu constater que l’on peut ronchonner par SMS. Avec un petit budget comme le mien (qui a dit pas de budget?) vous pensez bien que le service que j’utilise est gratuit. Il vaut donc le coup d’être partagé!

C’est nos amis de chez Orange Partner qui nous font le plaisir de proposer le SMS API. Toujours en version alpha, la chose est néanmoins tout à fait opérationnelle!

Très simple d’utilisation, il suffit de s’inscrire (c’est gratuit) puis de définir un mot clé (à mettre avant le message dans le SMS) et une URL. Celle-ci sera appelée avec deux paramètres GET à la réception d’un SMS. Ces derniers sont from (le numéro de téléphone) et content (le contenu du message). A vous de faire le traitement. Très très simple donc. Vous pouvez aussi rediriger les SMS vers un email.

Le service permet aussi d’envoyer des SMS. En revanche, cela devient payant. En fait, ça fonctionne avec un système de crédits. Envoyer un SMS vous coute 10 crédits. En recevoir un vous en rapporte 2. Vous pouvez aussi acheter des crédits supplémentaires.
Je n’ai pas tester l’envoi mais cela semble tout aussi simple. Il suffit d’appeler une URL avec le numéro du destinataire, le message et une API key.

Très bon service donc. Un grand merci aux gars d’Orange!

Posted in Web services at February 2nd, 2008. Comments.