2009-09-17 6 views
2

Je travaille sur une application développée en utilisant Zend Framework. J'ai défini des relations dans les modèles, et peut les utiliser avec bonheur, par exemple:Relations Zend Framework - Définition des noms de colonnes dans findManyToManyRowset()?

$rowset = $row->findManyToManyRowset('People', 'Jobs'); 

Cependant, je l'ai frappé un problème où l'ensemble de lignes est retourné a les noms de colonnes qui sont les mêmes dans les « gens » et « Emploi » , et donc, fusionne les clés de tableau, perdant certaines des données de l'ensemble de lignes final.

Je comprends que je peux passer un objet Zend_Db_Select-findManyToManyRowset() comme l'un des paramètres, mais ne peut trouver aucune documentation expliquant comment l'utiliser dans ce cas, par exemple:

$select = $this->select()->from(array(
            'p' => 'people', 
            'j' => 'jobs' 
            ), 
           array( 
            'person_id' => 'p.id', 
            'job_id' => 'j.id', 
            'person_code' => 'p.code', 
            'job_code' => 'j.code' 
            ) 
           ); 

Si je tente d'utiliser le code ci-dessus, je reçois un message tel que:

Error: No reference rule "" from table People to table Jobs 

Quelqu'un peut-il m'éclairer sur la façon dont cela devrait être fait? Je sais que je pourrais changer mes noms de colonnes dans la base de données, mais je préférerais un changement de code plutôt que de re-concevoir ma structure DB et de mettre à jour tout le code associé.

Note: sans une certaine forme d'aliasing colonne comme ci-dessus, le jeu de résultats retourné se présente comme suit (elle se confond les colonnes avec les mêmes noms.):

[_data:protected] => Array 
    (
     [id] => 1 
     [code] => SX342 
    ) 

Cheers,
Matt

Répondre

1

Ma première recommandation est que vous ne devriez pas nommer des colonnes telles que des noms génériques comme id et code. Ces noms n'ont aucun sens et, comme vous l'avez découvert, ils entraînent également des collisions lorsque vous récupérez des résultats dans un tableau associatif.

Vous utilisez également l'interface Select de manière incorrecte. Vous devez spécifier une seule table par appel from() ou appel join().

Enfin, je n'essaie jamais de faire des requêtes complexes via l'interface de relations Zend_Db_Table. Il est destiné uniquement aux cas simples. Si vous avez une requête plus complexe, écrivez simplement la requête SQL explicitement.

Voir aussi How to do a joined query in the ZF tables interface?

+0

Merci pour la réponse Bill. Avez-vous des recommandations sur la façon dont les colonnes devraient être nommées, ou sur une échelle plus large, des recommandations pour de bons tutoriels sur les meilleures pratiques de conception de base de données? – fistameeny

+0

Par exemple, vous pouvez utiliser "person_id" dans les deux tables, au lieu de "person_id" dans une table et "id" dans une autre table. Lorsque cela est possible, faites en sorte que les colonnes ayant le même contenu portent le même nom dans toutes les tables. De même "person_code" au lieu de simplement "code". Fondamentalement, faire des noms de colonnes distinctes à travers les tables, au moins quand il s'agit de tables susceptibles d'être jointes dans une requête. –

+0

Lisez le premier chapitre de "Style de programmation SQL de Joe Celko pour Smarties". Google Livres inclut le chapitre un dans son aperçu en ligne: http://books.google.com/books?id=a9jtyioHfp8C –

2

Je sais que cette réponse est un peu en retard, mais voici quelques choses à signaler.

1) findManyToManyRowset($matchTable, $intersectionTable, $callerRefRule, $matchRefRule, $select); - Si vous passez un Zend_Db_Table_Select vous allez vouloir passer null pour les règles.

2) Le Zend_Db_Table_Select passé dans le findManyToManyRowset() devrait être créé à partir $matchTable et il est raisonnable de supposer que, dans les clauses where i est l'alias de la table d'intersection et m est l'alias de la table de correspondance.

3) Dans le cas de collisions, m va gagner le nom de la clé dans le tableau associatif retourné en php.La requête exécutée ressemble à ceci:

SELECT 
    `i`.*, `m`.* 
    FROM 
    `interscetTable` AS `i` 
    INNER JOIN 
    `matchTable` AS `m` 
    ON 
    `i`.`fk_m` = `m`.`pk` WHERE (`i`.`fk_o` = ?) 

4) Peu importe, la valeur de retour de findManyToManyRowset() sera un Rowset créé à partir du $matchTable donc, si vous devez saisir les informations de la table d'intersection, tout en capturant les données pour la table de correspondance, vous aurez probablement besoin d'un Zend_Db_Select personnalisé et évitez d'utiliser les trucs Zend_Db_Table pour mapper les données quand même. Donc, un exemple de travail, utilisant "People" comme table de correspondance, "Workers" comme table d'intersection et disant "Clients" comme table d'origine .. En supposant pour cet exemple que les tables lient ensemble quelque chose comme: Gens. id:... -> travailleurs. person_id:client_id:job_id -> clients: id:...

$client = $clientTable->fetchRow(); /// grab a random client 

// fetch all people that have worked for the client ordered by their last name. 
$client->findManyToManyRowset("People", "Workers", null, null, 
    $peopleTable->select()->order('m.lastname')); 

// fetch all people that have worked for the client ordered by their hire date: 
// `workers`.`hiredate` 
$client->findManyToManyRowset("People", "Workers", null, null, 
    $peopleTable->select()->order('i.hiredate'));