Welcome Guest, Not a member yet? Register   Sign In
Nested data
#1

[eluser]emanuel.landeholm[/eluser]
Hi!

I'm an MVC newbie but I have a fair bit of experience as a programmer. I would like to hear your opinion on an MVC issue.

Thing is, I have some nested data in my model. I cannot reliably make assumptions about the structure of the data in terms number of levels etc., because that structure is implicit in a database table (row elements that have pointers to parents). Which means I cannot hardcode the structure as ie. foreach(foreach)-loops in a view.

So where do I put the code to present it? I'm reluctant to add HTML-producing code in my model but I also don't want to add a lot of complex, possibly recursive code to the view or controller.

Another thought is that I send HTML-snippets from the controller to some sort of decoration method in the model. But that means I get some HTML in the controller...

What do you think?

TIA,
Emanuel
#2

[eluser]Cro_Crx[/eluser]
You should try and have all of your HTML served from views, it's what they are there to do. Removing HTML from your models/controllers into the views should clean up your controllers/models as well so you're code will be nicer and easier to follow.

To represent your tree like structure, you'll need to pull all the data from your model as a flat structure and turn it into a tree (an array with nested elements). That way you can properly transverse the data and output it in your views.

If you just search online for transversing trees in php, and turning flat structures into trees there's plenty of code snippets. I actually had to do this for a work project recently. I created a library with a couple of functions to do this. I don't have the code with me at the moment but I can give you a rough idea of what it would look like if you'd like.
#3

[eluser]emanuel.landeholm[/eluser]
Okay, I ended up creating a treeview library. The library simply injects special symbols for nesting start/end when flattening the tree. This removed all markup from my model and made my view trivial (no ugly recursive code):

Code:
<?foreach($nested as $row):?>
<?if(is_array($row)):?>
<li>stuff: &lt;?=$row['xyz']?&gt;</li>
&lt;?else:?&gt;
&lt;?php switch($row){
    case 'nbegin':
        echo '<ul>';
        break;
    case 'nend':
        echo '</ul>';
        break;
}
?&gt;
&lt;?endif?&gt;
&lt;?endforeach?&gt;

Sometimes the solution is really simple.
#4

[eluser]emanuel.landeholm[/eluser]
I'll post the library too. It's really quite general. The only assumption is that the data has parent pointers and priorities.

Code:
&lt;?php


class treeview
{
    private $idkey;
    private $pkey;
    private $ina; // implicitly nested array (elems with parent pointers)
    private $byid;
    private $children;
    private $tv;
    private $tvbyid;

    private function _flatten($root, $level)
    {
        if(!array_key_exists($root, $this->children))
        {
            return;
        }
        
        $c = $this->children[$root];
        if(count($c) == 0) // shouldn't happen, but just to be on the safe side of things
        {
            return;
        }

        $this->tv[] = 'nbegin';

        foreach($c as $id)
        {
            $idx = $this->byid[$id];
            $this->tv[]= array( '_id' => $id, '_level' => 0, '_idx' => $idx ) + $this->ina[$idx];
          
            $this->_flatten($id, $level + 1);
        }
        
        $this->tv[] = 'nend';
    }

    private function flatten()
    {
        $this->tv = array( );
        $this->_flatten(0, 0);
        
        foreach($this->tv as $idx => $a)
        {
            $id = $a['_id'];
            $this->tvbyid[$id] = $idx;
        }
    }
    
    function make_treeview($ina, $idkey, $pkey, $prikey)
    {
        $this->ina = $ina;
        $this->idkey = $idkey;
        $this->pkey = $pkey;
        $this->prikey = $prikey;
        $this->byid = array( );
        $this->children = array( );
              
        foreach($this->ina as $idx => $row)
        {
            $id = $row[$this->idkey];
            $parent = $row[$this->pkey];
            $priority = $row[$this->prikey];
            
            if(!array_key_exists($parent, $this->children))
            {
                $this->children[$parent] = array( );
            }
            
            $this->byid[$id] = $idx;
            $this->children[$parent][$priority] = $id;
        }
        
        # this key sort arranges siblings in order of priority
        
        foreach($this->children as $parent => $clist)
        {
            ksort($this->children[$parent]);
        }
        
        $this->flatten();
        
        return $this->tv;
    }
}
?&gt;
#5

[eluser]Cro_Crx[/eluser]
Good old recursive functions.




Theme © iAndrew 2016 - Forum software by © MyBB