Welcome Guest, Not a member yet? Register   Sign In
array in controller not recognized in rest of class' functions?
#1

[eluser]ScottBruin[/eluser]
Hi, I'm having trouble with the following code. I load helpers, a library, and a model, as well as define a $rules array for CI's validation, and set the rules. When I load athlete/edit, I get an undefined error for the $rules array. Is there some sort of scope that I'm misunderstanding? It seems to me that everything on the constructor should carry into the methods.

Thanks for any help.

Code:
class Athlete extends Controller {

    function Athlete()
    {
        // parent::Controller();
        $this->load->helper('url');
        $this->load->helper( array('form','array','scott') );
        $this->load->library('validation');
        $this->load->model('Scott_model');
        
        // VALIDATION
        $rules['AthleteTitle'] = '';
        $rules['AthleteNameFirst'] = 'trim|required|max_length[50]';
        $rules['AthleteNameMiddle'] = 'trim|max_length[50]';
        $rules['AthleteNameLast'] = 'trim|required|max_length[50]';
        $rules['AthleteGender'] = '';
        $rules['AthleteHOFMember'] = '';
        $rules['AthleteHOFInductionDate'] = 'trim|callback__hof_check|numeric';
        $rules['AthletePhotoUCLA'] = '';
        $rules['AthletePhotoPostUCLA'] = '';
        $rules['AthleteVideoUCLA'] = '';
        $rules['AthleteVideoPostUCLA'] = '';
        $rules['AthleteStoryUCLA'] = 'trim|htmlspecialchars';
        $rules['AthleteStoryPostUCLA']  = 'trim|htmlspecialchars';
        
        $this->validation->set_rules($rules);
    }
    
    
    function edit()
    {
        $id = $this->uri->segment(4);
        
        if ($this->validation->run() == FALSE)
        {
            $data['success_string'] = '';
        }
        else
        {
            // form validates, prep for data entry, insert into db
            $input = userules_forinput($rules);     // **** LINE WITH UNDEFINED ERROR for $rules
            if ($input['AthleteHOFMember'] != -1)
            {
                $input['AthleteHOFMember'] = 0;
                $input['AthleteHOFInductionDate'] = NULL;
            }
            
            $this->db->where('AthleteID', $id);
            $this->db->update('athlete', $input);            
            $data['success_string'] = 'Form successfully submitted!';
        }
        
        if ($id == 'new')
        {
            redirect('ferdinand/athlete/newrecord/');
        }
        elseif ($id != '' && is_numeric($id) && strlen($id) == 5)
        {
            $data['row'] = $this->Scott_model->athleteinfo_results($id);
            $data['sportquery'] = $this->Scott_model->athletesport_query($id);
            $data['biosubmiturl'] = 'ferdinand/athlete/edit/' . $id;
        }
        else
        {
            redirect('ferdinand/search/results/athlete/normal/' . $id);
        }
        
        $data['sportnamearray'] = $this->Scott_model->sportnamearray();
        $data['resulturl'] = site_url('ferdinand/edit/sportjson/');
        $data['linkurl'] = site_url('ferdinand/edit/team') . '/';
        $this->load->view('athlete_edit',$data);
    }
    
    
    function newrecord()
    {
        if ($this->validation->run() == FALSE)
        {
            $data['success_string'] = '';
        }
        else
        {
            // form validates, prep for data entry, insert into db
            $input = userules_forinput($rules);            
            if ($input['AthleteHOFMember'] != -1)
            {
                $input['AthleteHOFMember'] = 0;
                $input['AthleteHOFInductionDate'] = NULL;
            }
            
            //$this->db->insert('athlete', $input);            
            $data['success_string'] = 'Form successfully submitted!';
        }
        
        $data['row'] = '';
        $data['biosubmiturl'] = 'ferdinand/athlete/newrecord';
        $this->load->view('athlete_edit',$data);
    }
}
#2

[eluser]Michael Wales[/eluser]
$rules is a class variable and the following line is referring to a local variable (a variable for that function only):
Code:
$input = userules_forinput($rules);     // **** LINE WITH UNDEFINED ERROR for $rules

Change it to:
Code:
$input = userules_forinput($this->rules);
#3

[eluser]ScottBruin[/eluser]
Thank you for your response, Michael.

I'm now getting another error from the helper function that calls $this->rules.

Here's the function:

Code:
function userules_forinput($rules)
{
    // Pass an array of CI rules to this function and it will return
    // them formatted as [formname] => [value] in an array
    
    $CI =& get_instance();
    foreach($rules as $key => $value)
    {
        $item = $CI->input->post($key,TRUE); // takes $rules array and uses its keys to get the $_POST values; "true" runs these through xss_clean
        $item = trim($item);
        $input[$key] = $item;
    }
    return $input;  // *** ERROR for this line, variable undefined
}

I won't lie, I'm not quite sure what $Ci =& get_instance() does. I saw it on this forum and it fixed my problem, but my understanding of OOP is poor.
#4

[eluser]Michael Wales[/eluser]
What's the error? On what line?
#5

[eluser]ScottBruin[/eluser]
I edited above. For the return of the variable $input. Says the variable is undefined.
#6

[eluser]Pascal Kriete[/eluser]
The variable is only defined in the scope it was initialized in. In this case that means the foreach loop.
Code:
$input = array();    //Declare it here, so that it's scope is the whole function
foreach($rules as $key => $value)
{
    $item = $CI->input->post($key,TRUE);
    $item = trim($item);
    $input[$key] = $item;
}
return $input;
#7

[eluser]ScottBruin[/eluser]
Thanks, inparo, that partially fixes the problem. Still, I don't understand why that was not a problem before I moved the definition of the $rules array and the setting of the rules to the constructor. So, I've made the two suggested changes by you and Wales, but am getting this error now: Message: Undefined property: Athlete::$rules. I think I just have a poor grasp of OOP and how CI works, so that's my struggle.

I defined the rules array in this way: $this->rules['key'] = 'value' and this seems to solve my problems after making your change and changing use of $rules to $this->rules everywhere. Is this the correct way of doing things? Is it best practice to define the array $rules and then say something like $this->rulesarray = $rules?

Thanks for any help, I'm obviously confused.
#8

[eluser]Pascal Kriete[/eluser]
Ok, I think the first thing we should clear up is the scope problem. Every variable is set in what is called a scope - most of the time it just means that it's inside curly braces.
Example:
Code:
class Something {
    $somevar = 'something';    //This is available in the entire class using $this->somevar ($this refers to the current class)

    function test() {
        $testvar = 'somethingelse';    //This is available in the test function, but not outside it.
    }

    function print() {
        $a = 1;
        if ($a == 1) {
            echo $a;    //No problem
        }

        echo $this->somevar;    //Prints 'something'
        echo $testvar;       //Not defined in this scope
    }
}
I hope that helps a bit.


So now we'll get to your class:
Code:
class Athlete extends Controller {

    /* Add this to make $rules a class variable */
    $rules = array();

    function Athlete()
    {
        // parent::Controller();
        $this->load->helper('url');
        $this->load->helper( array('form','array','scott') );
        $this->load->library('validation');
        $this->load->model('Scott_model');

        // VALIDATION

        /* Change all these to $this->rules... */
        $this->rules['AthleteTitle'] = '';
        $this->$rules['AthleteNameFirst'] = 'trim|required|max_length[50]';
        $this->$rules['AthleteNameMiddle'] = 'trim|max_length[50]';
        $this->$rules['AthleteNameLast'] = 'trim|required|max_length[50]';
        $this->$rules['AthleteGender'] = '';
        $this->$rules['AthleteHOFMember'] = '';
        $this->$rules['AthleteHOFInductionDate'] = 'trim|callback__hof_check|numeric';
        $this->$rules['AthletePhotoUCLA'] = '';
        $this->$rules['AthletePhotoPostUCLA'] = '';
        $this->$rules['AthleteVideoUCLA'] = '';
        $this->$rules['AthleteVideoPostUCLA'] = '';
        $this->$rules['AthleteStoryUCLA'] = 'trim|htmlspecialchars';
        $this->$rules['AthleteStoryPostUCLA']  = 'trim|htmlspecialchars';
        
        $this->validation->set_rules($this->$rules);
    }
    ...
    // Also change any other occurences of $rules to $this->rules...
}
OOP takes a while to get your head round, and PHP isn't really a great one to learn it with, but you'll get the hang of it.

I hope I got all that right (it's almost 3am), and I hope it helps Smile.

EDIT: Forgot this part: There is a CodeIgniter object, that most of the time you just call using $this->whatever (load, etc). That object is only defined in the views, models, controllers. To get it in your own classes you do $CI =& get_instance(). The & means that you're getting a reference (a pointer at the object) instead of copying it. And now you can use $CI as you would $this.
#9

[eluser]wiredesignz[/eluser]
Quote:There is a CodeIgniter object, that most of the time you just call using $this->whatever (load, etc). That object is only defined in the views, models, controllers. To get it in your own classes you do $CI =& get_instance(). The & means that you’re getting a reference (a pointer at the object) instead of copying it. And now you can use $CI as you would $this.

Controllers, Models and Views are part of the CI super-object and therefore can use $this to reference the CI core, libraries are not and require the use of &get;_instance() to reference the CI core.

There should be a sticky for this stuff it gets posted so often.
#10

[eluser]ScottBruin[/eluser]
Thank you inparo and wiredesignz, this helped me a ton and should be required reading for those using CI. I agree, a sticky thread or some documentation should be more readily available about how CodeIgniter operates (though I understand some of my misunderstanding was because of poor grasp of OOP principles).

This is a good article on how CI uses a super-object: http://www.packtpub.com/article/codeigniter-and-objects

Also, to close up this thread for anyone that turns to it for help in the future: I found that inparo's code is slightly flawed in that declaring the variable $rules = array(); in the class needs a declaration like "var" or "public"




Theme © iAndrew 2016 - Forum software by © MyBB