Joindre automatiquement des tables sans rompre le comportement par défaut dans Zend Framework

StackOverflow https://stackoverflow.com/questions/234785

  •  04-07-2019
  •  | 
  •  

Question

La situation est la suivante: J'ai 2 modèles: "Action" et "Utilisateur". Ces modèles font référence aux tables "actions" et "utilisateurs", respectivement.

Ma table d'actions contient une colonne id_utilisateur . Pour le moment, j'ai besoin d'une vue d'ensemble de toutes les actions et des utilisateurs auxquels elles sont affectées. Lorsque j'utilise $ action- > fetchAll () , je ne dispose que de l'ID utilisateur. Je souhaite donc pouvoir joindre les données du modèle utilisateur, de préférence sans appeler . findDependentRowset () .

J'ai pensé créer des méthodes personnalisées fetchAll () , fetchRow () et find () dans mon modèle, mais cela romprait les valeurs par défaut. comportement.

Quel est le meilleur moyen de résoudre ce problème? Toute aide serait grandement appréciée.

Était-ce utile?

La solution

J'ai conçu et mis en œuvre la fonctionnalité de relations de table dans Zend Framework.

Mon premier commentaire est que vous n'utiliseriez pas findDependentRowset () - vous utiliseriez findParentRow () si l'action a une référence de clé étrangère à l'utilisateur. .

$actionTable = new Action();
$actionRowset = $actionTable->fetchAll();
foreach ($actionRowset as $actionRow) {
  $userRow = $actionRow->findParentRow('User');
}

Modifier: Dans la boucle, vous avez maintenant un objet $ actionRow et un objet $ userRow. Vous pouvez réécrire les modifications dans la base de données via l'un des objets en modifiant les champs de l'objet et en appelant save () sur l'objet.

Vous pouvez également utiliser la classe Zend_Db_Table_Select (qui a été implémentée après avoir quitté le projet) pour récupérer un ensemble de lignes basé sur une jointure entre Action et Utilisateur.

$actionTable = new Action();
$actionQuery = $actionTable->select()
  ->setIntegrityCheck(false) // allows joins
  ->from($actionTable)
  ->join('user', 'user.id = action.user_id');
$joinedRowset = $actionTable->fetchAll($actionQuery);
foreach ($joinedRowset as $joinedRow) {
  print_r($joinedRow->toArray());
}

Notez qu'un tel ensemble de lignes basé sur une requête de jointure est en lecture seule. Vous ne pouvez pas définir de valeurs de champ dans les objets Row et appeler save () pour publier les modifications dans la base de données.

Modifier: il n’existe aucun moyen de rendre accessible en écriture un ensemble de résultats jointes. Prenons un exemple simple basé sur l'ensemble de résultats réunis ci-dessus:

action_id  action_type  user_id  user_name
   1          Buy          1       Bill
   2          Sell         1       Bill
   3          Buy          2       Aron
   4          Sell         2       Aron

Suivant pour la ligne avec action_id = 1, je modifie l'un des champs provenant de l'objet utilisateur:

$joinedRow->user_name = 'William';
$joinedRow->save();

Questions: lorsque je consulte la rangée suivante avec action_id = 2, dois-je voir «Bill» ou «William»? Si «William», cela signifie-t-il que la sauvegarde de la ligne 1 doit automatiquement mettre à jour «Bill» en «William» dans toutes les autres lignes de cet ensemble de résultats? Ou cela signifie-t-il que save () réexécute automatiquement la requête SQL pour obtenir un ensemble de résultats actualisé à partir de la base de données? Et si la requête prend du temps?

Considérez également la conception orientée objet. Chaque ligne est un objet séparé. Est-il approprié que l'appel de save () sur un objet ait pour effet de modifier des valeurs dans un objet séparé (même s'ils font partie de la même collection d'objets)? Cela ressemble à une forme de Couplage de contenu pour moi.

L'exemple ci-dessus est une requête relativement simple, mais des requêtes beaucoup plus complexes sont également autorisées. Zend_Db ne peut pas analyser les requêtes avec l'intention de dire des résultats en écriture à partir de résultats en lecture seule. C'est aussi pourquoi les vues MySQL ne peuvent pas être mises à jour.

Autres conseils

Vous pouvez toujours créer une vue dans votre base de données qui effectue la jointure à votre place.

CREATE OR REPLACE VIEW VwAction AS
SELECT [columns]
  FROM action
  LEFT JOIN user
    ON user.id = action.user_id

Ensuite, utilisez simplement

$vwAction->fetchAll();

N'oubliez pas que les vues dans MySQL sont en lecture seule (en supposant qu'il s'agisse de MySQL)

La création d’une table SQL vue n’est-elle pas une bonne solution pour créer un joint? et après une simple classe de table pour y accéder

Je pense que c'est mieux si votre logique est en SQL qu'en PHP

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top