tags:

views:

600

answers:

4

I'm new to MVC. You have been warned...

I have User model that can return a MySQL result resource to a controller. The controller passes the MySQL resource over to the view to display. Is it acceptable to print the query results in the view, using a database result fetching function?

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

That doesn't look right to me. It's tightly coupled, right? The model must return some type of database resource, and the view has to loop through it using some type of database fetching method. Can that be decoupled without looping through the results twice? I'm thinking you would have to loop through the results in the model to create an array of the results, and then again in the view.

In summary:

  1. Can the view display a database result resource, while adhering to the MVC design pattern?
  2. Is it possible to avoid looping through the data twice, while avoiding tight coupling to a database?
+5  A: 

If you abstract away the database part of the code I think it's acceptable. For example, you could provide a "rowset" which can be iterated (implement Iterable interface or something). Behind the scenes, this object could contain a database result and use the fetching function.

Basically the idea is that your view deals with a generic looking rowset which doesn't imply it's coming from a database or any other source, and that way you reduce the coupling.

Jani Hartikainen
+2  A: 

Of course it can. But you actually shouldn't fetch the rows in your view. Do the Assignment of model data in your controller, but not directly in the view. As Hooray Im Helping pointed out, the fetching of data depends on the Model you are using. But you shouldn't have any Database specific methods or model logic in your view. If model implements a generic Iterator interface you could pass it directly to the view.

<?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']);
}
?>
Daff
This does not avoid requirement number 2 in OP. You can do what he asks with a class wrapper that implements the Iterator interface.
Martin
"Do the fetching in your controller, put it into an array and pass this to your view."I'm confused, Daff - shouldn't the fetching be done in the model, not the controller?
Hooray Im Helping
Hm ok that wasn't the best way to describe it. I guess it really depends on the architecture, too. What I meant was, that the assignment of Model data to the View should happen in the Controller, not the View (at least in most of the Request/Response based PHP Frameworks I worked with).
Daff
A: 

As Jani said, you should probably wrap your MySQL result in a class which implements the Iterable interface from the Standard PHP Library. This way your view can use the familiar and generic foreach construct, while not having to iterate twice over your results just to put it into an array.

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
}
Martin
A: 

I think the best way is to abstract the results of the SQL query into a list of objects and return the list.

I dont think iterating a Row Set de-couples the view from the specific database connectivity that you are using. The view should be independent of the database connectivity thats being used. If you decide to use JDBC or hibernate or whatever the transition shouldnt require modifications to the view.

SS