Services webmasters
Partenaires
Jeux concours gratuits
 
Objets
<<<
Ressources Macros de création automatique de variables globales
>>>

8.10 Créer des variables
8 Développer PHP 4.0
 Manuel PHP

Présentation
Entiers (Longs)
Les nombres à virgules flottantes (Doubles, Floats)
Chaînes de caractères (strings)
Booléens
Tableaux
Objets
->Ressources
Macros de création automatique de variables globales
Créations de constantes

8.10.8 Ressources

Les ressources sont des types de données spéciaux en PHP. Le terme de ressources ne fait pas référence à un type spécial de données, mais représente une méthode d'abstraction, pour gérer n'importe quelle type d'information. Les ressources sont gérées dans une liste spéciale de Zend. Chaque entrée de cette liste dispose d'une définition de type spéciale. Zend gère en interne les références de toutes ces ressources. L'accès aux ressources n'est pas possible directement : il faut utiliser l'API fournie. Aussitot que toutes les références à une ressources sont perdues, une fonction de destruction est appelée.

Par exemple, des ressources sont utilisées pour stocker les connexions aux bases de données, ou des pointeurs de fichiers. Le standard de facto d'iomplémentation peut être trouvée dans le module MySQL, mais d'autres modules comme celui d'Oracle utilisent aussi des ressources.
Note

En fait, une ressource peut être un pointeur sur n'importe quoi dont vous auriez besoin pour gérer vos fonctions (ce peut être un pointeur sur une structure), et l'utilisateur a simplement à passer cette variable de ressource à toutes vos fonctions.

Pour créer une nouvelle ressource, vous devez enregistrer un destructeur de ressource. Comme vous allez stocker n'importe quel type de données dans votre ressource, Zend doit savoir comment les détuire lorsque la ressource devra être libérée. Cela se fait en enregistrant un gestionnaire de ressource, qui sera appelé par Zend dès que votre ressource doit être libérée (manuellemetn ou automatiquement). Cet enregistrement auprès de Zend vous donne le gestionnaire de ressource de cette ressource. Ce gestionnaire est nécessaire à chaque fois que vous aurez à accéder à une ressource de ce type, et la plus part du temps, il est stocké dans une variable globale statique de votre extension. Il n'y a pas de problème de sécurité avec les threads, car ce gestionnaire est crée une fois, durant l'initialisation du module.

La fonction d'enrgistrement de votre gestionnaire de ressource est le suivante :


ZEND_API int zend_register_list_destructors_ex(rsrc_dtor_func_t ld, rsrc_dtor_func_t pld, char *type_name, int module_number);

Il y adeux types de gestionnaire de ressources que vous pouvez passer à cette fonction : le destructeur de ressources normales, et le destructeur de ressources persistantes. Les ressources sont utilisées dans le cas des connexions aux bases de données. Lorsque vous enregistrez une ressource, l'un de ces deux gestionnaires doit être fourni. Si vous n'en utilisez qu'un seul, passez la valeur de NULL pour l'autre.

zend_register_list_destructors_ex accepte les paramètres suivants :
ld Destructeur de ressource normale.
pld Destructeur de ressource persistante.
type_name Une chaîne spécifiant le nom de votre ressource. C'est toujours une bonne chose que de spécifier un nom unique dans PHP pour le type de ressource. Lorsque l'utilisateur appellera var_dump , il saura aussi quel type de ressource est utilisé.
module_number La valeur de module_number est automatiquement disponible dans la macro PHP_MINIT_FUNCTION et donc, vous pouvez l'ignorer.
La valeur retournée par la fonction est un identifiant unique de votre type de ressource .

Les destructeurs de ressources (permanantes ou normales) ont le prototype suivant :


void resource_destruction_handler(zend_rsrc_list_entry *rsrc TSRMLS_DC);
Le pointeur rsrc référence une structure comme celle-ci :

typedef struct _zend_rsrc_list_entry {
     
    void *ptr;
    int type;
    int refcount;

} zend_rsrc_list_entry;
Le membre void *ptr est le pointeur réel de votre ressource.

Maintenant que nous savons comment démarrer, définissons la ressource que nous souhaitons dans Zend. C'est simplement une structure avec deux entiers membres :


typedef struct {
     
    int resource_link;
    int resource_type;

} my_resource;
Notre destructeur de ressource va probablement ressembler à ceci :

void my_destruction_handler(zend_rsrc_list_entry *rsrc TSRMLS_DC) {

    // Généralement, on transptype le pointeur void vers une structure
    
    my_resource *my_rsrc = (my_resource *) rsrc->ptr;

    // Maintanent, faites ce que vous souhaitez avec votre ressource.
    // Fermer des fichiers, des sockets, libérez de la mémoire, etc...
    // De plus, n'oubliez pas de libérer la mémoire de votre ressource elle-même.
   
    do_whatever_needs_to_be_done_with_the_resource(my_rsrc);
}
Note

Une chose importante à citer : si votre ressource est une structure plutôt complexe, qui contient des pointeurs vers de la mémoire allouée durant l'exécution, il faut aussi les libérer mais avant de libérer votre ressource.

Maintenant que nous avons définit

  1. Ce que notre ressource est
  2. notre destructeur de ressource
nous pouvons nous consacrer aux autres étapes :
  1. créer une variable globale dans l'extension pour stocker l'identifiant de ressource, pour qu'il soit accessible à toutes les fonctions qui en auront besoin
  2. Définir un nom de ressource
  3. Ecrire le desctructeur de ressource
  4. et finalement, enregistrer le gestionnaire

// Quelque part dans votre extension, définissez la variable contenant vos ressources enregistrées
    // Si vous vous demandez ce que "le" signifie, c'est 'list entry' (élément de liste).
    static int le_myresource;

    // C'est une bonne chose que de donner un nom à votre ressource
    #define le_myresource_name  "My type of resource"

    [...]

    // Maintenant, codons réellement votre desctructeur de ressources
    void my_destruction_handler(zend_rsrc_list_entry *rsrc TSRMLS_DC) {

        my_resource *my_rsrc = (my_resource *) rsrc->ptr;
        do_whatever_needs_to_be_done_with_the_resource(my_rsrc);
    }

    [...]

    PHP_MINIT_FUNCTION(my_extension) {

        // Notez qu8e "module_number" est déjà fournie grâce à la définition
        // de PHP_MINIT_FUNCTION().

        le_myresource = zend_register_resource_destructors_ex(my_destruction_handler, NULL, le_myresource_name, module_number);

        // Vous pouvez enregistrer d'autres ressources, initialiser vos
        // variables globales, vos constantes, etc...
    }

Pour enregistrer réellement votre nouvelle ressource, vous pouvez soit utiliser la fonction zend_register_resource ou bien la macro zend_register_resoure , qui sont toutes les deux définies dans le fichier d'entête zend_list.h . Bien que les arguments des deux soient exactement les mêmes, c'est une bonne idée que d'utiliser la macro pour assurer une meilleure compatibilité :


int ZEND_REGISTER_RESOURCE(zval *rsrc_result, void *rsrc_pointer, int rsrc_type);
rsrc_result Une enveloppe zval * déjà allouée.
rsrc_pointer Votre pointeur de ressource, que vous souhaitez stocker.
rsrc_type Le type que vous avez reçu lorsque vous avez enregistré votre destructeur de ressources. Si vous avez suivi la convention de nommage, c'est le_myresource .
La valeur retournée est un identifiant de ressource unique.

Ce qui se passe en réalité lorsque vous enregistrez une novuelle ressource, c'est que vos valeurs sont insérées dans une liste interne de Zend, et que le résultat est stocké dans l'enveloppe zval * fournie :


rsrc_id = zend_list_insert(rsrc_pointer, rsrc_type);
     
    if (rsrc_result) {
        rsrc_result->value.lval = rsrc_id;
        rsrc_result->type = IS_RESOURCE;
    }

    return rsrc_id;
La valeur retournée rsrc_id identifie de manière unique la nouvelle ressource. Vous pouvez utiliser la macro RETURN_RESOURE pour la retourner à l'utilisateur.

RETURN_RESOURCE(rsrc_id)
Note

C'est une pratique courante si vous souhaitez retourner imméditament une ressource à votre utilisateur que de spécifier return_value comme enveloppe zval * .

Zend prend en charge la ressource. Aussitôt que toutes les références à cette ressources seront perdues, le destructeur que vous avez enregisté sera appelé. La magie de ce concept est que vous n'avez pas à vous soucier de fuites de mémoire, introduites par votre module : notez bien toutes les allocations que votre ressource demande. Aussitôt que cette mémoire doit etre libérée, Zend vous appelera, et vous demandera de les libérer. keeps track of all references to this resource. As soon as

Mainteant que l'utilisateur a sa ressource, et il la passe à chacune de vos fonctions qui en a besoin. Le champs value.lval dans l'enveloppe zval * contient une clé vers votre ressource, et sert donc à la récuperer, avec la macro suivante : ZEND_FETCH_RESOURCE :


ZEND_FETCH_RESOURCE(rsrc, rsrc_type, rsrc_id, default_rsrc_id, resource_type_name, resource_type)
rsrc Votre pointeur, qui va pointer sur votre ressource enregistrée précédemment.
rsrc_type C'est le type de votre pointeur, i.e. myresource * .
rsrc_id C'est l'adresse de votre enveloppe zval * , que l'utilisateur a passé à votre f onction, i.e. &z_resource si zval *z_resource est fourni.
default_rsrc_id Cet entier spécifie l'identifiant de ressource par défaut, si aucune ressource n'a pu être lue, ou bien -1.
resource_type_name C'est le nom de la ressource demandée. C'est une chaîne de caractèers, et elle est utilisée lorsque la ressource n'a pu être trouvée, ou qu'un message d'erreur intelligible n'a pu être constitué.
resource_type Le type de ressource resource_type que vous avez obtenu lorsque de l'enregistrement de votre destructeur de ressource. Dans notre exemple, c'était le_myresource .
Cette macro n'a pas de valeur de retour. C'est fait pour le confort des développeurs, et elle prend en charge les arguments de TSRMLS, ainsi que la vérification de la validité de la ressource lue. Au besoin, elle émet une alerte, et termine la fonction PHP courante avec la valeur NULL , si un problème de lecture de la ressource été rencontré.

Pour forcer la suppression d'une ressource de la liste, utilisez la fonction zend_list_delete . Vous pouvez aussi former le compteur de référence à 0 si vous savez que vous allez creer un autre référence pour une valeur précédemment allouée (par exemple, si vous réutilisez une connexion à une base de données par défaut). Pour recherche les ressources déjà allouée, utilisez la fonction zend_list_find . L'API complète est disponible dans le fichier zend_list.h .

<< Ressources >>
Objets Créer des variables Macros de création automatique de variables globales
Services webmasters
Les manuels
 
CoursPHP.com - Reproduction interdite -