calls to model in Codeigniter Constructor... how to - php

I am developing a CRM for our agency in Codeigniter and I have a question that I can't seem to find a solid answer on. If I have a task that I do on the majority of methods in a controller, is there any way to define that action only once? For instance...
Every view call gets passed the $data variable, like so...
$this->load->view('templates/template.php', $data);
So if I am doing something like getting the admins information in every function of the controller, how can i tell it to do that action ONE time and pass it to all my functions.
Like this...
$data['admin'] = $this->Crm_model->get_admin();
I've tried putting that ^ in the constructor and it doesn't work. Any ideas?

If you do:
$data['admin'] = $this->Crm_model->get_admin();
in the constructor, $data's scope is limited to the constructor. You need to create it as a class property so it is scoped to the entire class. Do this instead
$this->data['admin'] = $this->Crm_model->get_admin();
in the constructor, and then in other methods, you can access the array by doing $this->data
Here's an example:
class Foobar extends CI_Controller {
public function __construct() {
$this->data['foo'] = "bar";
}
public function index() {
// use the class property data here to add more info to it
$this->data['hello'] = "world";
// now pass this to the view
$this->load->view('myView', $this->data);
// myView will receive both $foo and $hello
}
}

Related

CodeIgniter: Global Vars via Controller and Indirect modification of overloaded property

A problem haunting me since early days of CodeIgniter and now, with the new CI 3 i want to see if there is a more elegant way to solve it.
// file: application/core/MY_Controller.php
class MY_Controller extends CI_Controller {
public $GLO;
function __construct(){
parent::__construct();
$this->GLO['foo'] = 'bar';
$this->GLO['arr'] = array();
}
}
then, later in the code, I need to get and set the values of the $GLO variable dynamically. So for instance:
// file: application/controllers/dispatcher.php
class Dispatcher extends MY_Controller {
function __construct() {
parent::__construct();
$this->load->model('public/langs');
print_r($this->GLO);
}
}
will print array('foo'=>'bar, 'arr'=>Array()) which is correct. Also in my models I can get the values of the $GLO array in the same manner. However, as soon as I need to set any values in the $GLO array, I get the Indirect modification of overloaded property notice and so I am stuck. In my model (after executing a DB query):
// file: application/models/public/langs.php
class Langs extends CI_Model {
function __construct(){
parent::__construct();
}
function set_global_languages(){
print_r($this->GLO); // <<< prints the same values as in the controller above
$temp = array();
// [stripped db code]
$temp['label'] = $row->label;
$temp['id'] = $row->id;
$this->GLO['arr'][] = $temp; // <<< this is where the notice happens
}
Any clues of how I can use $this->GLO['foo'] = 'baz'; for setting properties of this global array in my models?
Cheers.
I stumbled upon this problem a ton of times. Since you are asking for an elegant solution - i try to give you some idea.
There is a library called Registry, which is written totally fine and can be extended any time. You can find the library here.
Put it in your libraries folder.
This library should get autoloaded so it is always available.
Add it to your config/autoload.php
$autoload['libraries'] = array(...,"Registry");
After that you should have a really easy way of storing things globally within CI - in your code for example it would look like
class MY_Controller extends CI_Controller {
function __construct()
{
parent::__construct();
$arrSomething = [
'foo' => "bar",
"arr" => array()
];
$this->registry->set("arrSomething",$arrSomething);
}
}
class Dispatcher extends MY_Controller
{
function __construct()
{
parent::__construct();
$this->load->model('public/langs');
}
}
class Langs extends CI_Model
{
function __construct(){
parent::__construct();
}
function set_global_languages()
{
$arrSomething = $this->registry->get("arrSomething");
$temp = array();
// [stripped db code]
$temp['label'] = $row->label;
$temp['id'] = $row->id;
$arrSomething['arr'][] = $temp;
//in case of an array i guess you've to reset it because there is no reference or try to call it by reference with "&"
$this->registry->set("arrSomething");
}
}
sintakonte, thanks a lot for the tip. Last night I had to rewrite a lot of code to see if and how it works. The Registry class works as expected! The only issue with this set/get method is the handling of deep arrays, especially those created dynamically and having their data pushed dynamically too. So today morning I did something very bad :) and just created this class:
class Globals {
public $data = array();
}
So now I am going from $this->GLO['foo'] to $this->globals->data['foo'] and get to keep existing syntax intact! It also enables me to reuse the class in different controllers and models under different names, once initializing it as "globals" and the other time as "admin". Seems to work alright, too!

PHP Class Reference to Parent Variable

I'm building an API service and have a parent class:
classAPI {
public responseCode = "";
public responseMessageLog ="";
function run{
// here I call my user auth class
$oUser = new classUser(...);
}
}
Inside my classUser I do a bunch of stuff and then write a bunch of variables: responseMessageLog (which is running log of where the script went) and responseCode (which is set to 0 or 1 or whatever depending on success or failure or warning).
I need to access my responseCode and responseMessageLog variables from within my User class and my parent API class, but I don't really want to be passing these variables into each child class and then passing them back. I would like it that when I update the variable in the child class it updates everywhere in all my class.... kind of like a global variable would... but I know that's not a good idea.
How have others stopped passing variables down the rabbit trail of classes.
in this class I
Passing dependencies isn't a rabbit hole you want to avoid--it makes for more testable code. However, you don't need to pass every property, you can pass the parent object.
In your case just pass the classAPI object into the constructor of the classUser and in the constructor assign it to property. The classAPI properties are public so you can access them in an instance of classUser.
ClassAPI {
public $responseCode = "";
public $responseMessageLog ="";
public function run{
// here I call my user auth class
$oUser = new ClassUser($this, ...);
}
}
ClassUser {
public $myClassApi = null;
public function __construct(ClassAPI $myClassApi) {
$this->myClassApi = $myClassApi;
}
public function someFunction() {
echo $this->myClassApi->responseCode;
}
}
Added notes:
In case it comes up in another answer, don't use static properties to do what you're trying to do.
Capitalize your class names.
In production code I might add an initialization function in ClasUser instead passing the ClassAPI directly into the constructor.

OO PHP Accessing public variable from another class

I have a class like the following:
class game {
public $db;
public $check;
public $lang;
public function __construct() {
$this->check = new check();
$this->lang = DEFAULT_LANG;
if (isset($_GET['lang']) && !$this->check->isEmpty($_GET['lang']))
$this->lang = $_GET['lang'];
}
}
As you can see I have a public variable $lang that is also defined via the contructor.
The proble is that I want to access the result of this variable from other classes that are not directly related to this class, since I don't want to redeclare it for each different class.
So for example how can I call the result of that variable from another class, lets call it class Check ?
if you mark the public $lang; as static:
public static $lang;
you can access it via game::$lang;
if not static, you need to make an instance of game and directly access it:
$game = new game;
$game->lang;
static call inside of (current) class:
self::$lang;
late static bound call (to inherited static variable):
static::$lang;
call from child class to parent:
parent::$lang;
normal call inside of an instance (instance is when you use new Obj();):
$this->lang;
BTW:
variables defined by define('DEFAULT_LANG', 'en_EN'); are GLOBAL scope, mean, can access everywhere!
<?php
define('TEST', 'xxx');
class game {
public function __construct() {
echo TEST;
}
}
//prints 'xxx'
new game;
you can make it static variable, so you will be able to call it anytime anywhere, the diff is that instead of
$this->lang;
when editing it(Works inside class game only) you do :
self::$lang;
and when you call/edit it (Works everywhere) from anther class you do :
game::$lang
the idea of static class is that its exist only in one instance, so only one $lang exist in your program. but there is no need to load the whole class to get acsess to it.
How can I call the result of that variable from another class, lets call it class Check?
A variable doesn't have a result. If you mean to retrieve the state of that variable on a specific object $obj of class game then you can simply do:
$obj->lang
On a side note if $lang is publicly only read only you should protect it by defining it private or protected and create a getter method instead.
If you mean that you want to use the same variable name in another class I'd suggest you to consider inheritance:
class Check extends game { /* now Check has $lang */ }
but the variable of the two objects will be different.
Since the property is public, you can access it from outside the class as $objInstance->property. It doesn't matter if you're calling it from a function, procedural script, in another object. As long as you have the instance, you can call it's public property. Ex:
function foo($c) {
echo $c->lang;
}
foo($check);
Also, some advice on working with objects and such: It's considered better code if you don't create instances of objects in the other objects, but rather pass them in someway (either a setter method or through the constructor). This keeps the classes loosely coupled and results in code that is more reusable and easier to test. So:
class Game
{
...
public function __construct($check, $defaultLang, $get) {
$this->check = $check;
$this->lang = $defaultLang;
if (isset($get['lang']) && !$this->check->isEmpty($get['lang']))
$this->lang = $get['lang'];
}
...
$game = new Game(new Check(), DEFAULT_LANG, $_GET);
echo $game->check;
The first half of this article is an accessible explanation of what is known as Dependency Injection.

Static variable assignment in descendent bubbles up to parent?

I've run into a problem and I'm not sure if this is just normal behaviour or if I wrote something wrong. I have a method in my base class that applies a global filter to a given class by way of creating a proxy for all new instances of that particular class. The way I planned to go about it is as follows:
Attach static $global_filter (the proxy) to the class I want to be filtered, which extends the base class object
Via my loading mechanism, return the proxy instead of the actual class upon new instantiations (which will mask method calls and apply filters accordingly)
However, I am getting stuck in step 1 and it seems that when I try to assign static $global_filter to the descendent class I want filtered, my base class object also gets the same assignment, which breaks everything else that extends from it.
Please see below for relevant code:
class object {
public static $global_filter;
public function _filterGlobal($class, $method, $callback) {
if ( !is_object($class::$global_filter) ) {
$class::$global_filter = new filterable(null);
# Replace the object being called with the new proxy.
}
var_dump($class);
var_dump($class::$global_filter); // `filterable`
var_dump(\core\blueprint\object::$global_filter); // Returns same as line above
die();
return $class::$global_filter->_add($method, $callback);
}
}
Both $class::$global_filter and \core\blueprint\object::$global_filter (the base class) are returning same instance. Whereas I expected object::$global_filter to be null.
I'm not using late static binding in order to preserve consistency (both single-object filters and global filters are called much in the same way non-statically).
This question seems relevant
Any help will be much appreciated :)
Edit, full example
This would be a concrete class, which extends model which extends object
<?php
use core\blueprint\model;
class modelMock extends model {
protected $schema = array();
public function method($test) {
return $test;
}
}
This would be another object (e.g a controller), which extends object aswell. It applies a filter to all new instances of model
<?php
use core\blueprint\object;
class objectMock extends object {
public function applyFilters() {
$this->_filterGlobal('core\blueprint\model', 'method', function($self, $chain) {
$chain->params[0] = 'new param'; // adjust the paramters
return $chain->next();
});
}
}
when I try to assign static $global_filter to the descendent class I want filtered, my base class object also gets the same assignment
Yes, indeed this happens. A static property in essence is a global variable, constrained within the class's namespace. Running into problems with global variables is often an indication you're not using the best solution.
To solve your problem, you could make the filter a (non-static) property:
$class->$filter = new Whatever();
But as always, there's more roads that lead to Rome, and I would advise you to look for alterative ways to do it.
I don't know if this is a help for you:
class a {
public static $type;
public static function setType($class, $newType) {
$class::$type = $newType;
var_dump($class::$type);
}
}
class b {
public static $type = 'myType';
}
var_dump(b::$type);
a::setType('b', 'yourType');
var_dump(a::$type);
May be you have not defined the static property to the concrete class.
Thanks everyone for you help, I spent some time on it this morning and managed to solve my problem. It's a bit of a workaround but here's how it goes:
public function _filterGlobal($class, $method, $callback) {
if ( !is_object($class::$global_filter[$class]) ) {
$class::$global_filter[$class] = new filterable(null);
# Replace the object being called with the new proxy.
}
return $class::$global_filter[$class]->_add($method, $callback);
}
So basically in order to get unique static variables working in child classes without having to explicitly define them, you can use an array that stores the child's class name as a key and then access these variables via a getter.

Accessing parent class objects & variables through $this?

I have one main class "main", which I use to store the configuration and a few objects. However, I am unable to access the objects & variables in a class which extends main, through $this.
Here is some of my main class:
<?php
class main{
// the configuration vars
public $config = array();
// the current user variables
public $uid; // contains the user ID
public $gid; // contains the group ID
// database variables
public $DB; // contains the connection
public $query_id; // contains the query ID
public $query_count; // how many queries have there been?
// cache variables
public $cache;
// start up functions
public function startup(){
// first, set up the caching
if(function_exists('memcache_connect') AND $this->config['use_memcache'] == true){
// start up memcache
require_once('memcache.class.php');
$this->cache = Cache::getInstance();
}
// now, set up the DB
$this->connectToDatabase();
// now, set up the user session
$this->setUserSession();
// are we logged in? If so, update our location
if($this->uid > 0){
// update location
$this->updateUserSession();
}
}
Here is an example of another class
<?php
class user extends main{
public function viewProfile($uid){
exit($this->config['session_prefix']); // displays nothing
if($this->cache->exists('key')){ // fails
The $config value is correctly set up, and I can read it within main but not any sub class.
The $cache->exists object just results in Call to a member function exists() on a non-object.
On index.php, the classes are loaded and set up. The Main class is setup first, and the startup function is called. The configuration array is passed before startup is called.
Can anyone suggest how I can fix this?
Are you sure your array is correctly set up.
This simple test works for me:
<?
class main {
public $test = "Woot";
}
class test extends main {
public function __construct() {
echo $this->test;
}
}
$t = new test();
Just for testing purposes, add a variable $test like in my example to the class main and try to echo it in the user constructor.
I would check if your cache is really set up correctly.
Probably the error is in this if statement:
if(function_exists('memcache_connect') AND $this->config['use_memcache'] == true){
One of these two conditions isn't met, so your $cache variable won't get initialized.
you can use parent:: to referance variables in the parent class.
parent::cache->exists('key')
You can access parent class's attributes by $this->attribute, so the problem should be that you are not calling the constructor of the parent...
Like this code is perfectly working:
<?php
class foo {
public $x="aa";
}
class bar extends foo {
public function barbar()
{
echo $this->x;
}
}
$b = new bar;
$b->barbar();
?>
Though you can also access parent class properties by Parent::attr()

Categories