2010-12-04 24 views
0

Je sais que le titre ne décrit pas le meilleur que je veux atteindre, mais je ne pouvais pas penser à autre chose.CakePHP afficher les champs personnalisés du tableau

Disons que j'ai le tableau suivant:

[Sender] => Array 
      (
       [0] => Array 
        (
         [id] => 1 
         [username] => admin 
         [PrivateMessagesUser] => Array 
          (
           [id] => 1 
           [private_message_id] => 1 
           [sender_id] => 1 
           [recipient_id] => 3 
           [sender_status] => 1 
           [recipient_status] => 0 
           [random_key] => 
          ) 

        ) 

       [1] => Array 
        (
         [id] => 1 
         [username] => admin 
         [PrivateMessagesUser] => Array 
          (
           [id] => 3 
           [private_message_id] => 1 
           [sender_id] => 1 
           [recipient_id] => 2 
           [sender_status] => 1 
           [recipient_status] => 0 
           [random_key] => 
          ) 

        ) 

      ) 

J'utilise le ContainableBehaviour pour couper des données supplémentaires. Mon problème est: comment puis-je filtrer le Sender s après une clé qui est présent dans PrivateMessagesUser? Dire que j'ai besoin seulement de SenderPrivateMessagesUser.recipient_id = 3. J'ai essayé avec

'Sender' => array( 
'PrivateMessagesUser' => array(

) 
), 

mais cela n'a pas fonctionné. On dirait que je dois dépasser les touches [0], [1] ... et je ne sais pas comment.

Toute aide serait appréciée!

EDIT

Voilà comment j'obtenir le tableau affiché ci-dessus:

$this->paginate = array(
     'conditions' => array(
      'PrivateMessage.id' => $this->__getUserPrivateMessagesInbox() 
     ), 
     'contain' => array(
      'Sender' => array(
       'fields' => array('id', 'username'), 
       'PrivateMessagesUser' => array(
        'fields' => array('PrivateMessagesUser.id') 
        //'conditions' => array('PrivateMessagesUser.recipient_id' => $this->Auth->user('id')) 
       ) 
      ), 
      'Recipient' => array(
       'fields' => array('id', 'username'), 
       'conditions' => array('Recipient.id' => $this->Auth->user('id')) 
      ) 
     ) 
    ); 

Comment puis-je modifier ces lignes afin d'obtenir le résultat souhaité?

EDIT 2

J'appelle la paginate() du PrivateMessagesController.

Associations:

Modèle utilisateur:

var $hasAndBelongsToMany = array(
    'PrivateMessageSent' => array(
     'className' => 'PrivateMessage', 
     'joinTable' => 'private_messages_users', 
     'foreignKey' => 'sender_id', 
     'associationForeignKey' => 'private_message_id', 
     'unique' => true, 
     'conditions' => '', 
     'fields' => '', 
     'order' => '', 
     'limit' => '', 
     'offset' => '', 
     'finderQuery' => '', 
     'deleteQuery' => '', 
     'insertQuery' => '' 
    ), 
    'PrivateMessageReceived' => array(
     'className' => 'PrivateMessage', 
     'joinTable' => 'private_messages_users', 
     'foreignKey' => 'recipient_id', 
     'associationForeignKey' => 'private_message_id', 
     'unique' => true, 
     'conditions' => '', 
     'fields' => '', 
     'order' => '', 
     'limit' => '', 
     'offset' => '', 
     'finderQuery' => '', 
     'deleteQuery' => '', 
     'insertQuery' => '' 
    ) 
); 

PrivateMessage Modèle:

var $hasAndBelongsToMany = array(
    'Sender' => array(
     'className' => 'User', 
     'joinTable' => 'private_messages_users', 
     'foreignKey' => 'private_message_id', 
     'associationForeignKey' => 'sender_id', 
     'unique' => true, 
     'conditions' => '', 
     'fields' => '', 
     'order' => '', 
     'limit' => '', 
     'offset' => '', 
     'finderQuery' => '', 
     'deleteQuery' => '', 
     'insertQuery' => '' 
    ), 
    'Recipient' => array(
     'className' => 'User', 
     'joinTable' => 'private_messages_users', 
     'foreignKey' => 'private_message_id', 
     'associationForeignKey' => 'recipient_id', 
     'unique' => true, 
     'conditions' => '', 
     'fields' => '', 
     'order' => '', 
     'limit' => '', 
     'offset' => '', 
     'finderQuery' => '', 
     'deleteQuery' => '', 
     'insertQuery' => '' 
    ), 
); 

PrivateMessagesUser Modèle:

var $belongsTo = array(
    'PrivateMessage' => array(
     'className' => 'PrivateMessage', 
     'foreignKey' => 'private_message_id', 
     'conditions' => '', 
     'fields' => '', 
     'order' => '' 
    ), 
    'Sender' => array(
     'className' => 'User', 
     'foreignKey' => 'sender_id', 
     'conditions' => '', 
     'fields' => '', 
     'order' => '' 
    ), 
    'Recipient' => array(
     'className' => 'User', 
     'foreignKey' => 'recipient_id', 
     'conditions' => '', 
     'fields' => '', 
     'order' => '' 
    ) 
); 

et les tables de base de données ressemblent à:

  • users: id, username ...
  • private_messages: id, subject ...
  • private_messages_users: id, private_message_id, sender_id, recipient_id, status, ...
+0

Cela n'a pas de sens: un message privé peut avoir plusieurs expéditeurs? Plusieurs destinataires semblent communs. À moins que ce ne soit une forme de fonctionnalité filetée. – RabidFire

+0

Vous avez raison, il n'y a qu'un seul expéditeur. Mais je pensais que si j'ai 2 relations différentes pour le même modèle n'est pas correct. Comment suggérez-vous de changer ces relations afin de donner un sens et de garder la fonctionnalité? – linkyndy

Répondre

2

Il sont trois façons d'y parvenir.

En regardant votre tableau de données retourné, je suppose que PrivateMessagesUser appartient à Sender.

1. Interroger le modèle PrivateMessagesUser

Parfois, il suffit d'interroger le bon modèle. Vous pouvez appliquer les conditions directement au modèle pour lequel vous souhaitez appliquer vos restrictions.

$this->Sender->PrivateMessagesUser->find('all', array(
    'conditions' => array('PrivateMessagesUser.recipient_id' => 3), 
    'contain' => array('Sender') 
)); 

2. Appliquer des conditions aux modèles connexes

Cela ne fonctionne pas tout le temps, parce que la génération de SQL CakePHP ne fonctionne pas toujours comme vous le souhaitez. Mais dans les cas simples comme une relation hasMany, vous pouvez utiliser ceci:

$this->Sender->find('all', array(
    'conditions' => array('PrivateMessagesUser.recipient_id' => 3), 
    'contain' => array('PrivateMessagesUser') 
)); 

Encore une fois, cela ne fonctionnera que si un gâteau exécute REJOIGNEZ pour les paramètres maîtrisables et utilise les bonnes conditions.

3. Utiliser les jointures

Cette méthode est à toute épreuve, mais un peu désordonné car il est hautement personnalisable.

$this->Sender->find('all', array(
    'joins' => array(
     array(
      'table' => 'private_messages_users', 
      'alias' => 'PrivateMessagesUser', 
      'type' => 'inner', 
      'conditions' => array(
       'PrivateMessagesUser.sender_id = Sender.id', 
       'PrivateMessagesUser.recipient_id' => 3 
      ) 
     ) 
    ) 
)); 

Mon dernier conseil pour vous est de placer ce code dans le modèle. Suivez le principe des "gros modèles, contrôleurs maigres" autant que possible.

Dans le modèle Sender:

function fetchByRecipientId($recipientId) { 
    ... 
} 

Bonne chance!


EDIT: Pour faire ce travail pour la pagination, suivez les méthodes ci-dessus, mais utilisez le format suivant:

$this->paginate = array(
    'PrivateMessagesUser' => array(
     'conditions' => array('PrivateMessagesUser.recipient_id' => 3), 
     'contain' => array('Sender'), 
     // 'order' => ... other keys if you wish 
    ) 
); 
$this->set('senders', $this->paginate()); 
+0

Merci! Je vais essayer de suivre votre dernier conseil. Cependant, en ce qui concerne mon problème, il semble que les méthodes que vous avez fournies ne fonctionneront pas ... J'appelle paginate() (find(), quel que soit) du PrivateMessagesController. Là où j'ai besoin d'afficher la boîte de réception d'un utilisateur et donc besoin d'aller chercher tous les messages reçus avec l'expéditeur. Et le problème est qu'à l'intérieur de ce paginate(), je ne peux pas utiliser le modèle 'PrivateMessagesUser' dans les conditions, car il génère une erreur" Champ introuvable dans la condition ". Toute autre suggestion pour traiter ce problème particulier? – linkyndy

+0

J'ai modifié ma réponse pour ajouter les instructions de pagination. J'espère que cela pourra aider. – RabidFire

+0

Malheureusement, cela ne fonctionne pas. Pire, il sélectionne tous les messages avec tous leurs expéditeurs et destinataires ... (et j'ai ajouté la condition pour ne sélectionner que certains messages privés). La méthode que j'ai utilisée obtient tous les messages reçus, avec leur bon destinataire (c'est-à-dire, l'utilisateur actuel). Le problème est qu'il sélectionne tous les expéditeurs de ce message, avec l'association PrivateMessagesUser, même si le destinataire_id de l'association n'est pas l'utilisateur actuel. Mon choix était d'aller "vers le bas" les associations et de sélectionner seulement l'expéditeur qui a le bon destinataire_id. – linkyndy

1

Vous pouvez mettre des conditions à l'intérieur maîtrisable, comme ceci:

$this->Sender->find('all', array(
    'contain' => array(
     'PrivateMessagesUser' => array('conditions' => array('recipient_id' => 3)) 
    ) 
)); 

EDIT: Essayez de modifier votre $this->paginate comme suit:

$this->paginate = array(
     'conditions' => array(
      'PrivateMessage.id' => $this->__getUserPrivateMessagesInbox()//array of message id's 
     ), 
     'fields' => array('PrivateMessagesUser.id'), 
     'contain' => array(
      'Sender' => array(
       'fields' => array('id', 'username'), 
      ), 
      'Recipient' => array(
       'fields' => array('id', 'username'), 
       'conditions' => array('Recipient.id' => $this->Auth->user('id')) 
      ) 
     ) 
    ) 

appellent ensuite votre paginate $this->paginate($this->PrivateMessage)

+0

L'idée est que j'ai déjà une requête find() au sein de laquelle je voudrais obtenir et filtrer toutes les données associées. – linkyndy

+0

puis utilisez Set?Set :: extract ('/ Sender/PrivateMessagesUser [recipient_id = 3]', $ originalData); –

+0

Je voulais filtrer les données avant l'interogation SQL, afin de ne pas remplir la base de données avec des requêtes inutiles ... – linkyndy

Questions connexes