Welcome Guest, Not a member yet? Register   Sign In
Can I use a global inset/update function
#1

[eluser]simplepixie[/eluser]
I am trying to keep my code as clean as possible rather than having to repeat the following code throughout each insert and update function in all my models, I wonder if I can use it globally (I have tried various ways but can't seem to get it to work unless it is used in the actual add/update function).

Code:
function insert_udpate()
    {
        $keys = array_keys($_POST);

        foreach($keys as $key) {
            if(in_array($key,$this->mainfields)) {
                $data[$key] = $this->input->post($key,TRUE);
            }
        }
    }

The var $mainfields is set in the model and works fine when calling the foreach loop from within the model's insert and update functions but I don't want to have to keep repeating the same code through all models (have tried putting in My-Model and extending but still doesn't seem to work) - can this be called from one function and if so how?

I tried calling it like this so maybe this is where I have gone wrong:

Code:
$this->db->update('table_name', insert_update(), array('id' => $id));
#2

[eluser]richthegeek[/eluser]
You can do this but there are potentially security implications - you'd be wise to at least add a blacklist (better yet, a whitelist) of fields that are protected/writeable, so that user's cannot write any field at will.

The best option for something like this is to provide it as a parent model (MY_model) method and call it within a per-model insert_update class that vets the data.

Code:
class user extends MY_model
{
    ...
    function create()
    {
         // some whitelist/blacklist logic so that only valid fields are written to

         $this->db->insert( "users", $this->insert_update() );
    }
}

If you don't apply some sort of validation then you are leaving yourself open to major flaws even with XSS filtering.
#3

[eluser]simplepixie[/eluser]
I still can't get this working (I already had the function insert_update in MY_Model and am extending it and calling the function as suggested in the relevant model I am trying to sort at the moment). Ignoring trimming and escaping characters etc (for the time being as I know how to implement this, I just haven't done so yet) can anyone tell me why this won't work.

I have this in MY_Model:

Code:
class MY_Model extends Model
{
    function  __construct()
    {

        parent::__construct();
    }

    // Used to filter and create insert and update data/fields from form posts
    function insert_udpate()
    {
        $keys = array_keys($_POST);

        foreach($keys as $key) {
            if(in_array($key,$this->mainfields)) {
                $data[$key] = $this->input->post($key,TRUE);
            }
        }
    }
}

Then I have this in my accounts_model:

Code:
class Accounts_model extends MY_Model {

    public $mainfields = array(
        'firstname',
        'surname',
        'add1',
        'add2',
        'add3',
        'town',
        'county',
        'postcode',
        'landline',
        'mobile',
        'email'
    );

    function __construct()
    {
        parent::__construct();

    }

    // Some other code here

    function update($id)
    {
       $this->db->update('accounts', $this->insert_update, array('id' => $id));

    }
    
}

However, if I run the foreah in the accounts_model function it works fine:

Code:
class Accounts_model extends MY_Model {

    public $mainfields = array(
        'firstname',
        'surname',
        'add1',
        'add2',
        'add3',
        'town',
        'county',
        'postcode',
        'landline',
        'mobile',
        'email'
    );

    function __construct()
    {
        parent::__construct();

    }

    // Some other code here

    function update($id)
    {
        $keys = array_keys($_POST);

        foreach($keys as $key) {
            if(in_array($key,$this->mainfields)) {
                $data[$key] = $this->input->post($key,TRUE);
            }
        }

        $this->db->update('accounts', $data, array('id' => $id));

    }
    
}

Any ideas please???
#4

[eluser]Mat-Moo[/eluser]
Insert_update doesn't return anything... not going to help Smile Maybe add return $data
#5

[eluser]simplepixie[/eluser]
I did wonder that - should it be $this->insert_update($data)?
#6

[eluser]Mat-Moo[/eluser]
Either setup a private var $data in my_model and call $this->inset_update() before the update, then reference $this->data in the update statement. Or just return $data in the insert_update function.
#7

[eluser]simplepixie[/eluser]
Thank you - I will give it a go
#8

[eluser]Rodrigo Ferreira[/eluser]
This is how I do this:

1. users_m extends MY_Model: http://bitbucket.org/jamierumbelow/codei...base-model

2. the 'fieldset' property contains arrays of areas related to the model and their respective fields (ex: for a 'users' model it would have the address area, contact area etc). Something like this:

Code:
class Users_m extends MY_Model {
    public $fieldset = array(
        'identification' => array(    
            array(
               'field'    => 'firstname', // field used in the form
           'dbfield' => 'firstname', // field in the DB. The 'field' above could be used,
but this way I can change the DB structure, if needed, without having to touch the views and controllers.
        'label'    => 'First Name', // label in the form
        'rules'    => 'trim|required|xss_clean', // rules
        'type'    => 'text' // type (could be text, textarea, dropdown etc). This is used to define how the field will be displayed in the form view.
           ),
            array(
               'field'    => 'surname',
           'dbfield' => 'surname',
         'label'    => 'Surname',
         'rules'    => 'trim|required|xss_clean',
         'type'    => 'text'
            )
        )
(...)
        'address' => array(    
            array(
               'field'    => 'landline',
           'dbfield' => 'phone', // just for the demonstration, you may have different dbfields names, usefull if you share a table etc.
               'label'    => 'Landline',
        'rules'    => 'trim|xss_clean',
        'type'    => 'text'
           ),
            array(
               'field'    => 'cel',
           'dbfield' => 'cel',
         'label'    => 'Cel Phone',
         'rules'    => 'trim|required|xss_clean',
         'type'    => 'text'
            )
        )
(...)
)

Note we have an array for identification, other for address etc. This is useful for adjust display or to split data in pages (in long forms).

In the controller:
Code:
// Let's say there's a specific area to update the address:
$area = 'address'; // In a real case this would be dinamically set.
$data['area'] = $area;

// the View must know what fields should be displayed:
$data['forms'] = $this->users_m->fieldset[$area];

// set the validation rules for those fields as defined in the model (the set_validation function sets the validate property in MY_Model):
$this->users_m->set_validation($data['forms']);

// we limit the insert fields to those indicated in the fieldset[area] array:
foreach ($data['forms'] as $field)
    $insert_array[$field['dbfield']] = $this->input->post($field['field']);

// the model handles validation and inserts data. The same logic may be used for updates. Note we do NOT use the $_POST array.
$insert_id = $this->users_m->update($id, $insert_array);

In the View ($user has the current user data):
Code:
<?foreach($forms as $form):?>
<label for="&lt;?=$form['field']?&gt;">&lt;?=$form['label']?&gt;</label>
&lt;?if ($form['type'] == 'text'):?&gt;
   &lt;input id="&lt;?=$form['field']?&gt;" name="&lt;?=$form['field']?&gt;" type="&lt;?=$form['type']?&gt;" size="64" value="&lt;?=set_value($form['field'], $user-&gt;$form['dbfield'])?&gt;" />
&lt;?elseif ($form['type'] == 'textarea'):?&gt;
  &lt;textarea id="&lt;?=$form['field']?&gt;" name="&lt;?=$form['field']?&gt;" cols="64" rows="5"&gt;&lt;?=set_value($form['field'], $user->$form['dbfield'])?&gt;&lt;/textarea&gt;
//(...code for dropdowns, bool etc etc etc)
&lt;?endif?&gt;
&lt;?endforeach?&gt;

EDIT: fixed some typos and added information on set_validation
#9

[eluser]simplepixie[/eluser]
That is great, thank you for your reply - it is a great way to set things out and I makes things easier for me to manipulate if required etc.

I will reply with the outcome in case anyone else needs this.
#10

[eluser]simplepixie[/eluser]
OK, I now have My_Model in use and updating is working fine, however I can't get the validation to work.

If I use (in my controller):
Code:
function do_update()
        {
            $data['forms'] = $this->accounts_model->fieldset['info'];

            $this->accounts_model->set_validation($data['forms']);

            foreach ($data['forms'] as $field)
            $insert_array[$field['dbfield']] = $this->input->post($field['field']);

            $this->accounts_model->update($this->session->userdata('account_id'), $insert_array);
          
            redirect('memberarea');
          
        }

I end up with a blank page (stuck at accounts/do_update).

However if I remove the validation (which I thought would run anyway if using MY_Model as it seems to be run unless I set it to be skipped):

Code:
function do_update()
        {
            $data['forms'] = $this->accounts_model->fieldset['info'];

            foreach ($data['forms'] as $field)
            $insert_array[$field['dbfield']] = $this->input->post($field['field']);

            $this->accounts_model->update($this->session->userdata('account_id'), $insert_array);
          
            redirect('memberarea');
          
        }

The update works fine but no validation occurs (for example I have set the email field to required but it updates without an email address).

Should I be loading the CI form_validation file as well?
Or otherwise what am I doing wrong?

My Model fieldset is such:

Code:
class Accounts_model extends MY_Model {

    public $fieldset = array(
        'info' => array (
            array(
                'field' => 'firstname',
                'dbfield' => 'firstname',
                'label' => 'Name',
                'rules' => 'trim|strtoupper|xss_clean',
                'type' => 'text'
            ),
            array(
                'field' => 'surname',
                'dbfield' => 'surname',
                'label' => 'Surname',
                'rules' => 'trim|strtoupper|xss_clean',
                'type' => 'text'
            ),
            array(
                'field' => 'add1',
                'dbfield' => 'add1',
                'label' => 'Address',
                'rules' => 'trim|strtoupper|xss_clean',
                'type' => 'text'
            ),
            array(
                'field' => 'add2',
                'dbfield' => 'add2',
                'label' => ' ',
                'rules' => 'trim|strtoupper|xss_clean',
                'type' => 'text'
            ),
            array(
                'field' => 'add3',
                'dbfield' => 'add3',
                'label' => ' ',
                'rules' => 'trim|strtoupper|xss_clean',
                'type' => 'text'
            ),
            array(
                'field' => 'town',
                'dbfield' => 'town',
                'label' => 'Town',
                'rules' => 'trim|strtoupper|xss_clean',
                'type' => 'text'
            ),
            array(
                'field' => 'county',
                'dbfield' => 'county',
                'label' => 'County',
                'rules' => 'trim|strtoupper|xss_clean',
                'type' => 'text'
            ),
            array(
                'field' => 'postcode',
                'dbfield' => 'postcode',
                'label' => 'Postcode',
                'rules' => 'trim|strtoupper|xss_clean',
                'type' => 'text'
            ),
            array(
                'field' => 'landline',
                'dbfield' => 'landline',
                'label' => 'Landline',
                'rules' => 'trim|xss_clean',
                'type' => 'text'
            ),
             array(
                'field' => 'mobile',
                'dbfield' => 'mobile',
                'label' => 'Mobile',
                'rules' => 'trim|xss_clean',
                'type' => 'text'
            ),
             array(
                'field' => 'email',
                'dbfield' => 'email',
                'label' => 'Email',
                'rules' => 'trim|required|xss_clean',
                'type' => 'text'
            )
        ),
        'added' => array(
            array(
                'dbfield' => 'created'
            ),
            array(
                'dbfield' => 'createdby'
            )
        ),
        'updated' => array(
            array(
                'dbfield' => 'modified'
            ),
            array(
                'dbfield' => 'modifiedby'
            )
        )
    );

    function __construct()
    {
        parent::__construct();

        $this->_table = 'accounts';

    }

}
/* End of file accounts_model.php */
/* Location: .application/modules/accounts/models/accounts_model.php */

This isn't complete yet - not sure if I can use strtoupper in the rules or not and am only testing on one required field for the moment until I get things working.

Please help as I have been looking for a solution to this since implementing the MY_Model yesterday.




Theme © iAndrew 2016 - Forum software by © MyBB