2009-05-11 8 views
1

Désolé pour le titre générique. Je ne suis pas le meilleur des titres.Comment puis-je faire cela sans casser le cadre MVC dans CakePHP?

Quoi qu'il en soit, la façon dont Cake fait circuler les données (comme un hachage) est à peu près la raison pour laquelle j'ai même besoin de poser cette question. Si je transmettais une variable/obj du contrôleur à la vue, c'était un objet auquel je pouvais poser des questions (ie $ duck-> quack()) plutôt que d'avoir un tableau/dictionnaire (ie $ canck [' Duck '] [' quack '] == true) ce serait facile.

Ce que j'ai dans mon application est une liste d'éléments qu'un utilisateur x peut posséder ou non. Dans certaines vues, j'affiche tous les éléments de la base de données/app (c'est-à-dire paginate) et pour chaque élément j'ai besoin de savoir si l'utilisateur connecté le possède ou non. Pour répondre à cette question, j'ai besoin de faire une requête (en raison d'une relation HABTM compliquée), ce qui est fait dans le modèle. En d'autres termes, mon modèle Item a une fonction isOwnedByUser ($ user_id, $ item_id) qui est vraie si elle appartient à l'utilisateur. Je veux appeler cette fonction à partir de la vue.

Naturellement, cela viole le cadre MVC, mais je ne sais pas comment le faire autrement. J'ai eu quatre idées:

Idée 1:

Faites ceci dans une aide:

App:Import('Model','Item'); 
$item = new Item(); 
$item->isOwnedByUser($user_id,$item_id); 

et appeler l'aide de la vue (et passer dans le item_id de $ et user_id $ bien sûr). Mais cela viole VRAIMENT le cadre MVC.

Idée 2:

Créer une action à l'intérieur item_controller.php et appellent l'action de la vue à l'aide requestAction(). Mais je heard that this was extremeley inefficent

Maintenant ces deux idées que je trouvais quand j'étais looking une solution à mon problème, mais selon eux ces deux idées sont mauvaises si je suis venu avec deux autres solutions:

Idée 3: Lorsque je renvoie les données paginées à la vue, je peux m'assurer que tous les éléments ont une clé 'user_id' afin que je puisse vérifier la clé dans la vue par rapport à l'identifiant de l'utilisateur connecté pour voir s'il possède un élément . Mais cela nécessiterait a) de réécrire la pagination b) des requêtes très laides surtout pour certains points de vue (recherche), c) une laideur et une lenteur globales. Je décide donc d'abandonner cette idée

Idée 4:

Chaque fois qu'une vue a besoin de savoir si un élément appartient à l'utilisateur, je vais juste transmettre un autre tableau du contrôleur qui contient toutes les éléments que l'utilisateur possède et dans la vue, vous pouvez simplement utiliser in_array() pour vérifier si l'utilisateur possède cet élément. Bien sûr, le problème est évident: que se passe-t-il si l'utilisateur a beaucoup d'éléments?

En bref, je suis coincé à cela et je n'ai aucune idée d'où aller et j'apprécierais toute aide! Merci!

+0

Je devrais également ajouter que la façon dont Cake gère les relations HABTM est également nulle. Vraiment nul. Mais cela n'a rien à voir avec cette question. – encee

Répondre

3

Je combinerais 3 et 4.

Dans votre action, après que vous obtenez tous les éléments paginés:

$items = $this->paginate('Item'); 

obtenir leurs cartes d'identité et moissonneuse-batteuse avec l'ID utilisateur à récupérer tous les éléments de l'utilisateur.

$itemIds = Set::extract('/Item/id', $items); 

$usersItems = $this->Item->User->find 
    (
     'all', 
     array 
     (
      'conditions' => array 
      (
       'User.id' = $userId, 
       'Item.id' => $itemIds 
      ), 
      'fields' => array('User.id', 'Item.id') 
     ) 
); 

Maintenant, vous pouvez définir les usersItems de $ dans un format que vous préférez et définir les deux que et articles $ pour la vue. Cela vous amènerait à votre option 4 et in_array(), sauf que ce serait probablement Set :: extract() ou Set :: check().

Quelque chose comme ça devrait le faire:

if (Set::extract(sprintf('/Item[id=%s]', $itemId), $usersItems)) 
{ 
    // user has the item 
} 

(j'ai écrit ceci de ma mémoire alors ... vous savez quoi faire si elle échoue :))

Edit:

Alternativement, vous pouvez faire quelque chose comme ceci (il devrait être plus rapide que ce qui précède, assurez-vous juste de déplacer Set::extract() hors de la boucle):

$usersItemIds = Set::extract('/Item/id', $usersItems); 

if (in_array($itemId, $usersItemIds)) 
{ 
    // user has the item 
} 
+0

Désolé, il m'a fallu près d'une journée pour répondre, mais cela fonctionne très bien! Je ne connaissais absolument pas l'utilitaire Set et maintenant je peux refactoriser un gros tas de code qui a été écrit de manière inefficace! Merci encore! – encee

+0

Pas de problème! Set Class est l'une des meilleures choses dans le gâteau, et en quelque sorte inconnu du grand public. Alors, passez le mot! :) –

0

Je sais que c'est une vieille question, mais il semble que peut-être le composant ACL serait une bonne option ici.

Questions connexes