Welcome Guest, Not a member yet? Register   Sign In
Assigning View data before calling the view
#1

[eluser]philpem[/eluser]
Hi guys,
I'm doing some work on an application that has a navigation bar and menu along the top of each page, and a version number string on the bottom. All of these should be dynamic -- i.e. on the "Manufacturers" page, you get "List Mfgrs / Add New Mfgr / Search Mfgrs" as a submenu, the "Manufacturers" menu item is highlighted in the main menu, etc.

This is all view-related code, and I have a pretty good idea how to do it -- pass the current menu and submenu name into the view from the controller, and use that in the view to decide which menu items to highlight.

Thing is, I don't want to have code like this:
Code:
$data = array();
$data['currentMenu'] = 'foo';
$data['currentSubMenu'] = 'bar';
// ...
// main code adds stuff to $data too
$this->load->view('dashboard', $data);

... in all of my controller functions -- it's messy. Setting the submenu I can deal with, but the menu name is going to be static for an entire controller. The version number is system-global, so I'd like to add that to either global initialisation code, or maybe the ctor for each controller (though I'd consider the latter to be a pretty messy solution).

Now with libraries like Smarty, there's an "assign" function, which assigns a value to a template variable:

Code:
$sm->assign("fred", "This is the variable fred");

Which means that I could just put a call or three to assign() in the controller class constructor and my problem would be solved fairly cleanly.

But as I understand it, there isn't an equivalent in CodeIgniter -- you always have to pass the data for each view into the $this->load->view() call. There doesn't seem to be a way to do what I want -- that is, assign a couple of variables before the load->view() call, then load the rest when load->view() is called.

The nearest I have come to a workaround is:
Code:
class GenController {
  function __construct() {
    $this->$tdata = array();
    $this->$tdata['VERSION'] = "0.01pre1";
    $this->$tdata['CURMENU'] = "GeneralStuff";
  }

  function DoSomething() {
    $this->$tdata['fred'] = "this is fred";
    $this->$tdata['jim'] = "this is jim";
    $this->load->template("page", $this->$tdata);
  }
}

Is there a better way to do this?

Thanks,
Phil.
#2

[eluser]Colin Williams[/eluser]
CI's "assign" method is $this->load->vars();
#3

[eluser]markup2go[/eluser]
Extend Controller with My_Controller and use what Colin suggests in order to use "global" data in all your controllers.
#4

[eluser]jedd[/eluser]
Hi philpem and welcome to the CI forums.

I'm not sure if this will help, but there might be something in it for you -- how I [url="/wiki/Header_and_Footer_and_Menu_on_every_page_-_jedd/"]repeat common view partials[/url] across multiple controllers.
#5

[eluser]markup2go[/eluser]
Thanks jedd, that's actually how I learned how to do this so I'm sure your link is helpful Wink
#6

[eluser]philpem[/eluser]
[quote author="markup2go" date="1255761481"]Extend Controller with My_Controller and use what Colin suggests in order to use "global" data in all your controllers.[/quote]

I've already extended Controller as MY_Controller -- my app has a username/password authentication engine that's implemented as a controller, then all the other controllers (except the login form) extend that.

[quote author="jedd" date="1255761861"]Hi philpem and welcome to the CI forums.

I'm not sure if this will help, but there might be something in it for you -- how I [url="/wiki/Header_and_Footer_and_Menu_on_every_page_-_jedd/"]repeat common view partials[/url] across multiple controllers.[/quote]

First, thanks for the warm welcome. I've had a quick look at that link -- at this point I think I might do something similar for the menu implementation (I'm slowly redoing the table-based layout in CSS, so a fully-dynamic menu would be useful) but keep my current template layout (a template view for each function, which then call the "_header" and "_footer" views). The only thing I need to check is if variables propagate down through the View "tree".. i.e.:

Code:
// views/_header.php
<?=$pagetitle?>

// views/foo.php
<?php $this->load->view('_header', array("pagetitle" => "Page Title")); ?>

// controllers/foo.php
$this->load->vars(array('foo'=>'bar', 'bar'=>'baz'));

To put it another way: does _header.php see $foo, $bar and $pagetitle, or just $pagetitle?

Hmm.

Thanks for the help, guys!
#7

[eluser]jedd[/eluser]
No - views called within views need their data to be wrapped up in an array, much like the first view.

You could do that at the top level, where you call the primary view, by having the sub-view array contents within arrays themselves, and then wrapped in your conventional $data that gets sent to the top view.

Or you could re-create the sub-view's $data requirements in the primary view, and send that through.

(In either of those cases you're possibly going to be duplicating variables, or duplicating code to generate arrays.)

Or you could use load->vars() (See the Loader class for more information). You'll note Colin suggested this very early on. I don't use this function, but a lot of people are very happy with this approach, and I can see the appeal once you start nesting views.

Or you could change your views to be flatter - ie. not use any sub-view calls.
#8

[eluser]wiredesignz[/eluser]
Any data sent to the primary view is available to all sub-views without wrapping in an array at all.

CodeIgniter uses the same mechanism that $this->load->vars() uses to cache all view data and make it global to primary and sub-views.

Do NOT ever use a view to make data transformations as part of your application logic.
#9

[eluser]jedd[/eluser]
[quote author="wiredesignz" date="1255846737"]Any data sent to the primary view is available to all sub-views without wrapping in an array at all.[/quote]

Hey, you're right. My mistake.

I'm sure this has cropped up before (a few dozen times) and the conclusion was that sub-views needed the load vars function call first.

Having never used a view-within-a-view approach before, it wasn't something I'd bothered testing.
#10

[eluser]philpem[/eluser]
[quote author="jedd" date="1255890780"][quote author="wiredesignz" date="1255846737"]Any data sent to the primary view is available to all sub-views without wrapping in an array at all.[/quote]

Hey, you're right. My mistake.

I'm sure this has cropped up before (a few dozen times) and the conclusion was that sub-views needed the load vars function call first.

Having never used a view-within-a-view approach before, it wasn't something I'd bothered testing.[/quote]

I've been using a view-within-a-view approach (or some variant thereof) since I discovered the Smarty template engine about 4 years ago. I'm not using Smarty with CI (seems too much trouble for too little gain) but it's nice to know that the same tricks work on CI.

Thanks guys. This has got to be one of the most productive product support forums I've ever seen... Smile




Theme © iAndrew 2016 - Forum software by © MyBB