views:

332

answers:

4

Quick question about general MVC design principle in PHP, using CodeIgniter or Kohana (I'm actually using Kohana).

I'm new to MVC and don't want to get this wrong... so I'm wondering if i have tables:

categories, pages, notes

I create a separate controller and view for each one...? So people can go to

/category/#
/page/#
/note/#

But then lets say I want to also be able to display multiple notes per page, it would be bad to call the note view in a loop from the page view. So should I create some kind of a function that draws notes and pass variables to that function from then note view and from a loop in the page view? Would this be the best way to go about it, if not how else should I do it...?

Thanks,

Serhiy

A: 
  1. You can loop in the View. The View is allowed can also access the model in MVC. See: http://www.phpwact.org/pattern/model_view_controller
  2. You don't need to have a controller (or model) for each table.
Thorpe Obazee
+1  A: 

Yes, instead of just passing 1 entity (category, page, note) to your view, pass a list of entities. With a loop inside the view, you can display the whole list. That view may call another one (or a function) that know how to display one entry.

Savageman
A: 

I would personally have a "show" method for one item and a "list" method for multiple. In your controller you can say something like $page_data['note'] = get_note(cat_id,page_id) for the "show" method and $page_data['notes'] = get_all_notes(cat_id) for the "list" method.

Then in your view, you loop over the $page_data['notes'] and display HTML for each one. If the list view is using the same "note" HTML as the "show" view, create a template or function to spit out the HTML given a note:

// In your "list" view
foreach($n in $page_data['notes']){
    print_note_html($n)
}

//In your "show" view
print_note_html($n)

The print_note_html function can be a helper method accessible by all views for Notes. Make sense?

Tony
A: 

In CodeIgniter I create a separate helper file where I put functions that return the markup for UI elements that may need to be included multiple times in the one view.

In your example, I would create a function to return the markup for a note.

application/helpers/view_helper.php

function note($note)
{
    return '<div class="note">' .
        '<h2>' . $note->title . '</h2>' .
        '<p>' . $note->contents . '</p></div>';
}

I would normally auto-load this helper file. And then in the view I would do something like this.

echo note($note);

For a list of notes in a view, I would iterate the list calling this function.

<div class="note-list">
<?php foreach ($notes as $note) : ?>
    <?php echo note($note); ?>
<?php endforeach; ?>
</div>

I found that including a view many times in another view was slow. Thats why I did it this way.

Edit

I just dug into the CodeIgniter Loader class and sure enough a PHP include is being done every time you call

$this->load->view('view_name');

This means that if you use this method to display a list of 20 notes, you're going to be doing 20 separate includes.

Stephen Curran
That html should be in your view.
rick
It is in the view. I've just refactored it into a function since it is used multiple times in the view. I could have placed it in its own view file but I found it ran much slower if I did that since the file was being included many times.
Stephen Curran
<?php foreach ($notes as $note) : ?> <div class="note"> <h2><?=$note->title;?></h2> <p><?=$note->contents;?></p> </div><?php endforeach; ?>
rick
:-( Are you even reading what I'm writing? My point is that I could have placed that code in a separate view file, but if I was including this file many times in a page, the code ran very slow. I found it was faster to generate the markup from a function and call that function from my view file. I don't see how this violates any MVC principle. The code is still logically in the view. Are you saying the CodeIgniter anchor function isn't part of the view?
Stephen Curran
Don't do either. Don't put that html in a seperate view file, and definitely don't return it from a function. Performance-wise, this is analogous to a database query within a loop.
rick
But, as the original poster asked, what if you want to display a note in a consistent fashion across many views? You'd have to duplicate code across these views. If you had to update the markup you'd have to update in each view. Surely it makes sense to have it in the one place. In terms of performance, I don't see how making a function call like this is analogous to performing a database query? :-S
Stephen Curran
Yes, so the entire loop should be moved to another view file. This is the kind of thing for which HMVC was designed - a modular widget with its own controller, model, and view.
rick
The only issue is that if I put the loop in the separate view that uses the widget... every time I go to render the widget (say 20 times per page), isn't it causing 20 includes of the view file, and having to render the control 20 different times? Wouldn't this breed inefficiency?
Serhiy