• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
code duplication advice

#1
[eluser]winter[/eluser]
Hi everyone,

I hope you're having a great day.

I have probably a simple question for you all. I'm not PHP or CI veteran. So I thought I'd ask what you have done in this case.

There are many times when I'd like to use the same data and not have to do so. For example, I have a footer that shows the app version and release date. That data is pulled from the db. Now I could call the model function and set the array that is sent each time I load the footer view. However, it would be nicer to just maybe have it set once per controller. Or even just every time I load the footer.

OK now take a moment to laugh. Then if your feeling like you could spare a few moments, I would appreciate any suggestions to the above and similar things that I would/will/do encounter making apps with CI/PHP.

Thanks all! Take it easy!

#2
[eluser]jedd[/eluser]
Hi Winter,

This is a pretty common thing - and there's a few ways of doing it. I'm an advocate of the [url="http://ellislab.com/codeigniter/user-guide/general/core_classes.html"]extending the core controller approach[/url].

So, for example, in my file application/libraries/MY_Controller.php, within the constructor of same, I have a bunch of stuff - but this snippet is instructive:

Code:
$tmp_data['menu_data'] = $this->_generate_menu_data();
$this->data['main_menu_view'] = $this->load->view ('common/create_table_main_menu', $tmp_data, TRUE);


Elsewhere in the MY_Controller I have my _generate_menu_data() function that pretty much just returns one very big array( ... )

Anyway, the outcome of this is that every controller I have (which all extend MY_Controller rather than just Controller) now has $this->data['main_menu_view'] available - and they can also happily ignore it! (Because $this->data is the construct that I send to my view.) My view file is pretty sparse - it contains mostly echos of $data[] items in fact, wrapped in div's.

So for example, here's a section from my application/views/default.php (which delivers 99% of my pages):

Code:
<div id="div_navigation_menu">
     &lt;?php echo $main_menu_view; ?&gt;
</div>


Is this the kind of thing you were wondering about?

Database calls are slightly more complex, I gather, from the MY_Controller location - but not insurmountable. There are a a few ways, as I say, of providing this kind of 'everywhere' functionality.

#3
[eluser]wiredesignz[/eluser]
You could look at using the Widget plugin.
http://ellislab.com/forums/viewthread/109584/

#4
[eluser]winter[/eluser]
Jedd,

That looks very interesting. I think I can do a lot more with CI now that you've shown me that page. That's just great!

So basically in your constructor you are making a call to a member function which returns some data that is assigned to a member variable which is then available to *any* controller - because we extended the controller class.

Does that sound about correct?

Also, I noticed that you are generating the view and storing it in memory rather than displaying it. I think I used this method to generate an html email. Are there any benefits to working with views in this way?

wiredesignz,

I will have to look at that plugin some time as well. I didn't really understand what it is for. Being green, that's a given. Will read more.

#5
[eluser]jedd[/eluser]
Hi Winter,

Quote:So basically in your constructor you are making a call to a member function which returns some data that is assigned to a member variable which is then available to *any* controller - because we extended the controller class.

Does that sound about correct?

Yes. And because in this case it's part of the $data array that gets shoved off to the view(s) later, the actual controller where I'm doing page-specific stuff doesn't have to refer to, or be aware of, that array element.

Note that there are several ways of doing this, and you should remain open to others. Entries in the config file, for example, are good for (I think) shorter data. Anything non-algorithm-generated are good candidates, too, for a config file entry. Anything that won't be used on pretty much all your pages should have a bit more logic wrapped around it.

Quote:Also, I noticed that you are generating the view and storing it in memory rather than displaying it. I think I used this method to generate an html email. Are there any benefits to working with views in this way?

I get confused by hierarchical views. Or rather, views that call other views. It throws me, it's hard to track, it's easy to break when making changes.

So all my views get generated by the controller, with component views (or 'sub-views' if you prefer) getting treated thus, and then fed into my one, very lightweight (30 lines or so) default view.

Also, of course, in this particular instance there's not many ways around it. The MY_controller function could just generate the array, but then I'd have code duplicated in all of my real controllers where I had to process that data and turn it into a view.

#6
[eluser]jwindhorst[/eluser]
I chose a slightly different approach that work better or worse for you depending on your style. In my view instead of calling
Code:
$this->load->view('viewname');

I call:
Code:
$header_data=array( 'page_title'=>"Title of my page", 'footer_info'=>"Info for footer");
$views=array('generic/dashboard'=>$data);
load_view_with_templates($views, $header_data);

and the function of course looks like this:
Code:
function load_view_with_templates($views, $header_data=array())
{
  $CI =& get_instance();
  $CI->load->view('header',$header_data);
  foreach($views AS $v=>$d)
  {
    $CI->load->view($v, $d);
  }
  $CI->load->view('/footer');
}

The function lives in a helper file that is pre-loaded from the config.

It's has worked out pretty well for me so far.

#7
[eluser]winter[/eluser]
My apps so far have been pretty basic and doing views like this has not been a hassle:

Code:
$this->load->view('header', $data);
$this->load->view('specific_view', $data);
$this->load->view('footer', $data);

I just change the specific_view depending on what I'm showing to the user. Sometimes there are a couple specific view in and then my footer. It usually sits at the end of a controller function. Perhaps that's a bit too simple for some apps. But it's worked fine for me so far.

I'm also interested in what obiron2 says here:
http://ellislab.com/forums/viewthread/106749/

Sounds cool.

#8
[eluser]rootman[/eluser]
I just hit a quite similar problem. I have some variables that have to be availiable in every view. For example $logged_in, $user_name, ...

I looked at the different approaches, I extended the Controller and i got a method collecting all the relevant data and passing it in $this->data like suggested. But now i gotta go through all of my code changing the view calls to
Code:
$this->load->view('myview', $this->data);
and i have to change all my other $data arrays to add to $this->data. Well guess what, i don't really like to do so because I think there has to be a way to make these variables availiable in every view.
Just a way to tell the output class (or whatever class handles the views) that it can use this set of vars.

Is there no simple way by using a hook or calling a function like: $this->output_class->set_global_vars($data)

anything like this?!

greetz
tim

#9
[eluser]jwindhorst[/eluser]
rootman

Unless I'm missing something those variables might better serve your purpose if you stored them in the session. Personally I usually store the entire User object in the session. *yes I know many of you will disagree with storing objects in sessions -- I did say it was a personal preference*.

Hope that helps, If I missed something about your situation feel free to clarify.

#10
[eluser]rootman[/eluser]
Some of the data is already stored in the session, but i got to get it out of the session into the view and i'd like to automate it. I just want a way to pass a set of variables into the view without doing it in every controller.


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2021 MyBB Group.