Welcome Guest, Not a member yet? Register   Sign In
Coding approach question: how to (easily) build a navigation.
#1

[eluser]Bramme[/eluser]
Hey all,

First of all, I just started using CodeIgniter (I downloaded it like an hour ago or so :p), so I want to apologize if I'm asking smth really stupid, or smth that has been answered a million times allready. I just don't know how to search for an answer.

I'm trying to port a website I made with Smarty to CI. The website is a very easy portfolio with only a few (more or less) static pages: home, contact, about, paintings, drawings, portraits, guestbook.

At the moment I'm using 5 separate tpl files: one for each page, except for the paintings/portraits/drawings pages, since they do exactly the same (display a gallery, only the folder used to draw images from is different). I was planning on writing 5 controllers: one for each tpl file etc etc.

But I've hit a little snag: With Smarty, the links for the navigation are stored in an array which I loop through to create the nav
Code:
// $pages = array( 'controller' => 'to be displayed in nav', etc, etc)
// $page = $_GET['page'];
<ul>
&lt;?php foreach($pages as $c => $p): ?&gt;
<li><a href="&lt;?=$c?&gt;"&lt;?php if($c == $page) echo ' id="active"'; ?&gt;>&lt;?=$p?&gt;</a></li>
&lt;?php endforeach; ?&gt;
</ul>

Now I realise that for a simple navigation as this, I could just as easily hardcode the links in my view_navigation.php file and leave it at that, but what if I have to dynamically generate that array from, say, a database? My navigation stays the same for the entire site. It seems so silly then to copy paste the build array code in every controller. And what seems even more stupid is that, if I change one line for it, I have to copy paste it in every controller again.

So basically, what I needed to know was: is there a way to execute a certain piece of code for every controller, so that that piece of code can pass along the $pages array, so I can pass the $pages array to my view...

Which leads me to a second question I just thought off: I have to load 3 view for every controller: header, a variable one and footer. Is there a way to automatically load the footer and header view? Purely for the sake of reducing lines of code?

And a third question: how do I check what page I'm currently on? So I can display the proper active state in my menu?
#2

[eluser]Jay Turley[/eluser]
[quote author="Bramme" date="1212026451"]
So basically, what I needed to know was: is there a way to execute a certain piece of code for every controller, so that that piece of code can pass along the $pages array, so I can pass the $pages array to my view...

Which leads me to a second question I just thought off: I have to load 3 view for every controller: header, a variable one and footer. Is there a way to automatically load the footer and header view? Purely for the sake of reducing lines of code?

And a third question: how do I check what page I'm currently on? So I can display the proper active state in my menu?[/quote]

Okay, first of all, in the user guide, you can read about multiple views (CI views). This should allow you to "chain" a bunch of views together - with one of them being the menu.

Second, if you are going to just use a "page" controller, look at the example code in the views section of the user guide. You could use separate functions in the controller or IMHNO (in my humble n00b opinion) you could use the uri segment. So for example for the url:

http://foo.com/index.php/page/about

you could either have separate functions in the controller:

Code:
&lt;?php

class Page extends Controller {

   function index()
   {
      // do stuff
   }

   function home()
   {
      // do home page stuff
      $data['page_name'] = 'home';
      $this->load->view('menu', $data);
      $this->load->view('page', $data);
   }

   function about()
   {
      // do about stuff
      $data['page_name'] = 'about';
      $this->load->view('menu', $data);
      $this->load->view('page', $data);
   }

}
?&gt;

or you could access the uri segment and pass that to the menu and page views:

Code:
&lt;?php

class Page extends Controller {

   function index()
   {
      // do stuff
      // get the segment after /page - return 0 if doesn't exist
      $page_name = $this->uri->segment(2, 0);
      $data['page_name'] = $page_name;
      $this->load->view('menu', $data);
      $this->load->view('page', $data);
   }

}
?&gt;

Once again, I am not a CI expert, but this seems like the correct approach. Caveat Emptor. I wrote this code without testing it. Etc.

Best of luck; I love CI.
#3

[eluser]Bramme[/eluser]
Thanks for the answer. I knew about the multiple views, I've been over the user guide (some parts rather quickly). I just wondered if there could be an autoload function for views, like there is for helpers etc.

If I get this right, you're suggesting I'd only use one controller. So let me check if I get this right:
one controller, uri's look like foo.com/page/blah where page is the controller and blah the function. I guess I could rewrite the .htaccess a little so /pages/ is omitted, seeing as it would be a little silly. actually, is there a way to use only one controller? Oh wait, don't answer, I should check out routing for that, no?

Could something like this work:
Code:
class Page extends Controller {

    function __construct (){
        parent::Controller();
        $pages = array();
        $this->load->view('navigation', $pages);
    }

    function home (){
        //get data for home
        $this->load->view('home', $data);
    }

    function contact(){
        //get data for contact
        $this->load->view('contact', $data);
    }

    function home (){
        //get data for about
        $this->load->view('about', $data);
    }
    ....
}
I guess I should just try it out... This way, I only have to load the navigation view once. And only process the $pages array for it once.

Hmm, things are starting to clear up! Thank you for your advice!

If i'm getting this right: you should only use one controller for simple websites. But could somebody give me an example when you should use multiple controllers?
#4

[eluser]gtech[/eluser]
there are two ways you could do this..

1) create a library.. what you could do is autoload you new library so its available in every controller and create a template function in the library.. In this template function you can get the CI instance and make a call to the model, load a header then load the view passed in as a parameter and then load the page footer.

[url="http://ellislab.com/forums/viewthread/80071/"]There is an example here[/url]

the link shows you an example library there is no call to a model, but that can be easily added using the CI instance

Code:
...
        // extended from example link above
        $CI =& get_instance();
        $CI->load->model('modelname');
        $data = $CI->modelname->function();
        $CI->load->view('header',$data);
...

What you do is instead of calling $this->load->view you call the template function in the library.

2) There is another way, that is to create a base controller with the functionality that would be in the template. Then when you create your controllers rather than extending from the controller class like we normally do you extend from your base class.. then all the functions in the base class will be available in your new class.
#5

[eluser]Bramme[/eluser]
I've created a simple model which I set to autoload:
Code:
class Pagemodel extends Model {
    var $data = null;
    
    function showViews($display = 'home', $data = null) {
        $this->data['pages'] = array('...........');
        $this->load->view('header', $this->data);
        $this->load->view($display, $this->data);
        $this->load->view('footer');
    }
}

What would be the difference if I used a library? Or what's wrong about using a model, other than it's supposed to interact with my database? I might as well use it as a means to send e-mail, no?




Theme © iAndrew 2016 - Forum software by © MyBB