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.
Related
In my current implementation of the MVC design pattern (demonstrated using PHP and CodeIgniter):
Let's say I have a "page" located at "www.mysite.com/blue/page" that is ultimately generated by the following (greatly simplified) files:
/libraries
session_lib.php
/controllers
/red
/white
/blue
page.php
/models
/red
/white
/blue
funky_class.php
page_model.php
/views
/red
/white
/blue
page.php
And here's an easy to understand controller:
// FILE: /controllers/blue/page.php
// Get some paramaters from URL
$params = $this->input->get();
// Use a library to do some stuff with these params with a session
$this->load->library('session_lib');
$this->session_lib->store_in_session($params);
// Use a very page specific class to do some funky stuff with the params
$this->load->model('blue/funky_class');
$funkified_params = $this->funky_class->funkify($params);
// Pass params to a model
$this->load->model('blue/page_model');
$data['output_from_db'] = $this->page_model->get_some_output_from_db($funkified_params);
// Send to view
$this->load->view('blue/page', $data);
And now the question...
What is the best procedure for these "funky" little page specific classes that don't interact with the database? In this example I store the little class with the models, and in some cases might just add additional methods inside the model class to do the funky stuff. Is this good practice? Or should the library and funky class both go inside the model so the controller is even skinnier (however the model might be used in other places without the need for sessions and funkiness)?
I would use a helper.
When a helper is loaded, that function will be available in the global scope so you can call it anywhere.
They're great for small, stand-alone functions that do only one thing that is not necessarily related to code in a model or library
Helpers especially excel for me when converting things between one format or another (slugify, convert_timezone, change_query_string) or doing little tasks that you don't want to think about (force_ssl, is_image, uri_string)
funkify() seems like an appropriate helper function that may prevent a lot of repeated code.
Here's the codeigniter documentation page on them: http://ellislab.com/codeigniter/user-guide/general/helpers.html
If you're in a situation where the helper function is so specific it will be only used in one place, you can still use a helper. Name the helper after your controller, page_helper.php for example.
page_helper.php
function funkify($params) {
// do funky stuff
return $funky_params;
}
then in your controller:
class Page extends CI_Controller {
public function __construct() {
parent::__construct();
$this->load->helper('page');
}
public function page() {
// do stuff
$funky_params = funkify($params);
// do more stuff
$this->load->view('blue/page', $data);
}
I have no excuse for it, but sometimes if I am in a situation where I need a razor specific function that will only be used on one location (say, a controller) ever, I will put it right in the controller's file. You can paste a function outside of the class definition and it will act like a helper and be available globally (as long as that controller is loaded). You can also define functions inside of a view. Yucky, but possible. I don't like to do it often because it's unusual and not expected (by myself or other developers)
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.
I am trying to put this function ((click_add)) in library so that i can call it from all the controllers. I already have get_ads() function in library. I tried various ways to shift the click_add(id) function to library and call it to view along with get_ads but doesn't work. Please help
function __construct() {
parent::__construct();
$this->load->library('ads');
$this->load->model('MGlobal');
}
public function index(){
$data['banner']= $this->ads->get_ads();
$this->load->view('test',$data);
}
//i want this in library but no luck
public function click_add($ads_id){
$ads_site = $this->MGlobal->getAds($ads_id);
$this->MGlobal->add_ads_view();
redirect($ads_site['url']);
}
//and views is like this
foreach($banner as $k=>$list){
echo anchor('test/click_add/'.$list['bannerid'],'<img src="'. $list['image']. '"/>');
}
please suggest me how do i achieve that with library
It's also important to remember the role of each part of the MVC pattern. In your click_add() method, it looks like you're rendering a view and causing a redirect. These are two things best suited for a controller rather than a library. Rendering views and redirecting are two things that must be a controller's responsibility, and indeed, you won't be able to access them through the URL, which is what you're trying to do here.
If you want to reuse this method across multiple controllers in your site, try creating a MY_Controller core class and extending your controllers from that. That way, any methods you define in the MY_Controller will be available in any controller you subclass from.
Without any specific error messages or a more verbose description of the problem you're having, I'm afraid there's little more help I can give you.
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.
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