⚠ In case you've missed it, we have migrated to our new website, with a brand new forum. For more details about the migration you can read our blog post for website migration. This is an archived forum. ⚠

  •     

profile picture

Problem invoking before insert/update callbacks



tanver
  • profile picture
  • Member

Posted 09 December 2011 - 23:04 PM

I am trying to make the before insert/update callbacks work for me but don't know why am unable to make it work. I am calling the
..
$this->grocery_crud->callback_before_insert(array($this,'insert_user_created'));
$this->grocery_crud->callback_before_update(array($this,'update_user_info'));
$output = $crud->render();
..

and here is how my two callback functions are constructed


function insert_user_created($post_array)
{
//echo 'Hello from before Insert ..';
$post_array['user_created'] = $this->session->userdata('username');
$post_array['password'] = md5($_POST['password']);
return $post_array;
}

function update_user_info($post_array, $PKey)
{

//echo 'Hello from before update ..';
$post_array['last_edit_user'] = $this->session->userdata('last_edit_user');
$post_array['last_edit_date_time'] = date("yyyy-dd-mm",time());
return $post_array;
}

but it appears as if the two callback functions are never reached .. even though the records are added/updated without these additional values.

tanver
  • profile picture
  • Member

Posted 10 December 2011 - 07:50 AM

Sorry, having bumped on this.
I had even tried the example for callback_before_insert, as given here

http://www.grocerycrud.com/crud/example/callback_before_insert

But no luck even with this. It appears as if there is some issue with the CRUD and CI v2.1, this is what I am using. Any help to overcome this will be appreciated.

web-johnny
  • profile picture
  • Administrator
  • 1,166 posts

Posted 10 December 2011 - 08:32 AM

[quote name='tanver' timestamp='1323471885' post='116']
I am trying to make the before insert/update callbacks work for me but don't know why am unable to make it work. I am calling the
..
$this->grocery_crud->callback_before_insert(array($this,'insert_user_created'));
$this->grocery_crud->callback_before_update(array($this,'update_user_info'));
$output = $crud->render();
..

and here is how my two callback functions are constructed


function insert_user_created($post_array)
{
//echo 'Hello from before Insert ..';
$post_array['user_created'] = $this->session->userdata('username');
$post_array['password'] = md5($_POST['password']);
return $post_array;
}

function update_user_info($post_array, $PKey)
{

//echo 'Hello from before update ..';
$post_array['last_edit_user'] = $this->session->userdata('last_edit_user');
$post_array['last_edit_date_time'] = date("yyyy-dd-mm",time());
return $post_array;
}

but it appears as if the two callback functions are never reached .. even though the records are added/updated without these additional values.
[/quote]


Probably your callbacks don't work for some reason in your project. Try a simple think to see if everything works correctly . Try to use the function call_user_func and do something like this in a controller function:

call_user_func(array($this, 'update_user_info'));

and just have a dump message to your function for example

function update_user_info()
{
echo "It works";
}

and see if everything works correctly. If not then you will not be able to have any callback to your project. Try to fix this issue and probably will work

tanver
  • profile picture
  • Member

Posted 10 December 2011 - 11:59 AM

@web-johnny To be honest could not understand what do you mean by
[quote]Try to use the function call_user_func [/quote], I did try to use it instead of callback_before_update but ERRORS

clare
  • profile picture
  • Member

Posted 31 December 2011 - 16:30 PM

Hi, I've just started using grocery crud (it's amazing btw!) and I'm having a similar problem.
I'm trying to encrypt the user's password as below, but it doesn't seem to call the encrypt_pw function at all.
I've trued using call_user_func as suggested and that does work.

Thanks :)


function crud_users() {
$this->grocery_crud->set_table('Users');
//$this->grocery_crud->change_field_type('pw', 'password');

$this->grocery_crud->display_as('pw','Password');
$this->grocery_crud->callback_before_insert(array($this,'encrypt_pw'));
$output = $this->grocery_crud->render();

$this->load->view('admin',$output);
}

function encrypt_pw($post_array) {
if(empty($post_array['pw'])) {
$post_array['pw'] = SHA1($_POST['pw']);
}
return $post_array;
}


EDIT: I've also just tried doing this via validation rules:


$this->grocery_crud->set_rules('pw', 'Password', 'trim|required|sha1');


In the documentation you say that this function works the same way as the codeigniter function, which allows PHP functions to be used as a rule ('trim' and 'sha1' in this case). 'trim' works but 'sha1' doesn't seem to work here.

trangman
  • profile picture
  • Member

Posted 15 January 2012 - 14:06 PM

I'm having a similar issue I have a controller to create a user, encrypt the password and create an activation key. These two function work fine from a callback before insert, I also want to send an email using a callback after insert, if I add this the page doesn't load and gives a "Call to a member function callback_after_insert()" error, if I remove the callback before insert the callback after works.

So what I am saying is as far as I can work out callback_before_insert and callback_after_insert don't work together, help would be appreciated.

web-johnny
  • profile picture
  • Administrator
  • 1,166 posts

Posted 15 January 2012 - 20:41 PM

[quote name='clare' timestamp='1325349033' post='202']
Hi, I've just started using grocery crud (it's amazing btw!) and I'm having a similar problem.
I'm trying to encrypt the user's password as below, but it doesn't seem to call the encrypt_pw function at all.
I've trued using call_user_func as suggested and that does work.

Thanks :)


function crud_users() {
$this->grocery_crud->set_table('Users');
//$this->grocery_crud->change_field_type('pw', 'password');

$this->grocery_crud->display_as('pw','Password');
$this->grocery_crud->callback_before_insert(array($this,'encrypt_pw'));
$output = $this->grocery_crud->render();

$this->load->view('admin',$output);
}

function encrypt_pw($post_array) {
if(empty($post_array['pw'])) {
$post_array['pw'] = SHA1($_POST['pw']);
}
return $post_array;
}


EDIT: I've also just tried doing this via validation rules:


$this->grocery_crud->set_rules('pw', 'Password', 'trim|required|sha1');


In the documentation you say that this function works the same way as the codeigniter function, which allows PHP functions to be used as a rule ('trim' and 'sha1' in this case). 'trim' works but 'sha1' doesn't seem to work here.
[/quote]

You have a wrong logic it has to be if(!empty and not if(empty . So the right one is the below:

function encrypt_pw($post_array) {
if(!empty($post_array['pw'])) {
$post_array['pw'] = SHA1($_POST['pw']);
}
return $post_array;
}


As for the sha1, I think you are right. Codeigniter not only validates but also filter the values. I didn't knew that actually. So that's why the sha1 doesn't work , cause I don't take the filtered data from the codeigniter validator. I just check if the validation is correct and then continue with the saving. I will try to have this feature in the next version (1.1.8).

web-johnny
  • profile picture
  • Administrator
  • 1,166 posts

Posted 15 January 2012 - 20:49 PM

[quote name='trangman' timestamp='1326636361' post='284']
I'm having a similar issue I have a controller to create a user, encrypt the password and create an activation key. These two function work fine from a callback before insert, I also want to send an email using a callback after insert, if I add this the page doesn't load and gives a "Call to a member function callback_after_insert()" error, if I remove the callback before insert the callback after works.

So what I am saying is as far as I can work out callback_before_insert and callback_after_insert don't work together, help would be appreciated.
[/quote]

Can you give an example of your functions/methods that you use? I check this scenario and it works.

trangman
  • profile picture
  • Member

Posted 16 January 2012 - 00:14 AM

I was just chaining the functions together in one long line of code, which seems to have caused the problem. I changed the code to [color=#000088]$crud[/color][color=#2C575B] [/color][color=#339933]=[/color][color=#2C575B] [/color][color=#000000][b]new[/b][/color][color=#2C575B] grocery_CRUD[/color][color=#009900]([/color][color=#009900])[/color][color=#339933]; [/color]etc and it immediately worked. I am using HMVC which further complicates things, anyway it's working now and thanks for your quick reply.

jcasanova
  • profile picture
  • Member

Posted 13 April 2012 - 15:32 PM

web-johnny, the before_insert doesnt work if you add an extra item in the post array (not listed in the add form)

any idea??

web-johnny
  • profile picture
  • Administrator
  • 1,166 posts

Posted 13 April 2012 - 21:30 PM

/topic/221-upgrading-from-11x-to-12-or-later/

mikiza
  • profile picture
  • Member

Posted 01 May 2012 - 23:26 PM

[quote name='jcasanova' timestamp='1334331146' post='1216']
web-johnny, the before_insert doesnt work if you add an extra item in the post array (not listed in the add form)

any idea??
[/quote]

I stumbled upon the same problem.
I tried even to create function that will work with references and similar staff but to no result.
Then I checked the insert code (db_insert fnction) in grocery crud. It turns out that the callback_before_insert is called before actual insert is done, but if the additional key => value pairs are added it will ignore them since the for loop
[color=#ff0000]foreach($add_fields as $num_row => $field)[/color]{
...
}
is looping through the fields that are set to be visible in insert form.

So I modified the db_insert function (around the line 695) - checked if there are keys in $post_data that are not present in field list, and if so, I just pass these values to the $insert_data array.
Although this way those extra data are bypassing the field type check, since they're coming from callback function anyway, it works for me.
My Code now look like:


$fieldnames=array(); //added
foreach($add_fields as $num_row => $field)
{
$fieldnames[]=$field->field_name; //added
if(isset($post_data[$field->field_name]) && !isset($this->relation_n_n[$field->field_name]))
{
if(isset($types[$field->field_name]->db_null) && $types[$field->field_name]->db_null && $post_data[$field->field_name] === '')
{
$insert_data[$field->field_name] = null;
}
elseif(isset($types[$field->field_name]->crud_type) && $types[$field->field_name]->crud_type == 'date')
{
$insert_data[$field->field_name] = $this->_convert_date_to_sql_date($post_data[$field->field_name]);
}
elseif(isset($types[$field->field_name]->crud_type) && $types[$field->field_name]->crud_type == 'datetime'){
$insert_data[$field->field_name] = $this->_convert_date_to_sql_date(substr($post_data[$field->field_name],0,10)).
substr($post_data[$field->field_name],10);
}
else
{
$insert_data[$field->field_name] = $post_data[$field->field_name];
}
}
}

//following loop added to copy data to $insert_data array
foreach(array_keys($post_data) as $key){
if(!in_array($key,$fieldnames))
$insert_data[$key] = $post_data[$key];
}


Real fix would be to have full field list from database, and to check the post data against it, not against the field list specified with add_fields.
Probably the same thing could be done for updates.

web-johny thanks for great work on Grocery CRUD

web-johnny
  • profile picture
  • Administrator
  • 1,166 posts

Posted 02 May 2012 - 05:57 AM

Well there is a solution for this.
That's why I created the type "invisible" field. So for example if you have:


$crud->fields('field1','field2','field3');
$crud->callback_before_insert(array($this,'test_callback'));


and :


function test_callback($post_array){
$post_array['field4'] = 'test';
return $post_array;
}


This will NOT works unless you add the invisible field so you have to do it like this:


$crud->fields('field1','field2','field3','field4');
$crud->change_field_type('field4','invisible');
$crud->callback_before_insert(array($this,'test_callback'));


This is for security reasons so your work around will work but you will have problems with your security as the user can add as many fields as he want without having permission to do it.

mikiza
  • profile picture
  • Member

Posted 02 May 2012 - 12:22 PM

Yes, as I said, my solution was a workaround, usage of invisible fields is the correct way to go.
Somehow I missed that. Thanks.