2009-07-10 5 views
4

Je suis nouveau à MVC. Vous avez été averti ...MVC: une vue peut-elle faire une boucle sur les résultats de la requête?

J'ai un modèle utilisateur qui peut renvoyer une ressource de résultat MySQL à un contrôleur. Le contrôleur passe la ressource MySQL à la vue à afficher. Est-il acceptable d'imprimer les résultats de la requête dans la vue, en utilisant une fonction de récupération des résultats de la base de données?

<?php while($row = some_fetching_function($database_result_resource): ?> 
<tr> 
    <td><?=$row['Username']?></td> 
    ...etc 
</tr> 
<?php endwhile; ?> 

Cela ne me semble pas correct. C'est étroitement couplé, n'est-ce pas? Le modèle doit renvoyer un type de ressource de base de données et la vue doit être parcourue en boucle à l'aide d'un certain type de méthode de récupération de base de données. Est-ce que cela peut être découplé sans boucler deux fois les résultats? Je pense que vous devrez parcourir les résultats dans le modèle pour créer un tableau des résultats, puis de nouveau dans la vue.

En résumé:

  1. la vue peut afficher une ressource de résultat de base de données, tout en respectant le modèle de conception MVC?
  2. Est-il possible d'éviter de faire deux boucles dans les données, tout en évitant un couplage étroit à une base de données?

Répondre

6

Si vous abstraction de la partie base de données du code, je pense que c'est acceptable. Par exemple, vous pouvez fournir un "rowset" qui peut être itéré (implémenter une interface Iterable ou quelque chose comme ça). Dans les coulisses, cet objet peut contenir un résultat de base de données et utiliser la fonction de récupération. Fondamentalement, l'idée est que votre vue traite avec un ensemble de lignes générique qui n'implique pas qu'il provient d'une base de données ou d'une autre source, et ainsi réduire le couplage.

2

Bien sûr, il peut. Mais vous ne devriez pas aller chercher les lignes dans votre vue. Effectuez l'affectation des données de modèle dans votre contrôleur, mais pas directement dans la vue. Comme l'a souligné Hooray Im Helping, la récupération des données dépend du modèle que vous utilisez. Mais vous ne devriez pas avoir de méthodes spécifiques à la base de données ou de logique de modèle dans votre vue. Si le modèle implémente une interface Iterator générique, vous pouvez le passer directement à la vue.

<?php 
public function someControllerAction($params) 
{ 
    $myModel = Model::getModel('Model Name'); 
    // But you don't do Model::getModel('Model Name')->getResults($params['date']) in your viewa 
    $this->view->rows = $myModel->getResults($params['date']); 
} 
?> 
+1

Ceci n'évite pas l'exigence 2 dans OP. Vous pouvez faire ce qu'il demande avec un wrapper de classe qui implémente l'interface Iterator. – Martin

+0

"Effectuez la récupération dans votre contrôleur, placez-le dans un tableau et transmettez-le à votre vue." Je suis confus, Daff - le chargement ne devrait-il pas être fait dans le modèle, pas dans le contrôleur? –

+0

Hm ok ce n'était pas la meilleure façon de le décrire. Je suppose que cela dépend aussi de l'architecture. Ce que je voulais dire, c'est que l'affectation des données du modèle à la vue devrait se faire dans le contrôleur, pas dans la vue (au moins dans la plupart des frameworks PHP basés sur la requête/réponse avec lesquels j'ai travaillé). – Daff

0

Comme dit Jani, vous devriez probablement envelopper votre résultat MySQL dans une classe qui implémente l'interface Iterable de la Standard PHP Library. De cette façon, votre vue peut utiliser la construction foreach familière et générique, tout en n'ayant pas besoin d'itérer deux fois sur vos résultats juste pour la mettre dans un tableau.

SPL

 
class rswrap implements Iterator 
{ 
    var $rs; 
    var $current; 

    function __construct($rs) 
    { 
     $this->rs = $rs; 
    } 

    function rewind() 
    { 
     // do nothing 
    } 

    function next() 
    { 
     $this->current = some_fetching_function($this->rs); 
    } 

    function current() 
    { 
     return $this->current; 
    } 

    function valid() 
    { 
     return $this->current !== false; 
    } 

    function key() 
    { 
     return 0; // usually sufficient but you may want to write a real key function. 
    } 
} 

$resultset = new rswrap($database_result_resource); 

foreach($resultset as $row) 
{ 
    // your code here 
} 
0

Je pense que la meilleure façon est de faire abstraction des résultats de la requête SQL dans une liste d'objets et retourner la liste.

Je ne pense pas que l'itération d'un ensemble de lignes dissocie la vue de la connectivité de base de données spécifique que vous utilisez. La vue doit être indépendante de la connectivité de la base de données utilisée. Si vous décidez d'utiliser JDBC ou Hibernate ou quelle que soit la transition, vous ne devez pas modifier la vue.

Questions connexes