codeigniter $this->load->vars between controllers - php

hi found free source code based in codeigniter,
i have a controller in codeigniter some code is this:
class front extends main
{
function __construct()
{
parent::__construct();
$this->load_main_vars();
}
private function load_main_vars()
{
$vars['title'] = $this->option->get('title');
$vars['keywords'] = $this->option->get('keywords');
$vars['description'] = $this->option->get('description');
$this->db->order_by('category_name', 'ASC');
$this->db->where('category_active', 1);
$vars['categories'] = $this->db->get_where('categories', array('category_state' => 1))->result();
$this->load->vars($vars);
}
}
then i have another controller that extends front(code above):
class Site extends front
{
function __construct()
{
parent::__construct();
}
function index()
{
$vars['site'] = $this;
$this->view('site/index', $vars);
}
}
my question is why i have to use this $vars['site'] = $this; in Site controller to use vars array added in front controller and pass to view,
thanks

I don't think your code would work in CI at all and I'm going to only answer your question
A controller can't extend another controller,CI does not allow it, instead you need to create a My_controller.php in your application/core directory,add nessecary codes there and extend that class in your controller,now for start I'm going to give you an example based on your code
application/core/My_controller.php
class Main extends CI_controller {
// methods and vars....
}
class Front extends Main {
function __construct() {
parent::__construct();
$this->load_main_vars();
}
function load_main_vars() {
$vars = [];
//assigning some vars to $vars
$this->load->vars($vars);
}
}
so now you can create your controller:
application/controllers/Site.php
class Site extends Front {
function __construct() {
parent::__construct();
}
function index() {
$this->view('site/index'); // now all vars are accesable in your view
}
}
THis is the correct way to accomplish what you want in CI

Your example is far far away from secure application.
Dedicating $this to some variable that is going to output is NOT RECOMMENDED.
In that variable is stored many private data such are database credentials
and you won't to deal with allowing view file have those.
If I should make decision I would rate that application as least safe application in CodeIgniter world. Select that source code as dangerous insecure.
Never output $this
Never output get_instance()
Read first two rules again
Instead that:
In core controller make an array that you would have approach over.
It can be top level core class so you could have that array in children classes.
class Front extends Main
{
public $data = array();
function __construct()
{
parent::__construct();
$this->data['front_vars'] = $this->load_main_vars();
}
private function load_main_vars()
{
$vars['title'] = $this->option->get('title');
$vars['keywords'] = $this->option->get('keywords');
$vars['description'] = $this->option->get('description');
$this->db->order_by('category_name', 'ASC');
$this->db->where('category_active', 1);
$vars['categories'] = $this->db->get_where('categories', array('category_state' => 1))->result();
$this->load->vars($vars);
}
}
class Site extends front
{
public function __construct()
{
parent::__construct();
}
public function index()
{
$this->view('site/index', $this->data['front_vars']);
}
}
In strict coding pay attention on capital cases of class names (and files) and on visibility of methods.

Related

Call a class method as soon as an object it extends is created

Assume we have the following class (simplified):
class SuperConfig {
public $mainDir;
public function setDir() {
$this->mainDir = "path/to/dir";
}
}
This class is supposed to be extended in EVERY other class in the project, and I do need the setDir() function of the parent to be executed. Obviously, I could do it like this:
class A extends SuperConfig() {
public function __construct() {
parent::setDir();
}
// ... other stuff is about to be done ...
}
and I could access the properties in the child class like this:
class A extends SuperConfig {
public function doSomething() {
SuperConfig::mainDir;
}
}
This is a viable solution, but I got multiple hundreds of classes and doing this in every single one seems tedious. So, is there a way to do something like this:
class SuperConfig {
public $mainDir;
public function __extend() {
$this->setDir();
}
public function setDir() {
$this->mainDir = "path/to/dir";
}
}
__extend() obviously doesn't work like that, but I'm wondering is there is a trick how I could make this work.
class SuperConfig {
public $mainDir;
public function __construct() {
$this->setDir(); // consider moving setDir's code here as well,
// unless you have a good reason for it to be a method
}
public function setDir() {
$this->mainDir = "path/to/dir";
}
}
You simply do this, and then you expect all subclasses to call the parent constructor if they're overriding the constructor:
public function __construct() {
parent::__construct();
// more code
}
It's perfectly reasonable to expect children to call their parent constructor, unless they deliberately want to leave the instance in an unknown and potentially broken state.
Put the constructor in the class that is being extended.
class SuperConfig {
public $mainDir;
public function __construct() {
$this->setDir();
}
public function setDir() {
$this->mainDir = "path/to/dir";
}
}
In any class that extends SuperConfig, if they have a constructor also, be sure to include parent::__construct(); so that setDir is called.
Read deceze's answer for an actual solution to your problem.
I would like to point out tho, that you should not extend every class in your project from a Config class. There are several ways how you could improve that.
1.) Create a static config class which you simply can call everywhere without the need of creation
class SuperConfig {
protected static $mainDir = null;
public static function setMainDir($dir) {
self::$mainDir = $dir;
}
}
2.) Create a trait rather then a parenting class.
trait SuperConfig {
protected $mainDir = null;
public function setMainDir($dir) {
$this->mainDir = $dir;
}
}
which you then can use inside your classes:
class XYZ {
use SuperConfig;
public function doSomething() {
$this->setMainDir('path/to/your/dir/');
}
}
Note that you can do that in the constructor too (which is kinda what you want).
Im not saying those two solutions are the best, but I dont like the thought of extending all classes from a config class. Just does not make much sence. Just imagine that you can only extend from one class per time, while you can use as many traits as you wish (and also have as many static classes as you need).
Well, in this particular case you just need:
class SuperConfig {
public $mainDir = "path/to/dir";
}

how to make load codeigniter database library inside a non codeigniter folder / file?

i have a folder named superfunctions
that folder is in same level with the controller, model and views folder
is it possible to call the the database library inside the php files of that said folder.
I want to use this->db->query("") etc...
on or inside
application/superfunctions/function1.php
function1.php is just pure function / not a class
The proper way to achieve your goal is to make it a helper file.
/application/helpers/function1.php
function1.php
<?php
if(!function_exists('function1'))
{
function function1()
{
// Get the CodeIgniter instance by reference
// Basically, $this from the controller is now $CI within this function
$CI = &get_instance();
$CI->db->query("");
// do whatever
return 'hi';
}
}
So whenever you need it in your controller then just do:
class Welcome extends CI_controller {
public function __construct()
{
$this->load->helper('function1');
}
public function index()
{
echo function1();
}
}
why not create a library with those functions, and autoload that library
On the other hand, you can create a class in you sub folder like
<?php
class My_super_class{
protected $CI;
public function __construct(){
parent::__construct();
$this->CI =& get_instance();
}
public function do_somthing( $param1 = NULL ){
//param1 as array
$this->CI->db->insert('table', $param1);
}
public function check_login(){
$this->CI->load->library('session');
return ( ! empty($this->CI->session->userdata('id'))) ? TRUE : FALSE;
}
}
?>

Can't extend my Controller

I am trying to write an extension to my Controller class. The problem is I can't seem to figure out how..
I have the following class named test in which there is one function which simply returns aaaa and in in the same file, at the end, as my Controller:
class test extends Controller
{
function test()
{
parent::Controller();
}
function echoMe(){
return 'aaaaaaaaaaaaaaaaa';
}
}
Within my Controller class I have a function which is the general output for a clients homepage. I'm trying to call the function echoMe from the extension above, but I keep getting
Call to undefined method Controller::echoMe()
Here is the client function (the call to echoMe() is right at the top):
function controller_client1($controlData = NULL)
{
echo $this -> echoMe();
//as the client page is content from the xml, mmodel needs the page number
$pageNumber = '';
if(isset($_GET['number']))
{
$num = htmlentities($_GET['number']);
if(ctype_digit($num) && $num >= 0)
{
$pageNumber = $num;
}
}
else{
$pageNumber = 0;
}
//loading the page content
$data = $this->model->model_loadXMLdata($pageNumber);
if(!empty($controlData))
{
//check if there is any info in the control data sent
foreach($controlData as $key => $value)
{
//add the info to the data array
$data[$key] = $value;
}
}
$this->load->load_clientHomePage($data);
}
I know this is a very simple question. I've been trying to follow this guide, but something isn't clicking...
Could somebody please help? How can I call the function echoMe() from test?
I know how to write just a brand new class and call it, but I'm trying to learn how to extend properly and keep failing.
Am I meant to call the "test" from within the Controller somewhere?
In the config.php you set the prefix for the file you want to extend. So it should be My_test, unless you have changed this preset(displayed below)
/*
|--------------------------------------------------------------------------
| Class Extension Prefix
|--------------------------------------------------------------------------
|
| This item allows you to set the filename/classname prefix when extending
| native libraries. For more information please see the user guide:
|
| http://codeigniter.com/user_guide/general/core_classes.html
| http://codeigniter.com/user_guide/general/creating_libraries.html
|
*/
$config['subclass_prefix'] = 'MY_';
Make sure you have the controller in the right folder (application/core in codeigniter 2.1.0) then you shouldn't have a problem. Hope that helps
here is my controller that i extend. The file is called My_Controller.php (creative I know)
<?php
class MY_Controller extends CI_Controller {
function __construct()
{
parent::__construct();
//constructor code here
}
//Custom functions here
}
//sencond controller I extend in the same file
class MY_Admin extends CI_Controller {
function __construct()
{
//more custom stuff for admin stuff
}
//more custom functions for admin stuff
}
?>
Has you see I have two extended controllers in the same file.
My extending code looks like this:
<?php
class home extends MY_Controller
{
and then just replace My_Controller with My_Admin if I want to extend the admin.
echoMe() function is defined in test class and not in Controller class. When controller_client1 function is called with the instance of Controller class, echoMe does not exist because it is not defined within Controller class.
The best way to achieve this is to create empty echoMe function in base Controller class. This way polymorphism works. When calling controller_client1 function from instance of test class, method from that class will be executed. Otherwise, method from base class will be executed.
I hope I didn't miss the point of the question :)
echo $this -> echoMe(); will fail because its created in the child(extended) class and your calling it in the parent class. The question is a little hard to understand.
abstract class Controller{
public function __construct(){
}
public function echoMe($str){
echo $str;
}
}
class test extends Controller{
public function __construct(){
parent::echoMe('aaaaaaaaaa');
}
}
Try this (general idea, not CodeIgniter only):
$test = new test();
echo $test->echoMe();
Remember, test extends your Controller class, not the other way round - so you can't call your methods outside the test class/object instance.
Also, it might be a good idea to upgrade to a new version of CodeIgniter - beware of the new parent controller name, though.
EDIT
Ok, this should be enought to get you started - note that it's PHP5, not PHP4, so constructors are called __construct and not the class name:
class Controller {
public $mainvar;
function __construct() {
$this->mainvar = '<br />';
}
function echoMe() {
return 'aaaaaaaaaaaaaaaaa';
}
}
class Test extends Controller {
function __construct() {
parent::__construct();
}
function echoMeAgain(){
return 'bbb';
}
}
$test = new Test();
echo $test->echoMe();
echo $test->mainvar;
echo $test->echoMeAgain();
I think the question has actually already been answered by Kosta, but there might be some misunderstanding at your side. So let me extend that by some example code:
class Controller {
public function run() {
$this->echoMe();
}
}
class test extends Controller {
public function echoMe() {
echo "works";
}
}
// This does NOT work, because Controller::echoMe does not exist
$controller = new Controller();
$controller->run();
// This DOES work, because $this will be instance of test, and
// test::echoMe exists and is callable.
$test = new Test();
$test->run();
"extends" does not mean, that the actual Controller class gets extended. The new class "test" just inherits every single method and property that is not declared "private" from the Controller class. The Controller class itself remains untouched.

Codeigniter constructor - Load database + set variables

I would like to know how I can add the following code to my codeigniter constructor:
$this->load->model('members_model');
$member = $this->session->userdata('email_address');
$viewdata['pagecontent'] = $this->members_model->get_profile($member);
The code is used throughout my controller and it seems silly to repeat it every time. When I try adding it to the constructor I am unable to reference the set variables.
This is the constructor so far:
public function __construct(){
parent::__construct();
Accesscontrol_helper::is_logged_in_super_user();
$this->load->model('members_model');
$member = $this->session->userdata('email_address');
$viewdata['pagecontent'] = $this->members_model->get_profile($member);
}
Why wouldn't the above code work? Do constructors require different code?
Constructor works, in this sense, like all other methods (and like functions), so your vars are subject to the variable scope.
Do:
class Mycontroller extends CI_Controller {
public $viewdata = array();
function __construct()
{
parent::__construct();
Accesscontrol_helper::is_logged_in_super_user();
$this->load->model('members_model');
// $this->load->library('session');
// $this->load->database();
// ^- if not already autoloaded
$member = $this->session->userdata('email_address');
$this->viewdata['pagecontent'] = $this->members_model->get_profile($member);
}
}
Then, in your other controller's methods, you just call the class property $this->viewdata, ex.
function index()
{
$this->load->view('myview',$this->viewdata);
}
And access it, in myview.php :
echo $pagecontent;
It looks like you are having some scope issues. Since the variables are declared inside of the __construct() method, that is the only method that is able to reference them. You would need to make them class variables in order to have access to them in all of your methods.
Try something like this:
class Your_class extends CI_Controller {
protected $member;
protected $viewdata;
public function __construct()
{
parent::__construct();
Accesscontrol_helper::is_logged_in_super_user();
$this->load->model('members_model');
$this->member = $this->session->userdata('email_address');
$this->viewdata['pagecontent'] = $this->members_model->get_profile($member);
}
}
Then you can reference $member and $viewdata in your other methods like this: $this->member
You may want to set this up a little differently, but hopefully you get the idea about variables and scope.

PHP MVC question

Given a Controller class and a View class, is it better for the controller to directly assign values to view properties or, is it better to assign values to properties in the controller and then copy those properties to the view when ready to display it?
Example Model Class
class Model
{
public $propertyA;
public $propertyB;
}
Example Controller class:
class Controller
{
protected $view;
protected $model;
public function __construct()
{
$this->model = new Model();
$this->view = new View();
$this->prepareData();
$this->initView();
}
protected function prepareData()
{
$this->model->propertyA = 'This is property A.';
$this->model->propertyB = 'This is property B.';
}
protected function initView()
{
$this->view->model = $this->model;
$this->view->display();
}
}
Example View class:
class View
{
public $model;
public function display()
{
echo "propertyA = $this->model->propertyA";
echo "propertyB = $this->model->propertyB";
}
}
Sorry, I was tired. I do use a model, so please reconsider your answers with this in mind.
The data should only be in one place. If not when things get complicated it is hard to sync the different places you have the data. In MVC you have a model and that is where the data should be. Pass the Model into the View and have the view display that.
Here is a simple explanation: http://en.wikipedia.org/wiki/Model%E2%80%93View%E2%80%93Controller or here for those that do not like Wikipedia: http://ootips.org/mvc-pattern.html
The model can be as simple as a class with the properties in it.
The view shouldn't be setting up variables unless they are related to the presentation. It's best to put static variables in a config file anyway.
copy those properties to the view
Rather than setting variables in the view why don't you just construct the view with a reference to the controller. That should save you from writing a lot of boiler plate code.
Class Controller() {
$this->something = 'abc';
function __construct() {
$this->display();
}
function display() {
$this->view = new View($this);
}
}
Class View() {
function View(&$controller) {
$this->controller = $controller;
print $this->controller->something;
}
}
Edit: I like Romain Hippeau's answer a lot more than my own. You should pass the model into the view.

Categories