I have a variable, contaning data that should be present in the entire site. Instead of passing this data to each view of each controller, I was wondering if there is a way to make this data available for every view in the site.
Pd. Storing this data as a session variable / ci session cookie is not an option.
Thanks so much.
Create a MY_Controller.php file and save it inside the application/core folder. In it, something like:
class MY_Controller extends CI_Controller {
public $site_data;
function __construct() {
parent::__construct();
$this->site_data = array('key' => 'value');
}
}
Throughout your controllers, views, $this->site_datais now available.
Note that for this to work, all your other controllers need to extend MY_Controllerinstead of CI_Controller.
You need to extend CI_Controller to create a Base Controller:
https://www.codeigniter.com/user_guide/general/core_classes.html
core/MY_Controller.php
<?php
class MY_Controller extend CI_Controller {
public function __construct() {
parent::__construct();
//get your data
$global_data = array('some_var'=>'some_data');
//Send the data into the current view
//http://ellislab.com/codeigniter/user-guide/libraries/loader.html
$this->load->vars($global_data);
}
}
controllers/welcome.php
class Welcome extend MY_Controller {
public function index() {
$this->load->view('welcome');
}
}
views/welcome.php
var_dump($some_var);
Note: to get this vars in your functions or controllers, you can use $this->load->get_var('some_var')
Set in application/config/autoload.php
$autoload['libraries'] = array('config_loader');
Create application/libraries/Config_loader.php
defined('BASEPATH') OR exit('No direct script access allowed.');
class Config_loader
{
protected $CI;
public function __construct()
{
$this->CI =& get_instance(); //read manual: create libraries
$dataX = array(); // set here all your vars to views
$dataX['titlePage'] = 'my app title';
$dataX['urlAssets'] = base_url().'assets/';
$dataX['urlBootstrap'] = $dataX['urlAssets'].'bootstrap-3.3.5-dist/';
$this->CI->load->vars($dataX);
}
}
on your views
<title><?php echo $titlePage; ?></title>
<!-- Bootstrap core CSS -->
<link href="<?php echo $urlBootstrap; ?>css/bootstrap.min.css" rel="stylesheet">
<!-- Bootstrap theme -->
<link href="<?php echo $urlBootstrap; ?>css/bootstrap-theme.min.css" rel="stylesheet">
If this is not an Variable(value keep changing) then I would suggest to create a constant in the constant.php file under the config directory in the apps directory, if it's an variable keep changing then I would suggest to create a custom controller in the core folder (if not exist, go ahead an create folder "core") under apps folder. Need to do some changes in other controller as mentioned here :
extend your new controller with the "CI_Controller" class. Example
open-php-tag if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class LD_Controller extends CI_Controller {
}
close-php-tag
Here LD_ is my custom keyword, if you want to change you can change it in config.php file under line# 112 as shown here : $config['subclass_prefix'] = 'LD_';
and extend this class in all your controllers as "class Mynewclass extends LD_Controller..
And in LD_controller you've to write the method in which you want to define the variable/array of values & call that array in all over the application as shown here :
defining variable :
var $data = array();
Method to get values from db through the Model class:
function getbooks()
{
$books = $this->mybooks_model->getbooks(); //array of records
$this->data = array('books'=>$books);
}
to call this variable in the views : print_r($this->data['books']);); you will get all the array values... here we've to make sure atleast one "$data" parameter needs to be passed if not no problem you can define this $data param into the view as shown here :
$this->load->view('mybookstore',$data);
then it works absolutely fine,,, love to share... have a fun working friends
you can use $this->load->vars('varname', $data);[ or load data at 1st view only] onse and use in any loaded views after this
Use sessions in your controllers
$this->session->set_userdata('data');
then display them in your view
$this->session->userdata('data');
Or include a page in base view file e.g index.php
include "page.php";
then in page.php,
add $this->session->userdata('data'); to any element or div
then this will show on all your views
I read all answers, but imho the best approch is via hook:
Create hook, let's get new messages for example:
class NewMessages {
public function contact()
{
// Get CI instance CI_Base::get_instance();
$CI = &get_instance(); // <-- this is contoller in the matter of fact
$CI->load->database();
// Is there new messages?
$CI->db->where(array('new' => 1));
$r = $CI->db->count_all_results('utf_contact_requests');
$CI->load->vars(array('new_message' => $r));
}
}
Attach it to some of the flow point, for example on 'post_controller_constructor'. This way, it will be loaded every time any of your controller is instantiated.
$hook['post_controller_constructor'][] = array(
'class' => 'NewMessages',
'function' => 'contact',
'filename' => 'NewMessages.php',
'filepath' => 'hooks',
'params' => array(),
);
Now, we can access to our variable $new_message in every view or template.
As easy as that :)
You could override the view loader with a MY_loader. I use it on a legacy system to add csrf tokens to the page where some of the forms in views don't use the builtin form generator. This way you don't have to retrospectively change all your controllers to call MY_Controller from CI_Controller.
Save the below as application/core/MY_Loader.php
<?php
class MY_Loader extends CI_Loader {
/**
* View Loader
*
* Overides the core view function to add csrf token hash into every page.
*
* #author Tony Dunlop
*
* #param string $view View name
* #param array $vars An associative array of data
* to be extracted for use in the view
* #param bool $return Whether to return the view output
* or leave it to the Output class
* #return object|string
*/
public function view($view, $vars = array(), $return = FALSE)
{
$CI =& get_instance();
$vars['csrf_token'] = $CI->security->get_csrf_hash();
return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_prepare_view_vars($vars), '_ci_return' => $return));
}
}
Related
I have for example this code in my HomeController:
public function index() {
$comments = Comment::get_recent();
$top = User::get_top_uploaders()->get();
$top_something = User::get_top_something_uploaders()->get();
$data = Post::orderBy('created_at', 'DESC')->paginate(6);
return View::make('index') ->with('data', $data)
->with('comments', $comments)
->with('top', $top)
->with('top_something', $top_something);
}
It works great, but I need to make another couple of view with the same data not only for index but also for other pages like comments(), post()...
How to make this in HomeController that I don't need to make it copy and paste those variables in every controller?
Pass your data using share method:
// for single controller:
class SomeController extends BaseController {
public function __construct()
{
$data = Post::orderBy('created_at', 'DESC')->paginate(6);
View::share('data', $data);
}
}
For all controllers you can put this code in BaseController's constructor
If the data is displayed using the same HTML each time you could put that piece of HTML into a partial and then use a View Composer.
Create a view and call it whatever you want and put in your HTML for the data.
In templates that need that partial include it #include('your.partial')
In either app/routes.php or even better app/composers.php (don't forget to autoload it)
View::Composer('your.partial', function($view)
{
$data = Post::orderBy('created_at', 'DESC')->paginate(6);
$view->with('data', $data);
});
Now whenever that partial is included in one of your templates it will have access to your data
I am trying to extend the CI_Controller class to load my global page header file so I don't have to load it at the beginning of every single controller method. It doesn't seem to be working. I know the Controller extension itself works... if I remove the call of the model method from the constructor and load it from my controller method, the rest of the controller extension works fine. But when I load the model method from within the constructor of the controller extension, I get a blank page(I haven't generated the main content yet).
Any ideas?
application/core/MY_Controller.php
<?php
class MY_Controller extends CI_Controller {
var $user = array();
function __construct(){
parent::__construct();
$this->load->model('member');
if($this->session->userdata('member_id')){
$this->member->get_info($this->session->userdata('member_id'));
$this->user = $this->member->info;
$this->member->update_activity($this->session->userdata('member_id'));
} else {
$this->load->helper('cookie');
if(get_cookie('Teacher Tools Member Cookie')){
$this->member->auto_login(get_cookie('Teacher Tools Member Cookie'));
} else {
$this->user = $this->member->default_info();
}
}
$this->load->model('template');
$this->template->overall_header();
}
}
application/models/template.php
<?php
class Template extends MY_Model {
function __construct(){
parent::__construct();
}
function overall_header($title = 'Home'){
$data = array(
'BASE_URL' => base_url(),
'MAIN_NAVIGATION' => $this->main_navigation(),
'TOOLBAR' => $this->toolbar()
);
return $this->parser->parse('overall_header.tpl', $data);
}
MY_Model is an extension of the CI_Model class to load member information into $this->user.
I think response generation is done in Controller's method and all HTML pieces that you might have gets glued there. So if you are calling /controller/method_a then method_a will be responsible for returning response whereas in constructor you cannot set response.
I agree with you on setting important data in Constructor once so that you don't have to do this again and again in each method. I think you should assign output to some Controller level variable and then use that variable in your Controller's method.
I' am sure you got my point.
For this reason there is a config/autoload.php:
$autoload['model'] = array('YourModel');
Normally, extending CI_Controller lets you use the function _output for rendering html outputs.
I'm using HMVC. MX_Controller doesn't load _output function.
I've tested it and run a couple of times.
Questions:
1 - Does MX_Controller inherits CI_Controller?
2 - How can I implement _output?
It seems like codeigniter-modular-extensions-hmvc does indeed break the _output() functionality. I can't figure out how to submit the bug on bitbucket: https://bitbucket.org/wiredesignz/codeigniter-modular-extensions-hmvc
My workaround involved overriding the Output class & adding a hook to fire a custom output method. Here's what I did.
Overwrite the main Output class:
class MY_Output extends CI_Output
{
function __construct()
{
parent::__construct();
}
// Overwrite the output
public function my_output()
{
$content = $this->get_output();
// do stuff to $content here
$this->set_output($content);
$this->_display();
}
}
Then enable hooks in your config.
$config['enable_hooks'] = TRUE;
Then add this to your hooks config.
$hook['display_override'][] = array(
'class' => '',
'function' => 'custom_output',
'filename' => 'custom_output.php',
'filepath' => 'hooks'
);
Finally add the "custom_output.php" file to your hooks directory and add this.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/*
* Customize the output
*/
function custom_output()
{
$CI =& get_instance();
$CI->output->my_output();
}
If you don't need to access any class variables, you can just edit the output right in the custom_output() function and not worry about overriding the Output class.
Very hacky, but it works. :)
I do not know if the following is possible. If not other suggestions are appreciated.
In nearly all my controllers I will load some default views. For example header, footer and menu.
I would like to have certain variables auto load for each view.
If I take the header as an example. Into my header I will always load an array of $css scripts and an array of $javascript files.
$javascript[] = 'js/jquery.js';
$javascript[] = 'js/jqueryui.js';
But additionally, depending on the current page logic, I might want to add another javascript file to my $javascript variable.
$javascript[] = 'js/custom.js';
Then ideally, I would like these variables to be automatically inserted as data into the load of the view.
In other words, I just want to call:
$this->load->view('header');
How could this be achieved?
Create MY_Controller add a public array there then extend from MY_Controller
class MY_Controller extends CI_Controller {
public $data;
function __construct() {
parent::__construct();
$this->data['MYVAR'] = 'Something';
}
}
in your other controllers you just do it like this
class SomeClass extends MY_Controller {
function __construct () {
parent::__construct();
}
function index () {
$this->data['SomeOtherVar'] = 'xxx';
$this->load->view('viewname', $this->data);
}
}
You can use $this->load->vars in your Controller.
I use this in my_controller and all controllers are extend from MY_Controller
For example
<?php
class MY_Controller extends Controller{
public function __construct(){
parent::__construct();
$this->setGlobalViewVariables();
}
public function setGlobalViewVariables(){
$result = array();
$result['value1'] = 'value1';
$result['value2'] = 'value1';
$this->load->vars($result);
}
}
?>
you should create an hook for this, it is very simple
I have question to you.
I try add to my page calendar and some events in this calendar. I know how I can load calendar in page, but I didn`t now how I can load this calendar on every page automatically.
Controller:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Calendar extends CI_Controller {
function index()
{
$data = array(
3 => 'Polska - Anglia',
);
$this->load->library('calendar');
$vars['calendar'] = $this->calendar->generate('', '', $data);
$this->load->view('main/calendar', $vars);
}
}
and In view I call:
<?php echo $calendar;?>
I use CodeIgniter 2.1.3
Instead of creating controller for calendar, create a library class and then add it to autoload configuration file
class MyCalendar{
public function get()
{
$CI =& get_instance();
$data = array(
3 => 'Polska - Anglia',
);
$CI->load->library('calendar');
return $CI->calendar->generate('', '', $data);
}
}
Add this library to autoload file and then you can call it anywhere you want by using this statement.
$data['calendar'] = $this->MyCalendar->get();
You can autoload your library by changing the application/config/autoload.php file.
Find :
$autoload['libraries'] = array();
Replace by :
$autoload['libraries'] = array('calendar');
To load the same calendar on all your pages, I suggest to build a parent controller in the application/core folder.
abstract class BaseController extends CI_Controller
{
protected $data;
public function __construct()
{
parent::__construct();
$this->data = array();
$calendarData = array(
3 => 'Polska - Anglia'
);
$this->data['calendar'] = $this->calendar->generate('', '', $calendarData);
}
}
You can then extend that BaseController class on all your controllers.
class Calendar extends BaseController {
function index()
{
$this->load->view('main/calendar', $this->data);
}
}
Be sure to always use $this->data to build on the protected member of your class.
Lastly, your BaseController will not be autoloaded, you probably don't want to include it everywhere. I suggest you to add the following method at the end of your autoload or config file.
/**
* Extra autoload function. Loads core classes automatically.
* #param type $class The class to load.
*/
function __autoload($class)
{
if (strpos($class, 'CI_') !== 0)
{
if (file_exists($file = APPPATH . 'core/' . $class . EXT))
{
include $file;
}
}
}
This will allow you to autoload any classes you have in your application/core folder. This solution might seems complex, but once it's setup. You can add functionality to your BaseController that is applicable for all pages, for example, header and footer stuff.
Hope this helps!