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 :

[SPL] Iterateur recursif


Sujet :

Langage PHP

  1. #1
    Membre émérite

    Profil pro
    H4X0|2 @ YourLabs Business Service
    Inscrit en
    Octobre 2006
    Messages
    657
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : H4X0|2 @ YourLabs Business Service
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2006
    Messages : 657
    Par défaut [SPL] Iterateur recursif
    J'ai lu les exemples, et j'ai fait de mon mieux pour chercher dans la doc.

    Malheureusement, je n'arrive pas à faire d'itérateur récursif "proprement".
    Par proprement, j'entends en exploitant au maximum les fonctionnalitées de SPL, au lieu de simplement implémenter Iterator avec des fonctions complexes et plein de variables.

    Je suis encore un peu confus quand à l'implémentation de l'iterateur, et j'hésite donc entre la façon qui est dans le docblock de classe, et celle qui est décrite dans le docblock de la méthode setIteratorOption().
    La première solution est plus naturelle pour "usiner" un itérateur externe, quand à la seconde: elle est plus naturelle pour implémenter Iterator avec des options dans la classe (ce à quoi je me résigne petit-à-petit, en fait).

    Voici la classe:
    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
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
     
    <?php
    /**
     * File containing class daFormGroupElement.
     * 
     * @uses daFormElement
     * @package Form
     * @version //autogen//
     * @copyright Copyright (C) 2008 eZ Systems As. All rights reserved.
     * @author James
     * @license http://ez.no/licenses/new_bsd New BSD License
     */
    /**
     * This class allows to wrap several elements into one element.
     *
     * <code>
     * <?php
     * // instanciate a group
     * $group = new daFormGroupElement( $name, $label, $description, $required );
     * // add an element
     * $group->addElement( new daFormTextElement( 'nick', 'your nickname', 'your nickname is useful for others to recognize you', true ) );
     * // get an element
     * $nick = $group->getElement( 'nick' );
     * // remove an element
     * $group->removeElement( $nick );
     *
     * foreach( $group->getIterator() as $element )
     * {
     *   // loops over all elements of that group
     * }
     *
     * foreach( $group->getIterator( true ) as $element )
     * {
     *   // loops over all elements of that group expect group elements
     * }
     *
     * foreach( $group->getRecursiveIterator() as $element )
     * {
     *   // loops over all elements of that group and all sub-groups
     * }
     *
     * foreach( $group->getRecursiveIterator( true ) as $element )
     * {
     *   // loops over all elements of that group and all sub-groups
     *   // without returning any group element
     * }
     * ?>
     * </code>
     * 
     * @uses daFormElement
     * @package Form
     * @version //autogen//
     */
    class daFormGroupElement extends daFormElement implements RecursiveIterator, Countable
    {
        /**
         * List of elements. 
         * 
         * @var array(name=>element)
         */
        protected $elements = array();
     
        protected $iteratorOptions = array(
            'hideGroups' => false,
            'recursive'  => false,
        );
     
        private $currentElement = null;
        private $currentGroup = null;
     
        public function __construct( $name, $label, $description, $required = true )
        {
            parent::__construct( $name, $label, $description, $required );
            $this->addElement( $this );
        }
     
        /**
         * Adds an element in the group.
         * 
         * @param daFormElement $element The element to add, the method will return it.
         * @return daFormElement The passed element.
         */
        public function addElement( daFormElement $element )
        {
            $this->elements[$element->name] = $element;
            return $element;
        }
     
        /**
         * Removes an element from the group.
         * 
         * @param daFormElement $element 
         * @return void
         */
        public function removeElement( daFormElement $element )
        {
            unset( $this->elements[$element->name] );
        }
     
        /**
         * Returns an element from the group.
         * 
         * @param string $name 
         * @return daFormElement
         */
        public function getElement( $name )
        {
            return $this->elements[$name];
        }
     
        /**
         * Sets any of the following options: hideGroups, recursive.
         * 
         * @param string $option Name of the option to set.
         * @param bool   $value  Value of the option to set.
         * @return daFormGroupElement
         */
        public function setIteratorOption( $option, $value )
        {
            if ( !is_string( $option ) )
            {
                throw new ezcBaseValueException( 'option', $option, 'strings', 'argument' );
            }
            if ( !in_array( $option, $this->iteratorOptions ) )
            {
                throw new ezcBaseValueException( 'option', $option, 'any of the following: ' . join( ', ', $this->iteratorOptions ), 'argument' );
            }
            if ( !is_bool( $value ) )
            {
                throw new ezcBaseValueException( 'value', $value, 'bools', 'argument' );
            }
            $this->iteratorOptions[$option] = $value;
        }
     
        /**
         * Returns the number of elements in the group. 
         * 
         * @return int Number of elements in the group.
         */
        public function count()
        {
            return count( $this->elements ) - 1;
        }
     
        public function next()
        {
            next( $this->elements );
        }
     
        public function current()
        {
            return current( $this->elements );
        }
     
        public function rewind()
        {
            reset( $this->elements );
        }
     
        public function valid()
        {
            return !is_null( key( $this->elements ) );
        }
     
        public function key()
        {
            return key( $this->elements );
        }
     
        public function hasChildren()
        {
            $current = $this->current();
            return $current && $current instanceof daFormGroupElement && count( $current );
        }
     
        public function getChildren()
        {
            return $this->current();
        }
    }
    ?>
    Voici le test:
    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
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    <?php
    class daFormTestGroupElement extends daFormTestCase
    {
        static public function suite()
        {
            return new PHPUnit_Framework_TestSuite( 'daFormTestGroupElement' );
        }
     
        // functionnal tests
     
        public function testElementContainerWithCount()
        {
            $g = new daFormGroupElement( 'testGroup', 'labelGroup', 'descriptionGroup', true );
            $el = $g->addElement( new daFormTestElementMock( 'testElement', 'labelElement', 'descriptionElement', true ) );
            $el2 = $g->addElement( new daFormTestElementMock( 'testElement2', 'labelElement2', 'descriptionElement2', true ) );
            $this->assertEquals( 2, count( $g ) );
            $g->removeElement( $el );
            $this->assertEquals( 1, count( $g ) );
            $this->assertEquals( $el2, $g->getElement( 'testElement2' ) );
        }
     
        public function testRecursiveIterator()
        {
            $root = self::getForm();
            $i = 0;
            foreach( $root as $name => $element )
            {
                switch( $i )
                {
                    case 0:
                        $this->assertEquals( 'widget', $name );
                        $this->assertEquals( $root, $element );
                        break;
                    case 1:
                        $this->assertEquals( 'name', $name );
                        $this->assertEquals( $root->getElement( $name ), $element );
                        break;
                    case 2:
                        $this->assertEquals( 'address', $name );
                        $address = $this->assertEquals( $root->getElement( $name ), $element );
                        break;
                    case 3:
                        $this->assertEquals( 'street', $name );
                        $this->assertEquals( $address->getElement( $name ), $element );
                        break;
                    case 4:
                        $this->assertEquals( 'city_group', $name );
                        $this->assertEquals( $root->getElement( $name ), $element );
                        break;
                    case 5:
                        $this->assertEquals( 'country', $name );
                        $this->assertEquals( $root->getElement( $name ), $element );
                        break;
                    case 6:
                        $this->assertEquals( 'zip', $name );
                        $this->assertEquals( $root->getElement( $name ), $element );
                        break;
                    case 7:
                        $this->assertEquals( 'city', $name );
                        $this->assertEquals( $root->getElement( $name ), $element );
                        break;
                    case 8:
                        $this->assertEquals( 'fav_lang', $name );
                        $this->assertEquals( $root->getElement( $name ), $element );
                        break;
     
                }
                $i++;
            }
            $this->assertEquals( 8, $i );
        }
     
        static public function getForm()
        {
            $form = new daFormGroupElement(
                'widget',
                'The widget of your dreams',
                'Please fill this form and let us know about the best widget that you could think of'
            );
     
            $form->addElement(
                new daFormTextElement(
                    'name',
                    'Your name',
                    'Please type your name.'
                )
            );
     
            $address = $form->addElement(
                new daFormGroupElement(
                    'address',
                    'Your Address',
                    'We need your address to contact you'
                )
            );
     
            $address->addElement(
                new daFormTextElement(
                    'street',
                    'Street name',
                    'The name of your street'
                )
            );
     
            $city = $address->addElement( 
                new daFormGroupElement( 
                    'city_group',
                    'Your city',
                    'Maybe we can figure your city name with your country and zip'
                )
            );
     
            $city->addElement(
                new daFormTextElement( 
                    'country',
                    'Country',
                    'Your country'
                )
            );
     
            $city->addElement( 
                new daFormTextElement( 
                    'zip',
                    'Zip',
                    'Your zipcode'
                )
            );
     
            $address->addElement(
                new daFormTextElement(
                    'city',
                    'City',
                    'Your city name is where you live',
                    false
                )
            );
     
            $form->addElement(
                new daFormTextElement(
                    'fav_lang',
                    'Your favourite language',
                    'Please type "PHP" in this field or be banned'
                )
            );
     
            return $form;
        }
    }
    ?>
    Voici le résultat du test:
    There was 1 failure:

    1) testRecursiveIterator(daFormTestGroupElement)
    Failed asserting that two strings are equal.
    expected string <street>
    difference <xxxxxx??>
    got string <fav_lang>
    /pd/sources/dac2/trunk/Form/tests/elements/group.php:43
    On remarque que l'itération n'est pas récursive du tout, et c'est la raison de l'échec du test.


    Notez que les autres classes impliquées sont testées et documentées.
    Débutant en OO, en developpement conduit par tests fonctionnels, en SPL Iterators ainsi qu'en documentation, j'éspère que je n'ai pas écrit de bêtises et que vous avez de quoi comprendre et résoudre mon problême dans ce message

  2. #2
    Membre émérite

    Profil pro
    H4X0|2 @ YourLabs Business Service
    Inscrit en
    Octobre 2006
    Messages
    657
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : H4X0|2 @ YourLabs Business Service
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2006
    Messages : 657
    Par défaut
    J'ai enfin compris, c'est tres simple.

    Classe:
    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
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
     
    <?php
    /**
     * File containing class daFormGroupElement.
     * 
     * @uses daFormElement
     * @package Form
     * @version //autogen//
     * @copyright Copyright (C) 2008 eZ Systems As. All rights reserved.
     * @author James Pic <jamespic@gmail.com> 
     * @license http://ez.no/licenses/new_bsd New BSD License
     */
    /**
     * This class allows to wrap several elements into one element.
     *
     * <code>
     * <?php
     * // instanciate a group
     * $group = new daFormGroupElement( $name, $label, $description, $required );
     * // add an element
     * $group->addElement( new daFormTextElement( 'nick', 'your nickname', 'your nickname is useful for others to recognize you', true ) );
     * // get an element
     * $nick = $group->getElement( 'nick' );
     * // remove an element
     * $group->removeElement( $nick );
     *
     * // Loop over all elements recursively including groups
     * $iterator = new RecursiveIteratorIterator( $group, RecursiveIteratorIterator::SELF_FIRST );
     * // Loop over all elements recursively
     * $iterator = new RecursiveIteratorIterator( $group, RecursiveIteratorIterator::LEAVES_ONLY );
     * // Loop over all elements of this groups, non-recursively
     * $iterator = new IteratorIterator( $group );
     *
     * // Use the iterator
     * foreach( $iterator as $name => $element )
     * {
     *   // do something ...
     * }
     * ?>
     * </code>
     * 
     * @uses daFormElement
     * @package Form
     * @version //autogen//
     */
    class daFormGroupElement extends daFormElement implements Countable, RecursiveIterator
    {
        /**
         * List of elements. 
         * 
         * @var array(name=>element)
         */
        protected $elements = array();
     
        public function __construct( $name, $label, $description, $required = true )
        {
            parent::__construct( $name, $label, $description, $required );
        }
     
        /**
         * Adds an element in the group.
         * 
         * @param daFormElement $element The element to add, the method will return it.
         * @return daFormElement The passed element.
         */
        public function addElement( daFormElement $element )
        {
            $this->elements[$element->name] = $element;
            return $element;
        }
     
        /**
         * Removes an element from the group.
         * 
         * @param daFormElement $element 
         * @return void
         */
        public function removeElement( daFormElement $element )
        {
            unset( $this->elements[$element->name] );
        }
     
        /**
         * Returns an element from the group.
         * 
         * @param string $name 
         * @return daFormElement
         */
        public function getElement( $name )
        {
            return $this->elements[$name];
        }
     
        /**
         * Returns the number of elements of this group. Non-recursive. 
         * 
         * @return void
         */
        public function count()
        {
            return count( $this->elements );
        }
     
        protected $current = null;
     
        /**
         * implements RecursiveIterator::hasChildren()
         *
         * @return bool current element has children
         */
        public function hasChildren()
        {
            $current = $this->current();
            return $current && $current instanceof daFormGroupElement && !$current->isLeaf();
        }
     
        /**
         * implements RecursiveIterator::getChildren()
         *
         * @return daFormGroupElement same as self::current()
         */
        public function getChildren()
        {
            return $this->current();
        }
     
        /**
         * implements Iterator::valid()
         *
         * @return bool check if there's a current element
         */
        public function valid()
        {
            return key($this->elements) !== null;
        }
     
        /**
         * implements Iterator::next()
         */
        public function next()
        {
            next($this->elements);
        }
     
        /**
         * implements Iterator::key()
         *
         * @return string key/local name of current element
         */
        public function key()
        {
            return key($this->elements);
        }
     
        /**
         * implements Iterator::current()
         *
         * @return daFormGroupElement current group
         */
        public function current()
        {
            return current($this->elements);
        }
     
        /**
         * implements Iterator::rewind()
         */
        public function rewind()
        {
            reset($this->elements);
        }
     
        /**
         * check if group has no subgroup
         *
         * @return bool true if no subgroups
         */
        public function isLeaf()
        {
            return empty($this->elements);
        }
     
    }
    ?>
    Tests:
    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
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
     
    <?php
    class daFormTestGroupElement extends daFormTestCase
    {
        static public function suite()
        {
            return new PHPUnit_Framework_TestSuite( 'daFormTestGroupElement' );
        }
     
        // functionnal tests
     
        public function testElementContainerWithCount()
        {
            $g = new daFormGroupElement( 'testGroup', 'labelGroup', 'descriptionGroup', true );
            $el = $g->addElement( new daFormTestElementMock( 'testElement', 'labelElement', 'descriptionElement', true ) );
            $el2 = $g->addElement( new daFormTestElementMock( 'testElement2', 'labelElement2', 'descriptionElement2', true ) );
            $this->assertEquals( 2, count( $g ) );
            $g->removeElement( $el );
            $this->assertEquals( 1, count( $g ) );
            $this->assertEquals( $el2, $g->getElement( 'testElement2' ) );
        }
     
        public function testRecursiveIterator()
        {
            $root = self::getForm();
            $root = new RecursiveIteratorIterator( $root, RecursiveIteratorIterator::SELF_FIRST);
            $elements = array();
            foreach( $root as $name => $element )
            {
                $elements[$name] = $element;
            }
            $this->assertEquals(
                array(
                    'name',
                    'address',
                    'street',
                    'city_group',
                    'country',
                    'zip',
                    'city',
                    'fav_lang',
                ),
                array_keys( $elements )
            );
        }
     
        static public function getForm()
        {
            $form = new daFormGroupElement(
                'widget',
                'The widget of your dreams',
                'Please fill this form and let us know about the best widget that you could think of'
            );
     
            $form->addElement(
                new daFormTextElement(
                    'name',
                    'Your name',
                    'Please type your name.'
                )
            );
     
            $address = $form->addElement(
                new daFormGroupElement(
                    'address',
                    'Your Address',
                    'We need your address to contact you'
                )
            );
     
            $address->addElement(
                new daFormTextElement(
                    'street',
                    'Street name',
                    'The name of your street'
                )
            );
     
            $city = $address->addElement( 
                new daFormGroupElement( 
                    'city_group',
                    'Your city',
                    'Maybe we can figure your city name with your country and zip'
                )
            );
     
            $city->addElement(
                new daFormTextElement( 
                    'country',
                    'Country',
                    'Your country'
                )
            );
     
            $city->addElement( 
                new daFormTextElement( 
                    'zip',
                    'Zip',
                    'Your zipcode'
                )
            );
     
            $address->addElement(
                new daFormTextElement(
                    'city',
                    'City',
                    'Your city name is where you live',
                    false
                )
            );
     
            $form->addElement(
                new daFormTextElement(
                    'fav_lang',
                    'Your favourite language',
                    'Please type "PHP" in this field or be banned'
                )
            );
     
            return $form;
        }
    }
    ?>
    Les discussions a ce sujet etant rares sur dvp, je ne demande pas le delestage.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [langage] listage répertoire en récursif
    Par Jeh dans le forum Langage
    Réponses: 3
    Dernier message: 22/12/2004, 15h01
  2. ecrire un iterateur pour une classe
    Par Blowih dans le forum C++
    Réponses: 2
    Dernier message: 15/11/2004, 19h19
  3. STL iterateur pour queue
    Par Mathieu.Nanoux dans le forum SL & STL
    Réponses: 2
    Dernier message: 05/11/2004, 00h35
  4. [LG]tri selection récursif
    Par max_lupin dans le forum Langage
    Réponses: 2
    Dernier message: 15/04/2004, 22h23
  5. Probleme liste chainne et recursif
    Par rippoz dans le forum Algorithmes et structures de données
    Réponses: 2
    Dernier message: 05/02/2004, 16h52

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