Code Igniter - Best Practice for views to not violate DRY - php

Trying to determine the best way to handle views in codeigniter. Right now anything I consider seems too messy.
Currently I have 3 relevent views:
1) Header
2) Content
3) footer
Every single controller has something like this. Some controllers even have this several times (different functions in the same controller):
$this->load->view('head', $data);
$this->load->view('volunteers/add_profile.php',$content_data);
$this->load->view('foot');
It seems pretty silly to have to load header and footer on EVERY single page. However, each page will have slightly different data in the header (meta tags, style sheets, loaded scripts, etc).
Is there a cleaner way for me to do this?
Thanks!

I like to create a parent controller with a method like renderPage('content_view', $data). That method can include the header, menu, footer, ... That way, all the view loading stuff is kept in the controller and I don't have to bother with header, menu or footer on every action or view. It's also flexible as your child controllers can redefine the renderPage() method to fit their purposes.
If you need to load multiple content views, you could create a renderPage() method that takes in an array of string instead of a string.

Yes - have a template view. In your controller:
$data['header'] = xxx;
$data['content'] = xxx;
$this->load->view('my_template', $data);
Then in your my_template.php view file:
$this->load->view('head', $header);
$this->load->view('volunteers/add_profile.php',$content);
$this->load->view('foot');

Either what #TheShiftExchange suggested, or, if your application allows it, you can call header and footer views from each content view (which is the only view called from the controller then).

I've created my own controller where I create MY_Controller extends CI_Controller class then in MY_Controller I use access modifier $data and $loadviewArray.
public $data = array();
public $loadviewArray = array();
after this I create function in MY_Controller
public function loadview() {
foreach ($this->loadviewArray as $key => $val) {
$this->load->view($val, $this->data);
}
}
then I create controller Admin and extends MY_Controller like this Admin extends MY_Controller in Admin controller create function index.
public function index() {
$this->data["page_title"] = "Login";
$this->data["records"] = $data; // You can pass data
$this->loadviewArray = array("admin/header", "admin/login", "admin/footer");
$this->loadview();
}
In $data access modifier array I pass data at views and in $loadviewArray load views then call a function for loading views you can do like this also its very helpful for me now. And create header and footer views seperate...

please check https://github.com/alzalabany/codeigniter-base-controller/tree/master
So you can always use a templating lib. yet i dont like them for some reason !
codeigniter allow you to extend its core; if you go to link mentioned above u can see a small example
in this example every controller that will extend MY_controller will start with these defauls
protected $body='base/body',
$title='Codeigniter Z master',//txt
$js=array(),//filename
$inline_js='',//script
$css=array(),
$inline_css='',//style
$breadcrumb=FALSE,//<li><a>
$content=array(),//html
$noEcho = FALSE;
so if u chose to change them in MY_controller its effect will be default, otherwise use $this->title = 'Codeigniter - welcome page'; in ur controller constructor for example;
loading assist is a very easy job just call $this->_assets() and location of asset (edit MY_controller.php default location to you assets folder); if its an inline_js/css just call
$this->_assets('alert("hi");','js');
if you want to load a view into a page section use $this->outv(view_path,view_data,section_name);
and if you want to just load html into a variable u can use
$this->out('Footer','footer');
at end just call ->_flush();
some other options i use like
$noEcho ; if set it will clear all buffer to remove any echo's before it send your view content to browser;
you can also set functions like log-out or log-in inside MY_controller and it will be accessible by any of ur controllers http://localhost/ci/welcome/logout
any way :) i hope that answers your question !

Related

CodeIgniter - Attach functions to View to be called on all pages

I'm currently working on a e-commerce using codeigniter. I'm done with almost all the views and I am starting the coding (controllers and models) now.
For the login, my ideia is set its form on the "top view".
The problem is that I have to call the "top view" in every controller and configure the form_validation everytime I call it.
There is a proper way to dealing with it?
There are a lot of different ways to solve the problem of how to handle commonly recurring html snippets that load on many different pages.
One solution is to add a helper function to each controller like the render_page() function shown below. [NOTE: Any dynamic data that is needed in any of the views to be loaded should be passed via the $data argument.]
protected function render_page($main_view, $data=null){
$this->load->view('top_view', $data);
$this->load->view('menu_view');
if(isset($main_view)){
$this->load->view($main_view);
}
$this->load->view('footer_view');
}
Elsewhere in the same controller
public function index(){
//do stuff including setting $data as needed
$this->render_page('some_view', $data);
}
The problem with this approach is that you need to define render_page() in every controller. To get around this, use the render_page() idea in a custom library (class) that works in a similar fashion. You then autoload that library and use its render_page() method in any controller you want.
If you made such a library and named it Viewmaster then you would use it in a controller as follows (assumes it was autoloaded)
public function index(){
//do stuff including setting $data as needed
$this->viewmaster->render_page("some_view", $data);
}
I'll leave it to you to figure out the implementation details of the Viewmaster class.

How to call controller function in other php file - codigniter

First just look at my code than i will explain my problem.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Category extends CI_Controller {
function Category()
{
parent::__construct();
$this->load->model('category_model');
}
public function index()
{
}
public function _left()
{
echo "side";
$data['all_categories'] = $this->category_model->getallcategory();
$this->load->view('include/left', $data);
}
}
this is my category controller, i have a left() function in which i listed all category in the left bar of my website.
I just want to know that how can i show left() function data in another php file ?
You really shouldn't have a function you would call repeatedly or from another file in a controller... typically you would want to put them in a Helper library or as a Plugin...
For the function you have created, I am wondering if you know that you can have a view, that calls other views. For example, you have a template view that would load the header view, the view referenced in $data from your controller, and your left view, etc...
I would read more about MVC and how it's setup and how you lay out your files a bit more as it will save you a huge headache and some messy code.
Best of luck!
you call create one function and call many view from this.
or create one main view and other top,left ,right,center view and load from main view
I would consider writing a helper and autoloading it in your config file
For more information about creating helpers go here CodeIgniter: Create new helper? or check CodeIgniter's user guide.
DISCLAIMER: THIS IS A RANT
I know everyone is trying to be "helpful" but please, please, please stop using "helper" classes and "helper" files. Models get there own data, they persist their own data, in short, they do the helping!!
Ex:
DO NOT create a file called "userhelper.php", just put the methods in a file called "user.php". This is called a model. You might say at this point, "What if I need to share the model with another part of my project or just somewhere else but make it look different or something or whatever??" That's where you would use a viewmodel. The viewmodel has no persistence information in it, in fact it should be significantly different from the model enough to justify its own existence.
To wrap up, just put the CRUD into the model itself. Don't build "managers" or "helpers' or whatever the hell you want to call them.
And I don't care if CodeIgniter encourages this with it's "helper" framework. It's still WRONG and is not OOP. You will end up writing messy code and duplicating effort all over the place.

Creating a database-generated menu on every page in CodeIgniter?

I'm using CodeIgniter and have a menu on the site that needs to read a list of cities from the database. This is simple to do if it's just on one or two pages - I load the model and call a function from the controller, and pass the data into the view.
But if I want it on every page, that means I have to keep copying the same code to every single controller function and pass the data into the view. (Note, I'm using a separate "header" view that contains the menu.)
What's the best way to automatically load some data on every page load and have it available to my view?
Create a new root controller class like MY_Controller.
You can read how here: https://www.codeigniter.com/user_guide/general/core_classes.html
Then make all your controllers extend that class.
Add a function in MY_Controller like this:
function show_view_with_menu($view_name, $data) {
$menu_data = $this->menu_model->get_menu(); // load your menu data from the db
$this->load->view('header', $menu_data); // display your header by giving it the menu
$this->load->view($view_name, $data); // the actual view you wanna load
$this->load->view('footer'); // footer, if you have one
}
Whenever you normally do load a view, instead do this:
$this->show_view_with_menu('view_for_this_controller', $data);
You define your own Application_Controller, which extends CI_Controller. All of your own controllers then extend your Application_Controller rather than the CI_Controller.
In the __construct() of your Application_Controller you'll introduce the code you've been copying and pasting everywhere previously.
My solution was just to create a display class that handles these things. A simplified version:
class Display
{
public function load_pages($name, $data = array()) {
$CI =& get_instance();
// Top and header templates
$CI->load->view('header.php', $data);
// Default to loading the one template file
$CI->load->view($name, $data);
// Footer template
$CI->load->view('footer.php');
}
}
I have it doing fancier stuff, such as setting default values (page title, meta tags) and loading js/css, etc. It works just like a shortcut to having to copy/paste the regular templates that I load but also allows me to define a custom template setup if I need to, unlike if you have it do so automatically be extending your controller class.
I haven't had the need to but you can also specify different functions within this class to load different sections of the site, such as load_admin_pages() or some such. In my case I handle that just by setting a prefix parameter that gets prepended to the file paths and that's gotten what I need for my current project.

Library calls in header view - CodeIgniter

I need to call some library functions in order to correctly display some data in my header view - what is the best/correct way to approach this?
I take it I'm supposed to call this in all my controllers but it seems a bit redundant. Should I take this route? What sort of non 'hacky' method do you suggest?
Edit:
I have a view which outputs the header portion of the page. In this view I have a menu which varies depending whether you're logged in, have any favorites etc. To determine what to display in the menu, I must refer to some libraries, for example, an authentication and favorites library.
I tried calling the library from the view, but it gives me an error.
I suppose I could load the controller and pass the data to the view in every controller but I would have a lot of repetitive code. Is this the way to go?
Yes, manually assigning the same data to a partial view in every controller or method is redundant. You want to avoid this.
Any decent template library should be able to handle this for you. You can google up a solution or write your own.
Here, in mockup code, is what it may resemble:
class Template {
public $data = array();
function area($area_name)
{
$CI =& get_instance();
$data = isset($this->data[$area_name]) : $this->data[$area_name] ? NULL;
$CI->load->view('templates/'.$area_name, $data);
}
function set_data($area_name, $data)
{
$this->data[$area_name] = $data;
}
}
Then in the controller, something like this:
$this->template->set_data('header', $my_data);
Then in the view, something like this:
<header><?php echo $this->template->area('header'); ?></header>
<div><?php echo $this->template->area('content'); ?></div>
<footer><?php echo $this->template->area('footer'); ?></footer>
This is over-simplified, and there are a million ways to handle it, but I definitely suggest writing some kind of class to handle your templates rather than just using $this->load->view() for everything, even if it is just a wrapper for loading views.
To avoid manually setting that same data in every controller, use a MY_Controller, set it in the template class __construct(), or call it directly from the view file from whatever the source is (model, library, etc.). Father MVC may shed a tear, but sometimes this is easiest or even makes the most sense.
Quick example of how to use a controller extension:
// File: application/core/MY_Controller.php
class MY_Controller extends CI_Controller {
public function __construct()
{
parent::__construct();
$data['var_name'] = $this->some_lib->get_data();
$data['var_name2'] = $this->some_model->get_more_data();
$this->template->set_data('header', $data);
}
}
Then, all your controllers would extend MY_Controller rather than CI_Controller and the header data would already be loaded. This is just a simplified glimpse into another topic altogether, much much more is possible with this method.
I tried calling the library from the view, but it gives me an error.
This shouldn't happen if the library is loaded and you are calling it correctly. The syntax is $this->library_name->method().
In any case, I definitely recommend writing or borrowing some kind of Template class.
You don't have to follow the MVC model, but if you want to, the "correct" way is to call the functions in the controller, then pass the data to the view where it's printed out.
You should be able to just autoload the library or else load it in the controller before the view. Then you'll have access to the library methods in your views and can access them the same way you would in your controllers.

Pagination in PHP MVC

I've written a small MVC in PHP5 and desire a pagination module to be added to some files in my views section/folder..
I was wondering.. would the Pagination class be included in the Controller or Models section/folder?
Currently i've included it in the Models folder and called the function when needed..
The way I see it, pagination is a control, allowing user to tell your database (model), which portion of data he or she wants to see.
So I would go with the Controllers module.
Well, I think a better approach would be to make a helpers folder and then load them into your application like this :
function use_helper()
{
static $helpers = array();
foreach (func_get_args() as $helper)
{
if (in_array($helper, $helpers)) continue;
$helper_file = HELPER_PATH.DIRECTORY_SEPARATOR.$helper.'.php';
if (!file_exists($helper_file))
throw new Exception("Helper file '{$helper}' not found!");
include $helper_file;
$helpers[] = $helper;
}
}
Then all you have to do is build a pagination.php file with your Pagination class.
When you need it, you call the function
use_helper('pagination');
From here of course it depends on you Pagination class.
Hope this helps.
i guess the best approach is to call the pagination from the view, referring to this MVC
A view queries the model in order to generate an appropriate user interface
(for example the view lists the shopping cart's contents).
The view gets its own data from the model.
In some implementations, the controller may issue a general instruction to the view to render itself.
In others, the view is automatically notified by the model of changes in state (Observer) that require a screen update.
and because you will be using this class almost in every view, you should make a helper and include this class inside that helper so that all the views can share its methods

Categories