IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

PHP introduit les générateurs, par un mécanisme similaire à celui de Python


Sujet :

Langage PHP

  1. #1
    Chroniqueur Actualités

    Homme Profil pro
    CEO
    Inscrit en
    Juillet 2012
    Messages
    78
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : CEO
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2012
    Messages : 78
    Points : 1 395
    Points
    1 395
    Par défaut PHP introduit les générateurs, par un mécanisme similaire à celui de Python
    PHP introduit les générateurs
    Par un mécanisme similaire à celui de Python avec le mot-clé yield


    Les générateurs sont un moyen simple et puissant de créer des itérateurs dans des langages tels que Python. Maintenant, c'est PHP qui fait le pas et s'approprie ce concept.

    Pour comprendre l'utilité et la puissance de ce dernier, on revoit l'exemple typique de lecture d'un fichier en entier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    function getLinesFromFile($fileName) {
        if (!$fileHandle = fopen($fileName, 'r')) {
            return;
        }
     
        $lines = [];
        while (false !== $line = fgets($fileHandle)) {
            $lines[] = $line;
        }
     
        fclose($fileHandle);
     
        return $lines;
    }
     
    $lines = getLinesFromFile($fileName);
    foreach ($lines as $line) {
        // do something with $line
    }
    Le point faible de ce code est le fait qu'il copie tout le fichier dans un grand tableau. Ainsi, plus le fichier est grand, plus le besoin en mémoire s'accroît, avec un risque imminent d'atteindre les limites. Il faut toujours se rappeler qu'un script PHP doit respecter une limite de mémoire spécifiée par l'administrateur.

    On peut certainement éviter ce comportement et récupérer les données ligne par ligne, en utilisant les itérateurs qui sont parfaits pour ce cas d'utilisation. Malheureusement, en PHP il n'existait jusque-là aucune manière simple d'implémenter les itérateurs. Pour y arriver, on est amené à créer une classe complexe implémentant une interface Iterator comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
     
    class LineIterator implements Iterator {
        protected $fileHandle;
        protected $line;
        protected $i;
     
        public function __construct($fileName) {
            if (!$this->fileHandle = fopen($fileName, 'r')) {
                throw new RuntimeException('Couldn\'t open file "' . $fileName . '"');
            }
        }
     
        public function rewind() {
            fseek($this->fileHandle, 0);
            $this->line = fgets($this->fileHandle);
            $this->i = 0;
        }
     
        public function valid() {
            return false !== $this->line;
        }
     
        public function current() {
            return $this->line;
        }
     
        public function key() {
            return $this->i;
        }
     
        public function next() {
            if (false !== $this->line) {
                $this->line = fgets($this->fileHandle);
                $this->i++;
            }
        }
        public function __destruct() {
            fclose($this->fileHandle);
        }
    }
     
    $lines = new LineIterator($fileName);
    foreach ($lines as $line) {
        // do something with $line
    }
    Pour un cas aussi simple que notre exemple, le code est déjà complexe. Avec les générateurs, on peut considérablement réduire le nombre de lignes de code de manière directe à partir de la première version du code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    function getLinesFromFile($fileName) {
        if (!$fileHandle = fopen($fileName, 'r')) {
            return;
        }
     
        while (false !== $line = fgets($fileHandle)) {
            //c'est ici la différence
            yield $line;
        }
     
        fclose($fileHandle);
    }
     
    $lines = getLinesFromFile($fileName);
    foreach ($lines as $line) {
        // do something with $line
    }
    La toute petite différence réside dans l'utilisation du mot clé yield, qui génère une nouvelle donnée dans l'itération.

    En effet, l'instruction $lines = getLinesFromFile($fileName) ne renvoie aucune donnée, c'est simplement un générateur qui implémente l'itérateur qui vient d'être créé.

    Après, pendant l'exécution de la boucle foreach ($lines as $line), chaque itération génère les données renvoyées par yield, qui seront stockées dans $line. En fait, cette génération implémente un objet Iterator et des appels à Iterator::next() seront effectués. L'exécution s'arrête jusqu'à la rencontre du prochain yield, qui renvoie la prochaine donnée, et ainsi de suite...

    Quelques jours après l'introduction du mot clé Finally, se succèdent donc pour PHP les bonnes nouvelles. Ou les emprunts d’autres langages, diront certains.



    Source : détails du mot clé yield dans le site de PHP

    Et vous ?

    Quelle impression vous laisse cette annonce ?
    Pouvez-vous trouver d'autres cas d'utilisation intéressants ?
    Quelle autre approche de simplification des itérateurs auriez-vous préférée pour PHP ?

  2. #2
    Membre éprouvé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2006
    Messages
    519
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Septembre 2006
    Messages : 519
    Points : 1 105
    Points
    1 105
    Par défaut
    Citation Envoyé par tarikbenmerar Voir le message
    Quelle autre approche de simplification des itérateurs auriez-vous préférée pour PHP ?
    En fait, pour l’exemple donné, une autre était déjà possible :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function forEachLineFromFile($fileName, $f) {
        if (!$fileHandle = fopen($fileName, 'r')) {
            return;
        }
     
        while (false !== $line = fgets($fileHandle)) {
            $f($line);
        }
     
        fclose($fileHandle);
    }
     
    forEachLineFromFile($filename, function($line) {
        // do something with $line
    });

    C’est proche de l’approche employée, par exemple, par Scheme et sa fonction call-with-input-file.

  3. #3
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2012
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2012
    Messages : 17
    Points : 59
    Points
    59
    Par défaut
    J'avais été enchanté de découvrir les générateurs avec Python. Mais c'est avec de la pratique qu'on peut vraiment juger de la pertinence d'une telle fonctionnalité. Donc je vais attendre de pester contre les bogues (et trous de sécurité) qu'aura introduit ce nouveau gadget.

  4. #4
    Expert éminent
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    Novembre 2005
    Messages
    2 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 898
    Points : 7 752
    Points
    7 752
    Par défaut
    Ce n'est pas mal à voir comme ça.

    Mais déléguer un code de lecture de fichiers à une autre méthode, ça impliquerait presque une gestion d'erreur par exception. Si fgets retourne false, ça ne veut pas dire que la fin du fichier a été atteinte, ça peut être une erreur IO.

  5. #5
    Membre averti
    Inscrit en
    Mars 2008
    Messages
    283
    Détails du profil
    Informations forums :
    Inscription : Mars 2008
    Messages : 283
    Points : 380
    Points
    380
    Par défaut
    Ce mot clé est un raccourci pour cette structure :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    public class Resultat extends Exception {
        var $resultat;
        public function __constructor($resultat) {
            $this->resultat = $resultat;
        }
     
        public function getResultat() {
            return $this->resultat;
        }
    }
     
    function monIterateur() {
         $resultat = calculs();
         throw new Resultat($resultat);
    }
     
    function utilisation() {
         do {
             try {
                   monIterateur();
             } catch (Resultat $r) {
                   $line = $r.getResultat();
                   $continue = $line === FALSE; //On suppose que nos calculs nous retournent FALSE à la fin de lecture.
                   if ($continue !== FALSE) {
                        doStuff($line);
                   }
             }
         } while ($continue);
     
    }
    C'est un mécanisme identique qui se limite à un seul niveau de profondeur alors que dans mon exemple j'aurais pu utiliser autant d'intermédiaire que je souhaite entre "monIterateur" et "utilisation"

    Je trouve donc ce mot clé comme un sucre syntaxique inutile.

  6. #6
    Expert éminent
    Avatar de transgohan
    Homme Profil pro
    Développeur Temps réel Embarqué
    Inscrit en
    Janvier 2011
    Messages
    3 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Temps réel Embarqué

    Informations forums :
    Inscription : Janvier 2011
    Messages : 3 146
    Points : 9 391
    Points
    9 391
    Par défaut
    Je trouve qu'avec l'exemple donnée on perd en lisibilité et compréhension.
    Aucun retour de fonction mais il y en a bel et bien un de par l'implication de yield.
    Ils viennent de créer un second mot clé de retour de fonction mais que je ne trouve pas très pratique.

    J'ai parcouru la rfc et j'ai trouvé d'autres exemples qui me chagrinent comme celui là :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    function echoLogger() {
        while (true) {
            echo 'Log: ' . yield . "\n";
        }
    }
     
    function fileLogger($fileName) {
        $fileHandle = fopen($fileName, 'a');
        while (true) {
            fwrite($fileHandle, yield . "\n");
        }
    }
     
    $logger = echoLogger();
    // or
    $logger = fileLogger(__DIR__ . '/log');
     
    $logger->send('Foo');
    $logger->send('Bar');
    En gros on balance des objets en exécution parallèle avec ce yield et c'est loin d'être un comportement/code qu'on a l'habitude d'utiliser avec ce langage.

    Voilà pour mes deux sous de réflexions.

  7. #7
    Membre éprouvé
    Homme Profil pro
    -
    Inscrit en
    Octobre 2011
    Messages
    344
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : -

    Informations forums :
    Inscription : Octobre 2011
    Messages : 344
    Points : 1 234
    Points
    1 234
    Par défaut
    En bref, c'est du lazy-evaluation ? Mais limité pour un itérateur ?

  8. #8
    Membre actif
    Homme Profil pro
    Développeur Java
    Inscrit en
    Octobre 2008
    Messages
    104
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Octobre 2008
    Messages : 104
    Points : 210
    Points
    210
    Par défaut
    En gros on balance des objets en exécution parallèle avec ce yield et c'est loin d'être un comportement/code qu'on a l'habitude d'utiliser avec ce langage.
    Je ne suis pas expert sur le sujet, mais cela repose plutôt sur un système de pointeurs que d'exécution parallèles, et cela semble être l'implémentation classique du mot clé Yield.

  9. #9
    Membre éprouvé
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    657
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2010
    Messages : 657
    Points : 1 237
    Points
    1 237
    Par défaut
    C'est bien mais on aimerai aussi que de vieux "bugs" soient corrigés , hein

    http://phpsadness.com/

    mais toute nouveauté est bonne à prendre.

  10. #10
    Expert éminent
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    Novembre 2005
    Messages
    2 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 898
    Points : 7 752
    Points
    7 752
    Par défaut
    Citation Envoyé par yohannc Voir le message
    Je ne suis pas expert sur le sujet, mais cela repose plutôt sur un système de pointeurs que d'exécution parallèles, et cela semble être l'implémentation classique du mot clé Yield.
    Oui, il faut imaginer que la boucle consommateur exécute elle-même la boucle fournisseur de façon transparente à chaque tour de boucle dans son propre thread. Si on le déroule on obtient surement un truc proche de ce qu'a posté Grimly.

  11. #11
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    1 027
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 027
    Points : 1 164
    Points
    1 164
    Par défaut
    Citation Envoyé par _skip Voir le message
    Mais déléguer un code de lecture de fichiers à une autre méthode, ça impliquerait presque une gestion d'erreur par exception. Si fgets retourne false, ça ne veut pas dire que la fin du fichier a été atteinte, ça peut être une erreur IO.

    C'est du php. Le fichier toujours est présent, disponible en lecture, et le disque dur n'à jamais de défaillances.
    Sinon, c'est qu'il y à un problème qui mérite un déboggage manuel.

    Sans troll aucun, php est un langage et une communauté optimiste.

    mes 2 cents

    PS: Je vous vois venir les aficionados de l'exception ect. Ce n'est pas la peine de me rétorquer on peut faire ceci-cela, car oui vous aurez probablement raison, mais non ce n'est pas la philosophie de ce langage simple, syntaxiquement épuré et simplement fonctionnel.

  12. #12
    Expert éminent
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    Novembre 2005
    Messages
    2 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 898
    Points : 7 752
    Points
    7 752
    Par défaut
    Citation Envoyé par ePoX Voir le message
    C'est du php. Le fichier toujours est présent, disponible en lecture, et le disque dur n'à jamais de défaillances.
    Sinon, c'est qu'il y à un problème qui mérite un déboggage manuel.

    Sans troll aucun, php est un langage et une communauté optimiste.
    Evidemment un script qui s'interrompt et le client qui bouffe un 500 c'est pas grave en soi, on le signale à l'administrateur, tu fais des tests et hop.
    Ce qui l'est déjà plus ce sont les applications qui continuent leur traitement en pensant être dans un état normal puis à la fin on remarque un beau jour qu'on a perdu des données. Et cet exemple fourni ci-dessus est typiquement un bon silent fail.

  13. #13
    Membre éprouvé Avatar de pcdwarf
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Février 2010
    Messages
    269
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2010
    Messages : 269
    Points : 978
    Points
    978
    Par défaut
    Je m'étonne du code impératif donné en exemple avec pour argument principal que ça fait charger tout le fichier en ram et que c'est moche.
    En effet Il est inutile et même néfaste de charger tout le fichier en ram si on peut le traiter ligne à ligne.

    Sauf qu'il n'y a pas besoin d'usine à gaz pour traiter un fichier en une seule passe.

    L'exemple deviens

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    function dosomethingwhithFile($fileName, $linefunction) {
        if (!$fileHandle = fopen($fileName, 'r')) {
            return false;
        }
     
        while (false !== $line = fgets($fileHandle)) {
            $linefunction($line);
        }
     
        fclose($fileHandle);
        return true;
    }
    La mémoire libérée sera bien mieux utilisée par le système d'exploitation qui est sensé déjà gérer les problématiques de cache/readahead donc ça ne devrait pas être moins performant qu'en lisant tout le fichier d'un coup.

    Au cas ou ça ne serait pas clair, je ne critique pas le nouveau "yield" mais simplement que le problème soulevé dans l'exemple et prétendument résolu par ce nouvel élément relève largement plus d'une mauvaise approche que d'une limitation du langage.

  14. #14
    Expert éminent
    Avatar de Matthieu Vergne
    Homme Profil pro
    Consultant IT, chercheur IA indépendant
    Inscrit en
    Novembre 2011
    Messages
    2 273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant IT, chercheur IA indépendant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2011
    Messages : 2 273
    Points : 7 803
    Points
    7 803
    Billets dans le blog
    3
    Par défaut
    Même remarque que transgohan, j'aime pas car on perd en intuitivité. Pas de return, mais ça retourne quelque chose. De plus, on perd complètement la logique d'exécution :
    - on appel la fonction
    - elle s'exécute et retourne le produit final
    - on utilise le produit final

    Là, on a :
    - on appel la fonction
    - on récupère un truc qui n'a rien à voir avec le contenu de la fonction
    - on utilise ce truc et là ça exécute le contenu de la fonction (alors qu'on n'appelle pas la fonction en question)

    Ou sinon, la fonction est belle et bien exécutée pour générer l'itérateur avec toutes ses itérations, mais dans ce cas où est la différence avec tout stocker dans un tableau (on a quand même remplit la mémoire) ? Vu l'article, je ne pense pas que ce soit le cas. Mais du coup le code perd en clarté : on ajoute un mot clé qui remet en cause le paradigme de base, qui est d'avoir une "suite d'instructions exécutées les unes à la suite des autres".

  15. #15
    Membre régulier
    Profil pro
    Inscrit en
    Février 2005
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 87
    Points : 95
    Points
    95
    Par défaut
    Par rapport a la syntaxe et sa lisibilité :
    si je fais une analogie avec un autre langage qui utilise yield :
    C# utilise bien "yield return" et pas juste "yield".
    J'aurai trouvé plus commode que PHP s'inspire de la syntaxe C# :
    de considérer yield comme un complément du return et pas comme un remplacant.

  16. #16
    Membre chevronné

    Homme Profil pro
    Mentaliste
    Inscrit en
    Mars 2008
    Messages
    872
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Mentaliste
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2008
    Messages : 872
    Points : 1 816
    Points
    1 816
    Par défaut
    C'est bien, au moins ce genre de choses fera réagir les développeurs Php, et peut être qu'ils vont essayer d'apprendre python.

    Je développe exclusivement en Php (99 % de mon temps), surtout principalement parce qu'il est le plus utilisé au monde, donc je ne fais pas un troll "Python est meilleur que Php".

    Python est très puissant, et j'aimerais ne faire que du Python, mais malheureusement pas assez de gens en font de manière professionnelle (même si Fabien Potencier, le créateur de Synfony, avoue qu'il s'est très largement inspiré du framework python Django qui est exceptionnellement puissant et qui montre par là même à quel point c'est dommage de préférer Synfony 2 à Django qui est toujours plus puissant, et qui a des années d'avance sur le reste (oui oui j'ai bien dit que je développais à 99 % en Php, mais il faut reconnaitre les qualités de certains outils (quand ils en ont (et même si je ne m'en sers pas )))).

    Ci suivent quelques uns de mes articles, et peut être que des gens voudront ajouter une corde à leur arc voulant maîtriser Python en plus de Php :



    Je dis cela dans le cadre de 'yield', parce que ceux qui connaissent déjà Python n'ont aucun mal avec cette possibilité de créer des itérateurs, ce qui ne semble pas être le cas pour les autres.

  17. #17
    Membre régulier
    Profil pro
    Inscrit en
    Février 2005
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 87
    Points : 95
    Points
    95
    Par défaut
    (ceci reste mon strict point de vue)

    j'ai fait quelques pas vers Python et meme Ruby :
    sans meme parler de puissance et tout ca
    rien que la syntaxe du langage me rebute, ca ressemble a du "vieux code".
    Avec des "def", des __INIT__, puis l'encapsulation optionnelle.
    C'est pas pour troller, juste expliquer pourquoi je suis réfractaire a Python.

    C'est sans doute une question d'affinité, car j'aime la syntaxe Java ou PHP avec des accolades et des points virgule, etc...
    Sans ca j'aurais surement adopté Python ou Ruby.

  18. #18
    Membre à l'essai
    Inscrit en
    Juin 2004
    Messages
    20
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Juin 2004
    Messages : 20
    Points : 16
    Points
    16
    Par défaut
    Je vais faire mon captain obvious, mais...

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    while (($line = fgets($fileHandle)) !== false) {
     
      // Il suffit de traiter la ligne directement ici
      // -> Consommation mémoire quasi constante
      // -> Pas besoin d'un yield avec post processing super lent
     
      doSomething($line);
     
    }

    Si c'est juste pour traiter le fichier ligne par ligne, les itérateurs ou le yield me semblent hors de propos.

    Mais je loupe peut-être le sens caché de cette formidable avancée technologique ?




    Edit : Grilled by spidermario et pcdwarf. J'me sens moins seul !

Discussions similaires

  1. Réponses: 15
    Dernier message: 07/09/2014, 13h27
  2. Afficher les données par PHP : la page charge indéfiniment
    Par smilly dans le forum XML/XSL et SOAP
    Réponses: 2
    Dernier message: 01/04/2013, 23h01
  3. Réponses: 8
    Dernier message: 05/09/2012, 12h24
  4. Réponses: 9
    Dernier message: 09/09/2009, 17h51
  5. Remplacer les frames par un script PHP/javascript
    Par midiweb dans le forum Webdesign & Ergonomie
    Réponses: 4
    Dernier message: 15/06/2006, 16h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo