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

Zend Framework PHP Discussion :

ZF2 : table avec prefix


Sujet :

Zend Framework PHP

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    79
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Mars 2007
    Messages : 79
    Points : 48
    Points
    48
    Par défaut ZF2 : table avec prefix
    Bonjour à tous,

    Je suis en train me former à Zend Framework 2 en suivant le tutoriel officiel (http://framework.zend.com/manual/2.1...plication.html). Et j'essaie de l'adapter à ma base de données.

    Mon problème vient du fait que toutes mes tables sont préfixées par deux lettres suivies d'un underscore (configurable à l'instalation de la base de données). Et j'aimerai que la classe AlbumTable garde ce nom au lieu de xx_AlbumTable.

    Voici la classe AlbumTable (reprise du tuto) située dans le répertoire module/Album/src/Album/Model :
    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
    ?php
    namespace Album\Model;
     
    use Zend\Db\TableGateway\TableGateway;
     
    class AlbumTable
    {
        protected $tableGateway;
     
        public function __construct(TableGateway $tableGateway)
        {
            $this->tableGateway = $tableGateway;
        }
     
        public function fetchAll()
        {
            $resultSet = $this->tableGateway->select();
            return $resultSet;
        }
     
        public function getAlbum($id)
        {
            $id  = (int) $id;
            $rowset = $this->tableGateway->select(array('id' => $id));
            $row = $rowset->current();
            if (!$row) {
                throw new \Exception("Could not find row $id");
            }
            return $row;
        }
     
        public function saveAlbum(Album $album)
        {
            $data = array(
                'artist' => $album->artist,
                'title'  => $album->title,
            );
     
            $id = (int)$album->id;
            if ($id == 0) {
                $this->tableGateway->insert($data);
            } else {
                if ($this->getAlbum($id)) {
                    $this->tableGateway->update($data, array('id' => $id));
                } else {
                    throw new \Exception('Form id does not exist');
                }
            }
        }
     
        public function deleteAlbum($id)
        {
            $this->tableGateway->delete(array('id' => $id));
        }
    }
    J'ai donc essayé de modifier le nom de la table dans le constructor en faisant un set table, mais j'ai l'erreur suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Invalid magic property access in Zend\Db\TableGateway\AbstractTableGateway::__set()
    A priori, la classe TableGateway n’autorise pas la modification de la table.

    Je vois pour l'instant qu'une solution qui est de créée une classe qui hérite de TableGateway en modifiant dans son construtor le nom de la table. Mais ça me plait pas trop car il faudra faire ça pour toutes mes tables !

    Je voudrais savoir s'il y avait une solution "plus élégante", c'est-à-dire plus une solution avec moins de code à écrire.

  2. #2
    En attente de confirmation mail

    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2003
    Messages
    253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Février 2003
    Messages : 253
    Points : 637
    Points
    637
    Par défaut
    Bonjour,

    Petit disclaimer, je débute totalement sur ZF2 je n'ai pour le moment même pas posé une ligne de code... Par contre j'ai pas mal lu dessus, aussi j'en profite pour me former un peu

    Si j'en crois cette étape : http://framework.zend.com/manual/2.1...the-albumtable

    Le ServiceManager a une entrée AlbumTableGateway qui configure le nom de la table à passer au TableGateway. Donc soit tu modifies le premier paramètre du constructeur en rajoutant ton préfixe... soit tu veux que le préfixe soit automatiquement ajouté pour toutes tes tables si je comprends bien ?

    Si oui je pense que la solution se trouve du côté de créer ta propre factory, dont le rôle sera de préfixer le nom des tables par ton préfixe, et de configurer le ServiceManager pour l'utiliser.

    Je proposerais bien un morceau de code, mais je n'ai pas d'environnement de travail pour tester... si tu recherches encore j'essayerais de faire un poc rapide, si personne avec des compétences ZF2 ne passe avant

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    79
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Mars 2007
    Messages : 79
    Points : 48
    Points
    48
    Par défaut
    merci Nighty pour ton aide.

    J'ai modifié dans le fichier Module.php le nom de la table en dur pour tester et ça fonctionne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return new TableGateway('xx_album', $dbAdapter, null, $resultSetPrototype);

    Maintenant, reste à aller chercher le préfixe dans la conf. (je pense mettre ça dans le fichier config/autoload/global.php dans la section 'db') et à automatiser le préfixage, je vais me diriger vers ta piste de la Factory. Mais, il me reste encore pas mal de notions de ZF2 à appréhender avant de developper cette factory.

  4. #4
    En attente de confirmation mail

    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2003
    Messages
    253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Février 2003
    Messages : 253
    Points : 637
    Points
    637
    Par défaut
    J'ai fait un petit test qui pourrait être concluent dans le contexte du tutorial (pour ma part je me suis contenté d'un die pour valider ma théorie...).

    Très possible que ce code soit une erreur d'interprétation de ma part, mais voilà l'idée.

    D'abord on met en place une AbstractFactory :
    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
    <?php
    namespace Album\Factory;
     
    class TableGateway implements \Zend\ServiceManager\AbstractFactoryInterface
    {
        const TABLE_PREFIX = 'xx_';
        const TABLE_GATEWAY_SUFFIX = 'tablegateway';
     
        public function canCreateServiceWithName(\Zend\ServiceManager\ServiceLocatorInterface $serviceLocator, $name, $requestedName)
        {
            return strpos($name, self::TABLE_GATEWAY_SUFFIX) !== false;
        }
     
        public function createServiceWithName(\Zend\ServiceManager\ServiceLocatorInterface $serviceLocator, $name, $requestedName)
        {
            $tableName = substr($name, 0, strpos($name, self::TABLE_GATEWAY_SUFFIX));
            $prefixedName = self::TABLE_PREFIX . $tableName;
            $dbAdapter = $serviceLocator->get('Zend\Db\Adapter\Adapter');
            $resultSetPrototype = new \Zend\Db\ResultSet\ResultSet();
            $resultSetPrototype->setArrayObjectPrototype(new \Application\Model\TableAlbum());
            return new TableGateway($prefixedName, $dbAdapter, null, $resultSetPrototype);
        }
    }
    L'abstract factory part du principe que le nom dans le ServiceManager se construit comme ${NomTable}TableGateway, ce qui est très light et mériterait de creuser...

    Ensuite dans la configuration du module :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    'service_manager' => array(
        'factories' => array(
            'Album\Model\AlbumTable' =>  function($sm) {
                $tableGateway = $sm->get('AlbumTableGateway');
                $table = new AlbumTable($tableGateway);
                return $table;
            }
        ),
        'abstract_factories' => array(
            'AlbumTableGateway' => 'Album\Factory\TableGateway',
        )
    ),
    A priori, ça devrait marcher... je suis pas contre un retour

  5. #5
    En attente de confirmation mail

    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2003
    Messages
    253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Février 2003
    Messages : 253
    Points : 637
    Points
    637
    Par défaut
    Petit up car je viens de finir le tutorial, j'ai donc une solution qui marche que je te propose ici.

    Dans modules/Album/Module.php :
    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
        public function getServiceConfig()
        {
            return array(
                'invokables' => array(
                    'AlbumModel' => 'Album\Model\Album'
                ),
                'factories' => array(
                    'Album\Model\AlbumTable' => function (ServiceLocatorInterface $sm) {
                        $tableGateway = $sm->get('AlbumTableGateway');
                        $table = new AlbumTable($tableGateway);
                        return $table;
                    }
                ),
                'abstract_factories' => array(
                    'TableGateway' => 'Application\Factory\TableGatewayFactory'
                )
            );
        }
    Dans modules/Application/Factory/TableGatewayFactory.php :
    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
    <?php
    namespace Application\Factory;
    use Zend\ServiceManager\AbstractFactoryInterface,
        Zend\ServiceManager\ServiceLocatorInterface,
        Zend\Db\TableGateway\TableGateway,
        Zend\Db\ResultSet\ResultSet;
     
    class TableGatewayFactory implements AbstractFactoryInterface
    {
        const TABLE_PREFIX = 'my_';
        const TABLE_GATEWAY_SUFFIX = 'tablegateway';
     
        public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
        {
            return strpos($name, self::TABLE_GATEWAY_SUFFIX) !== false;
        }
     
        public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
        {
            $tableName = $this->getTableNameFromServiceName($name);
            $modelClassName = $this->getModelClassNameFromTableName($tableName);
            $prefixedTableName = self::TABLE_PREFIX . $tableName;
            return $this->createTableGateway($serviceLocator, $prefixedTableName, $modelClassName);
        }
     
        protected function getTableNameFromServiceName($serviceName)
        {
            $suffixPos = strpos($serviceName, self::TABLE_GATEWAY_SUFFIX);
            $tableName = substr($serviceName, 0, $suffixPos);
            return $tableName;
        }
     
        protected function getModelClassNameFromTableName($tableName)
        {
            $modelClassName = ucfirst($tableName) . 'Model';
            return $modelClassName;
        }
     
        protected function createTableGateway(ServiceLocatorInterface $serviceLocator, $tableName, $modelClassName)
        {
            $dbAdapter = $serviceLocator->get('Zend\Db\Adapter\Adapter');
            $model = $serviceLocator->get($modelClassName);
            $resultSetPrototype = new ResultSet();
            $resultSetPrototype->setArrayObjectPrototype($model);
            return new TableGateway($tableName, $dbAdapter, null, $resultSetPrototype);
        }
    }
    Honnêtement je trouve ça beaucoup trop intimement lié à une convention de nommage pour être fiable... Je ne l'utiliserais personnellement pas en production, mais c'était pour le fun !

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    79
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Mars 2007
    Messages : 79
    Points : 48
    Points
    48
    Par défaut
    Je viens de mettre en place ton code et j'ai une erreur 500
    J'ai regardé dans les logs et j'ai l'exception suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    PHP Fatal error:  Uncaught exception 'Zend\\ServiceManager\\Exception\\InvalidArgumentException' with message 'Provided abstract factory must be the class name of an abstract factory or an instance of an AbstractFactoryInterface.' in /home/nicolas/zendTest/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:302
    Stack trace:
    #0 /home/nicolas/zendTest/vendor/zendframework/zendframework/library/Zend/ServiceManager/Config.php(126): Zend\\ServiceManager\\ServiceManager->addAbstractFactory('Application\\Fac...')
    #1 /home/nicolas/zendTest/vendor/zendframework/zendframework/library/Zend/ModuleManager/Listener/ServiceListener.php(223): Zend\\ServiceManager\\Config->configureServiceManager(Object(Zend\\ServiceManager\\ServiceManager))
    #2 [internal function]: Zend\\ModuleManager\\Listener\\ServiceListener->onLoadModulesPost(Object(Zend\\ModuleManager\\ModuleEvent))
    #3 /home/nicolas/zendTest/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php(460): call_user_func(Array, Object(Zend\\ in /home/nicolas/zendTest/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php on line 302
    Je suis aller voir dans le code et cette exception est déclenchée lorsque la factory ne satisfait pas ces conditions :
    Zend\ServiceManager\ServiceManager.php
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     public function setFactory($name, $factory, $shared = null)
        {
            $cName = $this->canonicalizeName($name);
     
            if (!is_string($factory) && !$factory instanceof FactoryInterface && !is_callable($factory)) {
                throw new Exception\InvalidArgumentException(
                    'Provided abstract factory must be the class name of an abstract factory or an instance of an AbstractFactoryInterface.'
                );
            }
    		...

    J'ai tout d'abord pensé à un mauvais formatage du nom de la classe (mauvais copier/coller, problème de casse, ...). Mais a priori ce n'est pas ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    ll -R /home/nicolas/zendTest/module/
    ...
    /home/nicolas/zendTest/module/Application/Factory:
    total 4
    -rw-r--r-- 1 nicolas nicolas 1815  4 mars  10:25 TableGatewayFactory.php
    ...
    J'ai ensuite pensé un problème d'import dans mon fichier module/Album/Module.php, j'ai donc rajouté un use sur TableGatewayFactory. Mais ce n'est pas ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    use Application\Factory\TableGatewayFactory;
    C'est certainement une erreur à la ***, mais laquelle ?

  7. #7
    En attente de confirmation mail

    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2003
    Messages
    253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Février 2003
    Messages : 253
    Points : 637
    Points
    637
    Par défaut
    Curieux, ta directive use ne changera rien en l'état vu que l'instanciation ne se fait pas dans Module.php, mais l'erreur me laisse un peu perplexe.

    Tu as possibilité de tracer la variable $factory de la méthode setFactory ? Car visiblement ce n'est pas un string alors que ça devrait l'être...

    Pour info j'ai fait le test sur ZendCloud, et donc en ZF 2.0. Visiblement tu es dans une version plus récente car le code mentionné est ligne 243 pour moi.

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    79
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Mars 2007
    Messages : 79
    Points : 48
    Points
    48
    Par défaut
    Je suis effectivement en version ZF 2.1.

    Je viens de tracer la variable $factory et j'ai la valeur suivante : "Application\Factory\TableGatewayFactory"

    Mais, je viens de me rendre compte dans la trace que l'erreur est à la ligne 304 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    PHP Fatal error:  Uncaught exception 'Zend\ServiceManager\Exception\InvalidArgumentException' with message 'Provided abstract factory must be the class name of an abstract factory or an instance of an AbstractFactoryInterface : "Application\Factory\TableGatewayFactory"' in /home/nicolas/zendTest/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:304
    Stack trace:
    #0 /home/nicolas/zendTest/vendor/zendframework/zendframework/library/Zend/ServiceManager/Config.php(126): Zend\ServiceManager\ServiceManager->addAbstractFactory('Application\Fac...')
    #1 /home/nicolas/zendTest/vendor/zendframework/zendframework/library/Zend/ModuleManager/Listener/ServiceListener.php(223): Zend\ServiceManager\Config->configureServiceManager(Object(Zend\ServiceManager\ServiceManager))
    #2 [internal function]: Zend\ModuleManager\Listener\ServiceListener->onLoadModulesPost(Object(Zend\ModuleManager\ModuleEvent))
    #3 /home/nicolas/zendTest/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.p in /home/nicolas/zendTest/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php on line 304
    Cette ligne ne correspont pas à la méthode setFactory mais à addAbstractFactory ! Et la condition qui ne passe pas est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (!class_exists($factory, true))
    PHP n'arrive pas à changer ma classe TableGatewayFactory ! Pourtant la classe est dans le bon repertoire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    ll -R /home/nicolas/zendTest/module/
    ...
    /home/nicolas/zendTest/module/Application/Factory:
    total 4
    -rw-r--r-- 1 nicolas nicolas 1815  4 mars  10:25 TableGatewayFactory.php
    ...
    Et le nom de la classe dans le fichier TableGatewayFactory.php me parait correct :
    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
    <?php
    namespace Application\Factory;
    use Zend\ServiceManager\AbstractFactoryInterface,
        Zend\ServiceManager\ServiceLocatorInterface,
        Zend\Db\TableGateway\TableGateway,
        Zend\Db\ResultSet\ResultSet;
     
    class TableGatewayFactory implements AbstractFactoryInterface
    {
        const TABLE_PREFIX = 'am_';
        const TABLE_GATEWAY_SUFFIX = 'tablegateway';
     
        public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
        {
            return strpos($name, self::TABLE_GATEWAY_SUFFIX) !== false;
        }
     
        public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
        {
            $tableName = $this->getTableNameFromServiceName($name);
            $modelClassName = $this->getModelClassNameFromTableName($tableName);
            $prefixedTableName = self::TABLE_PREFIX . $tableName;
            return $this->createTableGateway($serviceLocator, $prefixedTableName, $modelClassName);
        }
     
        protected function getTableNameFromServiceName($serviceName)
        {
            $suffixPos = strpos($serviceName, self::TABLE_GATEWAY_SUFFIX);
            $tableName = substr($serviceName, 0, $suffixPos);
            return $tableName;
        }
     
        protected function getModelClassNameFromTableName($tableName)
        {
            $modelClassName = ucfirst($tableName) . 'Model';
            return $modelClassName;
        }
     
        protected function createTableGateway(ServiceLocatorInterface $serviceLocator, $tableName, $modelClassName)
        {
            $dbAdapter = $serviceLocator->get('Zend\Db\Adapter\Adapter');
            $model = $serviceLocator->get($modelClassName);
            $resultSetPrototype = new ResultSet();
            $resultSetPrototype->setArrayObjectPrototype($model);
            return new TableGateway($tableName, $dbAdapter, null, $resultSetPrototype);
        }
    }

  9. #9
    En attente de confirmation mail

    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2003
    Messages
    253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Février 2003
    Messages : 253
    Points : 637
    Points
    637
    Par défaut
    C'est déjà plus compréhensible pour le coup. Le module Application est bien enregistré dans ta configuration globale ? Et l'autoloader du module Application est bien configuré ?

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    79
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Mars 2007
    Messages : 79
    Points : 48
    Points
    48
    Par défaut
    Oui, le module Application est bien enregistré ainsi que le module Album.
    config/application.config.php
    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
    <?php
    return array(
        // This should be an array of module namespaces used in the application.
        'modules' => array(
            'Application',
    	'Album',
        ),
     
        // These are various options for the listeners attached to the ModuleManager
        'module_listener_options' => array(
            // This should be an array of paths in which modules reside.
            // If a string key is provided, the listener will consider that a module
            // namespace, the value of that key the specific path to that module's
            // Module class.
            'module_paths' => array(
                './module',
                './vendor',
            ),
     
            // An array of paths from which to glob configuration files after
            // modules are loaded. These effectively overide configuration
            // provided by modules themselves. Paths may use GLOB_BRACE notation.
            'config_glob_paths' => array(
                'config/autoload/{,*.}{global,local}.php',
            ),
     
            // Whether or not to enable a configuration cache.
            // If enabled, the merged configuration will be cached and used in
            // subsequent requests.
            //'config_cache_enabled' => $booleanValue,
     
            // The key used to create the configuration cache file name.
            //'config_cache_key' => $stringKey,
     
            // Whether or not to enable a module class map cache.
            // If enabled, creates a module class map cache which will be used
            // by in future requests, to reduce the autoloading process.
            //'module_map_cache_enabled' => $booleanValue,
     
            // The key used to create the class map cache file name.
            //'module_map_cache_key' => $stringKey,
     
            // The path in which to cache merged configuration.
            //'cache_dir' => $stringPath,
     
            // Whether or not to enable modules dependency checking.
            // Enabled by default, prevents usage of modules that depend on other modules
            // that weren't loaded.
            // 'check_dependencies' => true,
        ),
     
        // Used to create an own service manager. May contain one or more child arrays.
        //'service_listener_options' => array(
        //     array(
        //         'service_manager' => $stringServiceManagerName,
        //         'config_key'      => $stringConfigKey,
        //         'interface'       => $stringOptionalInterface,
        //         'method'          => $stringRequiredMethodName,
        //     ),
        // )
     
       // Initial configuration with which to seed the ServiceManager.
       // Should be compatible with Zend\ServiceManager\Config.
       // 'service_manager' => array(),
    );

  11. #11
    En attente de confirmation mail

    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2003
    Messages
    253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Février 2003
    Messages : 253
    Points : 637
    Points
    637
    Par défaut
    Et dans la configuration de l'autoloader dans le Module.php dans le module Application est ok ?

    Si oui, il faudrait creuser en tentant de charger la classe autrement, en la plaçant temporairement dans le module Album (et en modifiant la config / le nom du namespace), en utilisant l'autoload_map... ça t'aidera à diagnostiquer pourquoi le chargement de la classe ne se fait pas.

  12. #12
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    79
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Mars 2007
    Messages : 79
    Points : 48
    Points
    48
    Par défaut
    Je viens de trouver d'où vient l'erreur :
    J'avais mis le dossier factory à la racine du module Application (module/Application/factory). Je l'ai donc déplacé dans le répertoire src du module Application (module/Application/src/Application/factory)

    Malheureusement quand j'essaie de charger la page album, j'ai maintenant une autre erreur 500 :
    Voici la trace :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     PHP Catchable fatal error:  Argument 1 passed to Album\{closure}() must be an instance of Album\ServiceLocatorInterface, instance of Zend\ServiceManager\ServiceManager given in /home/nicolas/zendTest/module/Album/Module.php on line 47
    et voici le code de module/Album/Module.php :
    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
    <?php
    namespace Album;
     
    use Album\Model\Album;
    use Album\Model\AlbumTable;
    use Zend\Db\ResultSet\ResultSet;
    use Zend\Db\TableGateway\TableGateway;
     
     
    class Module
    {
        public function getAutoloaderConfig()
        {
            return array(
                'Zend\Loader\ClassMapAutoloader' => array(
                    __DIR__ . '/autoload_classmap.php',
                ),
                'Zend\Loader\StandardAutoloader' => array(
                    'namespaces' => array(
                        __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
                    ),
                ),
            );
        }
     
    	// Add this method:
        public function getServiceConfig()
        {
    		return array(
                'invokables' => array(
                    'AlbumModel' => 'Album\Model\Album'
                ),
                'factories' => array(
                    'Album\Model\AlbumTable' => function (ServiceLocatorInterface $sm) { // ligne 47
                        $tableGateway = $sm->get('AlbumTableGateway');
                        $table = new AlbumTable($tableGateway);
                        return $table;
                    }
                ),
                'abstract_factories' => array(
                    'TableGateway' => 'Application\Factory\TableGatewayFactory'
                )
            );
        }
     
        public function getConfig()
        {
            return include __DIR__ . '/config/module.config.php';
        }
    }
    A priori j'appelle la fonction 'Album\Model\AlbumTable' => function (ServiceLocatorInterface $sm) avec un mauvais paramètre, mais je ne sais pas où est fait cet appel dans Zend.

  13. #13
    En attente de confirmation mail

    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2003
    Messages
    253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Février 2003
    Messages : 253
    Points : 637
    Points
    637
    Par défaut
    Citation Envoyé par CocoLeNain Voir le message
    Je viens de trouver d'où vient l'erreur :
    J'avais mis le dossier factory à la racine du module Application (module/Application/factory). Je l'ai donc déplacé dans le répertoire src du module Application (module/Application/src/Application/factory)
    My bad, j'ai dû t'induire en erreur. Effectivement, toutes les classes des modules va dans src à l'exception de la classe Module.

    Malheureusement quand j'essaie de charger la page album, j'ai maintenant une autre erreur 500 :
    Voici la trace :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     PHP Catchable fatal error:  Argument 1 passed to Album\{closure}() must be an instance of Album\ServiceLocatorInterface, instance of Zend\ServiceManager\ServiceManager given in /home/nicolas/zendTest/module/Album/Module.php on line 47
    En fait j'ai fait du zèle et j'ai mis un typehint dans la closure d'instanciation de la classe AlbumTable pour qu'elle n'accepte qu'un ServiceLocatorInterface (le ServiceManager l'implémente donc ça ne posera pas de soucis).

    Sauf que pour que ça marche il faut soit mettre le FQCN de l'interface ServiceLocatorInterface dans le typehint, soit rajouter la directive use :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    use Zend\ServiceManager\ServiceLocatorInterface;
    Pour le coup j'ai complexifié mon exemple plus que nécessaire, désolé

  14. #14
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    79
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Mars 2007
    Messages : 79
    Points : 48
    Points
    48
    Par défaut
    ça fonctionne mieux avec la directive use.

    merci pour ton aide.

    Par contre, j'ai une question :

    Pourquoi $name dans la classe TableGatewayFactory est tout en minuscule ?

    Car je vais avoir des tables du xx_TotoTyty, et je sens que je vais avoir des problèmes avec la casse.

  15. #15
    En attente de confirmation mail

    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2003
    Messages
    253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Février 2003
    Messages : 253
    Points : 637
    Points
    637
    Par défaut
    Pour l'occasion, je m'auto-quote :

    Citation Envoyé par Nighty Voir le message
    Honnêtement je trouve ça beaucoup trop intimement lié à une convention de nommage pour être fiable... Je ne l'utiliserais personnellement pas en production, mais c'était pour le fun !
    Sur cette base, à toi de transformer la Factory pour coller à tes besoins, tu peux utiliser la variable $requestedName qui elle conserve la casse plutôt que $name... par contre si tes tables ne suivent jamais le même schéma de nommage, tu risques d'avoir du mal à faire fonctionner l'ensemble

  16. #16
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    79
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Mars 2007
    Messages : 79
    Points : 48
    Points
    48
    Par défaut
    y a pas de risques, mes tables suivent toutes le même formatage.

    A la base je suis parti sur cette convention de nommage car je l'avais vu dans wordpress.

    Maintenant, en réfléchissant je sais si c'est une bonne idée.

    Mais tout cas ça ma permit de mieux comprendre comment Zend fonctionne.

    Et encore un grand merci.

  17. #17
    En attente de confirmation mail

    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2003
    Messages
    253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Février 2003
    Messages : 253
    Points : 637
    Points
    637
    Par défaut
    Vraiment pas de quoi, ça m'a permis de mettre en pratique sur un cas concret

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

Discussions similaires

  1. [MySQL-5.0] Dupliquer des tables avec prefixe
    Par jeremy059 dans le forum Requêtes
    Réponses: 0
    Dernier message: 09/10/2013, 11h59
  2. [MySQL] Exporter les tables avec un prefix défini
    Par Invité dans le forum PHP & Base de données
    Réponses: 0
    Dernier message: 29/01/2011, 16h04
  3. Réponses: 0
    Dernier message: 19/03/2010, 14h31
  4. [Access] Nom d'une table avec un espace dans SQL
    Par Corsaire dans le forum Langage SQL
    Réponses: 7
    Dernier message: 21/04/2006, 15h50
  5. Création de table avec index
    Par Seb7 dans le forum Requêtes
    Réponses: 2
    Dernier message: 10/04/2003, 16h11

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