By Dio-1 on
Hello,
I use hook_user in my module ("roles_by_profile") to modify account data when a user account gets updated:
function role_by_profile_user($op, &$edit, &$account, $category = NULL)
{
if ($op == 'update')
{
...
}
}
Within the ($op == 'update') condition I modify the $account object. However, these modifications are not saved to the database, although they should be – after all, $account is passed as a reference. What exactly is the problem here?
Comments
You want op == 'submit'
The case op == 'submit' happens before the user data is inserted/updated and sounds like what you want. The insert and update ops happen after the user data is saved and allow you to save additional data (typically in other tables).
Already tried it before - doesn't work
Even with op == submit, changes to $account aren't saved. Is this is a bug?
I now have my module write directly to the roles table, which of course isn't as elegant and possibly incompatible with later versions of Drupal.
$op == submit is only called
$op == submit is only called when you are submitting the user edit form at user/[uid]/edit, from what I can tell.
$op == update is called before the database is updated, but from what I can tell, only changes to $edit are saved into the user record.
$op == insert is called after the user is inserted into the database, but user_save does an update afterwards. Again, only changes to $edit are saved into the user record.
See http://api.drupal.org/api/5/function/user_save and pay close attention to where user_module_invoke() is called to get an idea of what's going on.
Case submit does work
but you should use the $edit object in hook_user for that. The info at hook_user is a bit unclear about this. It says: "submit": Modify the account before it gets saved.
What actually happens is this (Drupal 5):
1. You push submit from user edit form, the function user_edit_submit is called.
2. user_edit_submit() calls user_module_invoke('submit', $form_values, $account, $category);
3. user_edit_submit() calls user_save($account, $form_values, $category);
4. user_save() calls user_module_invoke('update', $form_values, $account, $category);
5. user_save() processes the $form_values (this is $edit in hook_user).
You jump in at step 2 (or 4, then you should use case 'update', I don't think there is any difference really), with your hook_user. You can add fields to the $edit object, or change them. In my hook_user this is what I do:
case 'submit':
$edit['fullname'] = $account->profile_first_name .' '. $account->profile_last_name;
break;
The function user_save figures out what it is that you added to the $edit object. If it is a standard field like [name] or [email], it is stored directly. If it's a role, the users_role table is update. If it doesn't know the field yet, it will add it (after serialization) to the [data] field in the users table. In that last case, the nice thing is that this data is automatically deserialized and added to the user object every time the user is loaded. So for example I'm able to acces a users fullname with $user->fullname always.
Note that although $account is passed by reference, user_save() doesn't actually do anything with the changes you do to it.
Another way of saving changes after an update from the user edit form is to store them by some database update as suggested in the hook_user, case update, documentation. But, as someone else mentioned on this page, this is only needed when you are working with data in a different table then the users or users_roles table.
Hope this helps anyone!
I can't get this to work
I can't get this to work either.
My 'login' and 'insert' cases work fine, but neither 'update' or 'submit' will work.
Extract from code:
This code doesn't really do anything, it's just test code to tray and get this working.
Thanks
Glenn
Glenn
THECA Group
You code appears to fail
You code appears to fail because the user module updates the roles after user_hook() is called for either insert or update calls.
Does anyone know whether this is a bug or a feature?
If it is a Drupal bug, where can I report/file it?
roles or role ?
You say your module name is roles_by_profile (with an s in roles), but your function is named role_by_profile_user without an s in the word role.