I am trying to initialize data in index function of controller, so that initialized data can be used in subsequent functions of controller. But the problem is data is not being displayed when I am trying to access it from other function. All of this is just to follow a sort of object oriented pattern.
Here is my code.
class Dashboard extends CI_Controller
{
private $account_data; /*Declaration*/
private $profile_data;
function __construct() {
// code...
}
function index() /*Here I am initializing data*/
{
$this->load->model('db_model');
$this->account_data = $this->db_model->get_row();
$this->profile_data = $this->db_model->get_row();
$this->load->view('user/dashboard');
}
function function account_details()
{
print_r($this->account_data); // This displays nothing
}
/*other function...*/
}
Idea is to get data once and use it for other functions and if data is updated again calls a function to initialize it.
But it is not working out. Please help me. Also suggest if I am following right approach.
Thanks for your time.
index method is not initializer, its default page/sub_method,
if you call the "*account_details*" in url as index.php/dashboard/account_details the index wont be called.
try put the code on constructor,
class Dashboard extends CI_Controller
{
private $account_data; /*Declaration*/
private $profile_data;
function __construct() { /*Here I am initializing data*/
parent::CI_Controller(); // Thank you Sven
$this->load->model('db_model');
$this->account_data = $this->db_model->get_row();
$this->profile_data = $this->db_model->get_row();
}
function index()
{
$this->load->view('user/dashboard');
}
function function account_details()
{
print_r($this->account_data); // This displays nothing
}
/*other function...*/
}
Note : don't the models or other computations on __construct() if you don't need on all methods of this controller.
create a private method like "model_initializer()" put this codes on this scope, and the call it in your other methos as $this->model_initialize(); if you need.
Thanks yo Sesama Sesame for note,
Related
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!
I have already tried lots of ways. add library, add config file, add a controller, just add in same controller.........etc.
This also have same problem:
(this is add in same controller)
<?php
class Test extends CI_Controller{
public $data = array();
public function __construct(){
parent::__construct();
//if call add_data() here, it is work
}
function add_data(){
$arraya = array('a'=>'aa', 'b'=>'bb');
$this->data = $arraya;
}
function index(){
$this->add_data();
}
function want_print(){
print_r($this->data);
}
}
?>
if I call add_data in index, i cannot get any data in want_print()....
if I call add_data in the construct, i can get data in want_print()..
Please anyone help me solve this problem?
I don't want to call it in construct because i will not call it every time...
You can set the data in your want_print() function like this:
function want_print() {
$this->index();
print_r($this->data);
}
Im using phalcon 2.0.0 and i am trying to call a function with in another function but from the same class like shown below, for some reason i get a blank page. And when i comment the calling of 2nd function from first, the page loads properly.
<?php
use Phalcon\Mvc\User\Component;
class Testhelper extends Component {
public function f1($data) {
$tmp = $this->f2($data);
return $tmp;
}
public function f2($data) {
return '5'; // just testing
}
}
And btw im accessing the f1 function by the volt function extender like this
$compiler->addFunction('customfunc', function($resolvedArgs, $exprArgs) {
return 'Testhelper ::f1('.$resolvedArgs.')';
});
if someone could help me, it would be deeply appreciated.
Thanks guys
You are trying to call TestHelper f1() statically in Volt, where your class does not expose that function as a static.
You can change your code like this:
<?php
use Phalcon\Mvc\User\Component;
class Testhelper extends Component
{
public static function f1($data)
{
$tmp = self::f2($data);
return $tmp;
}
public static function f2($data)
{
return '5'; // just testing
}
}
and your Volt function will work. However you have to bare in mind that because you are calling things statically you won't have immediate access to all the di container services that the Component offers like so:
$this->session
$this->db
You will need to modify your code to pick the di container using the getDefault()
Another option is to use the code as you have right now, but register the TestHelper in your di container like so:
$di->set(
'test_helper',
function () {
return new TestHelper();
}
);
and then your volt function will need to change to:
$compiler->addFunction(
'customfunc',
function ($resolvedArgs, $exprArgs) {
return '$this->test_helper->f1('.$resolvedArgs.')';
}
);
I have a problem, everything was working but then I tried to put my functions in my own libraries (to use them in different controllers) and it doesn't work.
I have SIGNUP controller with this:
$this->load->library('Check_functions');
// We check the form
$return_verif_form_signup = $this->check_functions->verif_form_signup($language);
which calls my librarie Check_functions:
class Check_functions {
public function verif_form_signup($language) {
if ($this->input->post()){
// Verification rules
$this->form_validation->set_rules('name', 'lang:name', 'trim|required|xss_clean');
....
if ($this->form_validation->run($this)) {
extract($_POST);
...
...
}
But I get the error:
Fatal error: Call to a member function post() on a non-object
Does anyone know how I could fix it?
thanks!
EDIT:
I have found the problem, the callback function is not called. If I replace callback_free_email by REQUIRED and I don't enter an email, my form is not submitted, so it's okay.
But if I have the following code, my form is always submitted. So the callback function is never called...
This is my code (i'm using HMVC):
class Check_functions {
private $CI;
public function __construct(){
$this->CI =& get_instance();
}
public function verif_form_signup($language) {
if ($this->CI->input->post()){
$this->CI->form_validation->set_rules('name', 'lang:field_name', 'trim|required|min_length[3]|max_length[25]|xss_clean');
$this->CI->form_validation->set_rules('email_signup', 'lang:field_email', 'callback_free_email');
...//other rules
if ($this->CI->form_validation->run($this->CI)) {
.....
}
}
}
public function free_email($str) {
return FALSE; // I have temporarly set that so I see if my function is called
}
}
I have a file called MY_Form_validation.php as suggested here: http://codeigniter.com/forums/viewthread/143057/#769347
class MY_Form_validation extends CI_Form_validation{
function run($module = '', $group = ''){
(is_object($module)) AND $this->CI = &$module;
return parent::run($group);
}
}
I really don't know what's wrong... why my callback function is not called?
Thank you for your help!
when you are writing libraries, you have to manually grab the Codeigniter instance like this
$CI =& get_instance();
then you would use $CI where you would normally use $this to interact with loaded codeigniter resources
so...
instead of
$this->input->post();
you would write
$CI->input->post();
Docs explain it here http://codeigniter.com/user_guide/general/creating_libraries.html
EXAMPLE LIBRARY STRUCTURE
class Examplelib {
// declare your CI instance class-wide private
private $CI;
public function __construct()
{
// get the CI instance and store it class wide
$this->CI =& get_instance();
}
public function lib_function()
{
// use it here
$this->CI->db->etc()
}
public function another_func()
{
// and here
$this->CI->input->post();
}
}
I finally found a workaround, instead of using the callback in my rule, I do a test later and call a verification function.
It’s works well like that.
Thanks for your help!
From a code igniter function I am loading a library with arguments and it performs a bunch of things and initiliazes the library instance.
What is the right way to pass this instance to another function?
EDIT:
public function init()
{
//...
$dataArr = array('directory' => $myDir, 'run' => TRUE);
$this->load->library('lib_mylib', $dataArr);
// here I want to pass the lib_mylib instance to final();
// lib my lib has variables that gets set when loaded, I don't want to reloaded it again in the next function because it performs some operations that should only happen once. How can I get a handle of that initiliazed library inside final?
}
public function final($inputLibMyLib)
{
}
Assuming this code is in your Controller, just load the library in the Controller's constructor...
class Example extends CI_Controller {
// load your Controller wide library here
public function __construct()
{
parent::__construct();
$dataArr = array('directory' => $myDir, 'run' => TRUE);
$this->load->library('lib_mylib', $dataArr);
}
public funciton init()
{
$this->lib_mylib->function(); // is available
}
public funciton final()
{
$this->lib_mylib->function(); // is also available
}
}
This constructor is called every time a function is requested.
CLARIFICATION
Doing this in the constructor is the best place because it guarantees that it is loaded before any following functions are.
However...
If you are calling functions sequentially the loaded library will hold over...
example
class Example extends CI_Controller {
// load your Controller wide library here
public function __construct()
{
parent::__construct()
}
public funciton init()
{
$dataArr = array('directory' => $myDir, 'run' => TRUE);
$this->load->library('lib_mylib', $dataArr);
$this->lib_mylib->function(); // is available
// call next function
$this->final();
}
public funciton final()
{
// is also available if final() is called from within init()
$this->lib_mylib->function();
}
}
Just make sure to pass the library instance by reference to your function, and it should work.