Overblog
Suivre ce blog Administration + Créer mon blog
14 février 2010 7 14 /02 /février /2010 12:25

La programmation orientée objet (ou POO) en PhP est de plus en plus présente. L'évolution du langage en lui même le montre, lors du passage de PhP 4 à PhP 5 des efforts ont été faits pour aller dans ce sens.

 

Les développeurs ont donc de plus en plus tendance à utiliser des classes et des objets mais, comme tout développeur qui se respecte, vous savez qu'en PhP les tableaux sont des outils très puissants. Ne serait-ce pas merveilleux si on pouvait cumuler les avantages des deux ? Et bien c'est possible.


L'interface ArrayAccess

 

Nous ne reviendrons pas sur ce qu'est une interface, vous le savez probablement et si vous ne savez pas, soit vous n'avez pas besoin de savoir pour l'utiliser, soit vous trouverez une description ailleurs.

 

L'interface ArrayAccess est donc une interface qui, lorsqu'elle sera implémentée, nous permettra d'ajouter des fonctionnalités propres aux tableaux à nos objets.

 

Elle comporte 4 méthodes :

 

  • offsetSet

  • offsetGet

  • offsetUnset

  • offsetExists

 

Leurs noms sont assez explicite pour se priver d'une description, voyons par l''exemple ce u'on peut en faire.

 

<?php

class MaClasse implements ArrayAccess

{

    private $nom;

    private $prenom;


    function getNom(){

        return $this->nom

    }


    function offsetSet($offset, $value){

        $offset = strtolower($offset);

        switch($offset){

            case 'nom':

            case 'prenom':

                $this->{$offset} = $value;

                break;

            default :

                throw new Exception('Undifined offset '.$offset,1);

        }

        return true;

    }


    function offsetGet($offset){

        $offset = strtolower($offset);

        switch($offset){

            case 'nom':

            case 'prenom':

                return $this->{$offset};

            default :

                throw new Exception('Undifined offset '.$offset,1);

        }

    }


    function offsetUnset($offset){

        $offset = strtolower($offset);

        switch($offset){

            case 'nom':

            case 'prenom':

                $this->{$offset} = null;

            default :

                throw new Exception('Undifined offset '.$offset,1);

        }

    }


    function offsetExists($offset){

        $offset = strtolower($offset);

        switch($offset){

            case 'nom':

            case 'prenom':

                return true;

            default :

                return false;

        }

    }

}

?>

 

Une fois notre classe définie, on peut facilement utiliser notre objet comme un tableau :

 

<?php


    $variable = new MaClasse();

    $variable['nom'] = 'mon nom';

    $variable['Prenom'] = 'mon prenom';

    if(array_key_exists('adresse',$variable)){

        echo 'Il y a une adresse'

    }

    else{

        echo 'Il n'y a pas d\'adresse';

    }

    unset($variable['prenom']);


?>

 

 

Facile non ? Votre objet est maintenant accessible comme un tableau. Si vous aviez une application qui manipulait des tableaux en PhP et que vous souhaitez lui ajouter des fonctionnalités, il est donc facile de définir une classe implémentant l'interface ArrayAccess et de remplacer les tableaux par des objets.

 

Conclusion ?

 

Ce n'est qu'une première étape dans notre procédé de croisement entre tableaux et objets. Tout décrire en une fois aurait été trop long alors la suite dans un prochain article.

Partager cet article
Repost0
13 février 2010 6 13 /02 /février /2010 17:31

Qu'est ce que c'est SimpleXml ?



Est-il besoin de présenter SimpleXml ? Je ne pense pas, vous êtes tous bien au courrant mais dans le doute disons simplement qu'il s'agit d'une extention php bien pratique pour manipuler des XML. Personnellement, je lui préfère parfois DomDocument mais SimpleXml est bien pratique et plus facile que DomDocument lorsqu'on ne souhaite que lire les données d'un XML.



Comment utiliser SimpleXml ?



Comme son nom nous l'indique, SimpleXml est... simple. L'utilisation est on ne peut plus basique, prenons par exemple considérons le XML suivant :



<?xml version='1.0' encoding='utf-8'?>
  <essay xmlns="http://docbook.org/ns/docbook" xml:lang="en" version='5.0'>
    <info>
      <title>XProc: An XML Pipeline Language</title>
    </info>
  </essay>
 </xml>


Pas très compliqué n'est ce pas ? Et bien dison que vous ayez besoin de le lire en PhP, que faire alors ? Oui vous l'avez compris, utiliser SimpleXml.


<?php

$xml = simplexml_load_file('chemin_du_fichier_xml');

if(false !== $xml){

//Affiche 'XProc: An XML Pipeline Language'

echo (string)$xml->info->title;

}

?>


Vous le voyez, le code est on ne peut plus simple. On dispose d'une fonction simplexml_load_file qui va lire un fichier et renvoyer un objet dont les propriétés représenterons les noeuds XML. Evidement, comme pour toutes les fonctions manipulant des fichiers en PhP, il est aussi possible d'ouvrir une URL. C'est bien pratique pour ouvrir un flux RSS par exemple.


A noter que le noeud racine (ici essay) n'est pas repris. On peut aussi utiliser simplexml_load_string qui, plutôt que de charger le XML depuis un fichier, va le charger depuis une chaine de caractère (une variable par exemple).


Pas mal, ou est le piège ?



Le piège, ou plutôt le problème si on peut l'appeler comme ça, c'est que SimpleXml n'est fait que pour lire et, éventuellement, enregistrer des XML. On ne peut pas forcément modifier le dit XML. S'il est possible de modifier les valeur, on ne peut par contre pas ajouter ni supprimer de noeud.


SimpleXml et le classes utilisateur



Mais il n'est pas question ici de faire une description complète de SimpleXml, le but de l'article est de parler du deuxième paramètre des fonctions simplexml_load_file et simplexml_load_string.


En effet, si le premier paramètre est le XML, le second lui peut être le nom d'une classe. Que se passe-t-il ddans ce cas ? Et bien si la classe en question hérite de la classe SimpleXMLElement alors la fonction renvera un objet de la dite classe.


Dans ce cas, les fonctionnalités « normale » restant évidement disponnible, il est toujours possible d'accèder aux noeuds de la même manière mais il est également possible de définir d'autres options.


Un exemple étant toujours plus parlant, imaginons que vous souhaitiez lire un flux RSS depuis PhP. En utilisant une classe utilisateur que vous avez prédéfinie, l'objet retourné par SimpleXml pourait contenir des fonction qui ne vous renverraient que les 10 articles les plus récents, les articles d'une certaine catégorie, ...


Conclusion ?



Pas de conclusion particulière. C'était juste une petite astuce que je voulais mettre là pour ne pas l'oublier.

Partager cet article
Repost0
15 janvier 2010 5 15 /01 /janvier /2010 00:04

Il arrive, parfois, qu’on ait besoin de récupérer un fichier envoyé par le visiteur. Rien de bien exceptionnel me direz-vous, faire un formulaire d’envoi de fichier n’est pas bien compliqué.

 


<form method="post" enctype="multipart/form-data" action="upload.php" />

<input type="file" name="fichier" />

<input type="submit" value="Envoyer" />

</form>

 

 

Et voilà. Notre formulaire est fin prêt à être utilisé (d’accord il est basique mais il rempli sa tache). Coté PhP, rien de miraculeux non plus :

 

< ?php

$fichier = $_FILE[‘fichier’] ;

//Reste du code ici

?>

 

En deux temps trois mouvements on a uploadé notre fichier sur le serveur et on peut l’utiliser. Seulement ce n’est pas aussi simple que ça. Evidement on ne peut pas simplement utiliser ce morceau de code tel quel. Pourquoi ? Simplement parce qu’il existe des contraintes qui font qu’on ne peut pas faire ce qu’on veut : le fichier peut ne pas avoir été reçu, il peut être incomplet, être trop gros ou encore, un mécréant peut très bien être en train d’essayer de faire de méchantes choses à notre serveur. Pour éviter cela on a plusieurs choses à mettre en place.

 

 
 

 

MAX_FILE_SIZE

 

 

Premier point, la taille du fichier. Vous n’êtes pas sans savoir que la taille du fichier est limitée. Elle peut l’être pour plusieurs raisons :

 

 

 

 

 

 

Dans tous les cas, si le visiteur tente de le faire il risque de perdre un temps précieux à attendre que son fichier soit envoyer avant de se voir dire (dans le meilleur des cas) que son fichier est trop gros.

 

La solution est d’utiliser MAX_FILE_SIZE. Il s’agit d’une petite astuce HTML supportée par tous les navigateurs utilisés actuellement. Pour l’utiliser c’est très simple : il suffit d’ajouter un input de type hidden portant ce nom. Son attribut value doit contenir la taille maximale en octets.

 

 

<form method="post" enctype="multipart/form-data" action="upload.php" />

<input type="hidden" name="MAX_FILE_SIZE" value="500" />

<input type="file" name="fichier" />

<input type="submit" value="Envoyer" />

</form>

 

 

 

Dans l’exemple ci dessus, si le visiteur sélectionne un fichier de plus de 500 octets le navigateur n’essayera pas de l’envoyer et la validation sera quasi instantanée. Nous verrons plus bas comment gérer ça coté serveur.

 

Bien entendu, ceci est coté client, notre mécréant de tout à l’heure pourrait modifier ça de son coté pour passer outre. Il faudra donc ajouter également une vérification coté serveur, cette astuce ne sert que pour le confort de l’utilisateur.

 

 

 

$_FILE

 

 

Coté serveur justement, c’est la variable $_FILE qui va nous permettre de récupérer les informations sur le fichier uploadé. Nous pouvons en tirer quelques informations :

 

Array

(

    [fichier] => Array

        (

            [name] => test.txt

            [type] => text/plain

            [tmp_name] => C:\wamp\tmp\php4E0.tmp

            [error] => 0

            [size] => 26

        )

 

)

 

 

 

 

 

 

 

 

La première chose à faire est de vérifier le champ « error ». En effet c’est lui qui nous indiquera si le fichier a été correctement chargé. Dans ce cas il sera égal à 0 ou à la constante UPLOAD_ERR_OK. En cas de problème il vaudra autre chose, par exemple dans le cas ou la taille du fichier était trop grande (notre exemple ci-dessus), il vaudra UPLOAD_ERR_FORM_SIZE.

 

Pour avoir la liste des codes d’erreurs possible, je ne peux que vous conseiller la documentation PhP : http://be2.php.net/manual/fr/features.file-upload.errors.php

 

Il pourrait être tentant d’utiliser le type mime pour filtrer les upload et empêcher notre scélérat d’envoyer sur notre serveur des fichiers malicieux. Cependant, cette information est envoyée par le client, elle peut donc être fausse ou même ne pas être présente.

 

De la même manière on pourrait avoir envie d’utiliser le paramètre name comme nom du fichier lorsqu’on le copiera à sa destination finale. Cette fois encore, l’insécurité due au fait que la valeur vienne du client cause problème. Il est préférable, de loin, de choisir un nouveau nom à notre fichier.

 

 

 

Move_uploaded_file

 

 

Pour conclure avec notre envoi de fichier, je ne saurais trop vous conseiller de ne pas directement utiliser le fichier ou même de le copier ailleurs directement. En effet, il se pourrait que les valeurs contenues dans $_FILE aient été corrompues d’une manière ou d’une autre.

 

Afin d’éviter tout ennui, il vous faudra utiliser la fonction move_upladed_file(). En effet, cette fonction permettra, en plus de copier le fichier temporaire vers sa destination, de vérifier qu’il s’agit bien d’un fichier uploadé via un script et non d’un fichier potentiellement dangereux. Son utilisation est on ne peut plus simple.

 

 

< ?php

move_uploaded_file($_FILE[‘fichier’][‘tmp_name’], $destination);

?>

 

 

Pour rappel, il est préférable de générer un nom pour le fichier de destination et ne pas utiliser la variable name.

 

 

 

Et voilà, vous savez maintenant tout ce qu’il faut savoir pour un upload agréable et sécurisé.

Partager cet article
Repost0
14 janvier 2010 4 14 /01 /janvier /2010 20:59

Depuis PhP5 on entend souvent parler de méthodes magiques. Non, elles ne sortent pas de lapins de leurs chapeaux, elles sont juste bien pratiques et viennent combler certains trous.

 

Pour faire simple, les méthodes magiques permettent de se simplifier la vie en venant à votre rescousse au moment opportun. Par exemple __get() et __set() permettent de gérer les propriétés d'un objet et donc de faire une seule fonction qui gère la modification et/ou la lecture des propriétés d'un objet plutôt que d'en faire une par propriété.

 

Je ne vais pas m'attarder là dessus, ce n'est pas le but de cet article et j'imagine que pas mal d'entre vous connaissent déjà. Pour les autres, les articles parlant de ça sont foison sur le net, sinon, j'en parlerais peut être dans un autre article, on verra bien.

 

Si je parle de ces méthodes magiques, c’est simplement parce que ce dont on va parler maintenant est souvient lié dans la plupart des articles qu’on trouve sur le sujet. Une des « méthodes magiques », qui en fait n'est pas une méthode mais une fonction est __autoload().C'est de celle-ci qu'on va parler.

 


 

__autoload()

 

 

__autoload() est une fonction bien pratique : elle charge les fichiers « à chaud » pendant l'exécution. Souvenez vous, autre fois, si vous aviez trois classes « Administrateur », « Redacteur » et  « Correcteur » dans une application quelconque et que vous aviez besoin de créer un objet en fonction de l'utilisateur qui venait de se connecter.  Bien souvent, au tout début de votre fichier étaient inclus trois fichiers (un par classe).

 

Pourquoi ? Simplement parce que vous ne saviez pas de laquelle vous aurez besoin avant que l'utilisateur soit connecté, il fallait donc tout charger (je sais qu'on aurait pu gruger pour n'en charger qu'un mais pour l'exemple on fera comme si on ne savait pas).

 

Maintenant c'est finit ! Miracle de l'évolution, grâce à la fonction __autoload() on peut charger le fichier juste quand on en a besoin de manière très propre. Comment me demanderez vous ? Et bien aussi simplement que ça :

 

 

 

function loadingClasses($class_name){

 

require_once(CHEMIN_DU_DOSSIER_DES_FICHIERS_CLASSES.$class_name.'.class.php');

 

 }

 

 

Pas compliqué n'est ce pas ? Lorsque vous créez une instance d’un nouvel objet et que PhP ne le connait pas, il appel immédiatement la fonction reçoit en paramètre le nom de la classe en question. Ensuite, libre à vous de faire le require_once comme vous le voulez. Si les fichiers respectent une règle de nommage un minimum cohérente, une seule ligne est suffisante.

 

  


 

spl_autoload_register

 

 

Jusque là tout va pour le mieux dans le meilleur des mondes possibles. Mais pas de chance, comme je ne suis pas gentil je vais compliquer les choses.

 

Imaginez que vous ayez votre petite application avec sa fonction __autoload() qui fonctionne on ne peut  mieux et que, pour une raison qui ne regarde que moi, je vous demande d’y inclure un développement fait par une autre personne qui définit aussi sa propre fonction __autoload(). La vous aurez un problème : PhP n’aime pas trop que deux fonctions aient le même nom et vous allez devoir repasser sur votre fonction __autoload() pour y inclure le chargement des autres classes.

 

Si on pousse le vice un peu loin, imaginez maintenant que c’est votre code à vous qui va être intégré dans le code d’un autre et que cet autre n’est pas spécialement un expert du PhP et qu’il a juste envie de copier les fichiers et que ça marche.

 

Rassurez vous ! Vous n’êtes pas perdu. Heureusement il existe une autre fonction en PhP qui s’appelle spl_autoload_register(). Cette fonction est très simple à utiliser : elle prend en paramètre le nom d’une fonction.

 

 

< ?php

spl_autoload_register('loadingClasses1');

spl_autoload_register('loadingClasses2');

?>

 

 

Si vous utilisez ce petit bout de code, lorsque PhP rencontrera une classe qu’il ne connaît pas, il appellera la fonction « loadingClasse21 ». Si après cet appel la classe n’est toujours pas connues, il appellera alors « loadingClasses2 ».

 

Voilà, vous pouvez maintenant définir autant de fonction que vous voulez pour charger vos classes. Il peut y en avoir une par « module » de l’application, une pour vos propres classes et une pour les modules inclus, …

 

D’autres fonctions SPL pourraient vous intéresser, un petit coup d’œil ne peut pas faire de mal. On en reparlera peut être une autre fois.

 

 


 

Sources : http://be.php.net/manual/fr/ref.spl.php

http://php.net/manual/fr/language.oop5.magic.php

 

Partager cet article
Repost0

Présentation

  • : Carnet de route d'un développeur PhP...
  • : Ah ! Une description... Ben en fait je me disais que j'allais faire un blog depuis longtemps, sauf que c'était juste pour y stocker des trucs pour moi, des espèces de post-it virtuels. Bon tant qu'à faire autant qu'il te profite à toi aussi.
  • Contact

Recherche

Liens