欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

drupal7 user_save example 保存用户例子 有大用 有大大用

    
   下面是我亲自做的例子  有大用
if($_GET['q']=='user/1/getdata'){
       db_set_active('old');
       $sql  = "select u.*,p.value from users u left join profile_values p on u.uid=p.uid  where u.uid>=2 order by u.uid asc";
       $results = db_query($sql);
       var_dump($results);
       foreach ($results as $result) {
           var_dump($result->name);
           $new_user = array(
               'name' => $result->name,
               'pass' => '111',
               'mail' => $result->mail,
               'init' => $result->mail,
               'signature_format' => 'filtered_html',
               'timezone' => 'Asia/Shanghai',
               'data' => false,
               'field_qq' => array(LANGUAGE_NONE => array(array('value' => $result->value))),
               'status' => 1,
           );
           db_set_active('default');

           $account = user_save(null, $new_user);
//            $edit = array(
//                'field_qq' => array(
//                    'und' => array(
//                        0 => array(
//                            'value' =>  $result->value,
//                        ),
//                    ),
//                ),
//            );
//            user_save($account, $edit);

       }
       echo "AAAAA";exit;





function user_save

4.6.x user.moduleuser_save($account, $array = array(), $category = 'account')
4.7.x user.moduleuser_save($account, $array = array(), $category = 'account')
5.x user.moduleuser_save($account, $array = array(), $category = 'account')
6.x user.moduleuser_save($account,$array= array(), $category = 'account')
7.x user.moduleuser_save($account,$edit= array(), $category = 'account')

Save changes to a user account or add a new user.

Parameters

$account: (optional) The user object to modify or add. If you want to modify an existing user account, you will need to ensure that (a) $account is an object, and (b) you have set $account->uid to the numeric user ID of the user account you wish to modify. If you want to create a new user account, you can set $account->is_new to TRUE or omit the $account->uid field.

$edit: An array of fields and values to save. For example array('name' => 'My name'). Key / value pairs added to the $edit['data'] will be serialized and saved in the {users.data} column.

$category: (optional) The category for storing profile information in.

Return value

A fully-loaded $user object upon successful save or FALSE if the save failed.

25 calls to user_save()

File


  • modules/

    user/

    user.module, line 422

  • Enables the user registration and login system.


Code

function user_save($account, $edit = array(
  
), $category = 'account') {  $transaction = db_transaction();  try {    if (isset($edit['pass']) && strlen(trim($edit['pass'])) > 0) {      
      // Allow alternate password hashing schemes.
      require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc');      $edit['pass'] = user_hash_password(trim($edit['pass']));      
      // Abort if the hashing failed and returned FALSE.
      if (!$edit['pass']) {        return FALSE;
      }
    }    else {      
      // Avoid overwriting an existing password with a blank password.
      unset($edit['pass']);
    }    if (isset($edit['mail'])) {      $edit['mail'] = trim($edit['mail']);
    }    
    // Load the stored entity, if any.
    if (!empty($account->uid) && !isset($account->original)) {      $account->original = entity_load_unchanged('user', $account->uid);
    }    if (empty($account)) {      $account = new stdClass();
    }    if (!isset($account->is_new)) {      $account->is_new = empty($account->uid);
    }    
    // Prepopulate $edit['data'] with the current value of $account->data.
    // Modules can add to or remove from this array in hook_user_presave().
    if (!empty($account->data)) {      $edit['data'] = !empty($edit['data']) ? array_merge($account->data, $edit['data']) : $account->data;
    }    
    // Invoke hook_user_presave() for all modules.
    user_module_invoke('presave', $edit, $account, $category);    
    // Invoke presave operations of Field Attach API and Entity API. Those APIs
    // require a fully-fledged and updated entity object. Therefore, we need to
    // copy any new property values of $edit into it.
    foreach ($edit as $key => $value) {      $account->{$key} = $value;
    }    field_attach_presave('user', $account);    module_invoke_all('entity_presave', $account, 'user');    if (is_object($account) && !$account->is_new) {      
      // Process picture uploads.
      if (!empty($account->picture->fid) && (!isset($account->original->picture->fid) || $account->picture->fid != $account->original->picture->fid)) {        $picture = $account->picture;        
        // If the picture is a temporary file move it to its final location and
        // make it permanent.
        if (!$picture->status) {          $info = image_get_info($picture->uri);          $picture_directory = file_default_scheme() . '://' . variable_get('user_picture_path', 'pictures');          
          // Prepare the pictures directory.
          file_prepare_directory($picture_directory, FILE_CREATE_DIRECTORY);          $destination = file_stream_wrapper_uri_normalize($picture_directory . '/picture-' . $account->uid . '-' . REQUEST_TIME . '.' . $info['extension']);          
          // Move the temporary file into the final location.
          if ($picture = file_move($picture, $destination, FILE_EXISTS_RENAME)) {            $picture->status = FILE_STATUS_PERMANENT;            $account->picture = file_save($picture);            file_usage_add($picture, 'user', 'user', $account->uid);
          }
        }        
        // Delete the previous picture if it was deleted or replaced.
        if (!empty($account->original->picture->fid)) {          file_usage_delete($account->original->picture, 'user', 'user', $account->uid);          file_delete($account->original->picture);
        }
      }      elseif (isset($edit['picture_delete']) && $edit['picture_delete']) {        file_usage_delete($account->original->picture, 'user', 'user', $account->uid);        file_delete($account->original->picture);
      }      
      // Save the picture object, if it is set. drupal_write_record() expects
      // $account->picture to be a FID.
      $picture = empty($account->picture) ? NULL : $account->picture;      $account->picture = empty($account->picture->fid) ? 0 : $account->picture->fid;      
      // Do not allow 'uid' to be changed.
      $account->uid = $account->original->uid;      
      // Save changes to the user table.
      $success = drupal_write_record('users', $account, 'uid');      
      // Restore the picture object.
      $account->picture = $picture;      if ($success === FALSE) {        
        // The query failed - better to abort the save than risk further
        // data loss.
        return FALSE;
      }      
      // Reload user roles if provided.
      if ($account->roles != $account->original->roles) {        db_delete('users_roles')->condition('uid', $account->uid)->execute();        $query = db_insert('users_roles')->fields(array(          'uid',          'rid',
        ));        foreach (array_keys($account->roles) as $rid) {          if (!in_array($rid, array(            DRUPAL_ANONYMOUS_RID,            DRUPAL_AUTHENTICATED_RID,
          ))) {            $query->values(array(              'uid' => $account->uid,              'rid' => $rid,
            ));
          }
        }        $query->execute();
      }      
      // Delete a blocked user's sessions to kick them if they are online.
      if ($account->original->status != $account->status && $account->status == 0) {        drupal_session_destroy_uid($account->uid);
      }      
      // If the password changed, delete all open sessions and recreate
      // the current one.
      if ($account->pass != $account->original->pass) {        drupal_session_destroy_uid($account->uid);        if ($account->uid == $GLOBALS['user']->uid) {          drupal_session_regenerate();
        }
      }      
      // Save Field data.
      field_attach_update('user', $account);      
      // Send emails after we have the new user object.
      if ($account->status != $account->original->status) {        
        // The user's status is changing; conditionally send notification email.
        $op = $account->status == 1 ? 'status_activated' : 'status_blocked';        _user_mail_notify($op, $account);
      }      
      // Update $edit with any interim changes to $account.
      foreach ($account as $key => $value) {        if (!property_exists($account->original, $key) || $value !== $account->original->{$key}) {          $edit[$key] = $value;
        }
      }      user_module_invoke('update', $edit, $account, $category);      module_invoke_all('entity_update', $account, 'user');
    }    else {      
      // Allow 'uid' to be set by the caller. There is no danger of writing an
      // existing user as drupal_write_record will do an INSERT.
      if (empty($account->uid)) {        $account->uid = db_next_id(db_query('SELECT MAX(uid) FROM {users}')->fetchField());
      }      
      // Allow 'created' to be set by the caller.
      if (!isset($account->created)) {        $account->created = REQUEST_TIME;
      }      $success = drupal_write_record('users', $account);      if ($success === FALSE) {        
        // On a failed INSERT some other existing user's uid may be returned.
        // We must abort to avoid overwriting their account.
        return FALSE;
      }      
      // Make sure $account is properly initialized.
      $account->roles[DRUPAL_AUTHENTICATED_RID] = 'authenticated user';      field_attach_insert('user', $account);      $edit = (array) $account;      user_module_invoke('insert', $edit, $account, $category);      module_invoke_all('entity_insert', $account, 'user');      
      // Save user roles. Skip built-in roles, and ones that were already saved
      // to the database during hook calls.
      $rids_to_skip = array_merge(array(        DRUPAL_ANONYMOUS_RID,        DRUPAL_AUTHENTICATED_RID,
      ), db_query('SELECT rid FROM {users_roles} WHERE uid = :uid', array(        ':uid' => $account->uid,
      ))->fetchCol());      if ($rids_to_save = array_diff(array_keys($account->roles), $rids_to_skip)) {        $query = db_insert('users_roles')->fields(array(          'uid',          'rid',
        ));        foreach ($rids_to_save as $rid) {          $query->values(array(            'uid' => $account->uid,            'rid' => $rid,
          ));
        }        $query->execute();
      }
    }    
    // Clear internal properties.
    unset($account->is_new);    unset($account->original);    
    // Clear the static loading cache.
    entity_get_controller('user')->resetCache(array(      $account->uid,
    ));    return $account;
  } catch (Exception $e) {    $transaction->rollback();    watchdog_exception('user', $e);    throw $e;
  }
}

Comments

ookami.kb’s picture

To save fields data in user account we can act this way:

$account = user_load($uid); // Loading account$edit = array(
  'field_some_custom_field' => array(
    'und' => array(
      0 => array(
        'value' => $new_value,
      ),
    ),
  ),);user_save($account, $edit);
stano.lacko’s picture

Depends on Field type.

Some types want other than standard "value" key name:

Link - "url"
Email - "email"

peterx’s picture

'tid' => $new_value,

drippydrop’s picture

I was looking and looking to find out how to add a new user to an organic group via a custom form.
Here is what I found out.

$new_user = array(
      'name' => $form_state['values']['name'],
      'pass' => user_password(),
      'mail' => $form_state['values']['mail'],
      'init' => $form_state['values']['mail'],
      'field_first_name' => array(LANGUAGE_NONE => array(array('value' => $form_state['values']['field_first_name']))),
      'field_last_name' => array(LANGUAGE_NONE => array(array('value' => $form_state['values']['field_last_name']))),
      'field_phone_number' => array(LANGUAGE_NONE => array(array('value' => $form_state['values']['field_phone_number']))),
      'status' => 1,
      'access' => REQUEST_TIME,
      'roles' => $roles,);// $account returns user object$account = user_save(null, $new_user);// $group is organic group node I want to add the brand new user to$group = og_get_group('node', $node->nid);// This adds user to the groupog_group($group->gid, array('entity' => $account));

Hope this helps some folks along with adding a new user to a group!

xcel’s picture

Wow, this was exactly what I was wanting to do.
I had to change the custom form to submitted node values but still, the whole process is there, well explained
I will not set 'access' though because it confuses admin since it says user has logged in whereas (s)he have not.
Anyway, many thanks you made me save a lot of time.

artfulrobot’s picture

This is good for a new user, but will only add membership to the $group, not edit all membership fields. If you want to absolutely set memberships to a known list then you can do this:

$new_user['og_user_node'][LANGUAGE_NONE] = array(
  array('target_id' => $group->gid),
  // ... add other groups here ...
  );
paul2’s picture

Worth noting:

Even though the user object that is returned from user_load() (and by this function) stores an integer value in $user->picture (being the file's fid), that is not the correct data type to use if you wish to update the profile picture using this function. If you try to do so, somehow this function silently fails, and none of your other attempted edits will be saved either (still not sure why there isn't instead an error somewhere).

The correct way to update the profile picture is to pass its associated file object in the $edit array, not its integer fid.

resplin’s picture

The anonymous user in Drupal has a uid=0.

When execution reaches this line:

 if (!empty($account->uid)  && !isset($account->original)) {

The call to empty returns true because of the zero value, and user_save decides it is a new user. This will fail because the new user has a duplicate username.

So if you need to edit all users (I am setting a default value for a custom field), you need to strip uid=0 from the list and deal with it as a special case.

peterx’s picture

User data is going away in Drupal 8 and user data is difficult to list. Move your data into fields. You can then list users that have your data and you can list their values.

Each extra field will slow down your database a little bit. If you have several related items, you might want to group them the way the address field module groups address fields in one row.

peterx’s picture

When you save a user, other modules have their user hooks called to modify the user. If you get weird results, such as missing fields, it can be another module responding to a hook and changing stuff.

Your save might be followed by another module changing the same field. Another module might respond as if you are editing the user in the admin page. A good test is to visit the user in the admin edit page, note all the values, run your save, then visit the user in the admin edit page and look for unexpected changes.

kiamlaluno’s picture

In Drupal 8, this function has been replaced from Entity::save().

ih8grep’s picture

The example user_save($user, array("key" => "value")); is wrong! Instead do something like this

global $user;$user_fields = user_load($user->uid);$myfield = $user_fields->field_myfield;$myfield['und'][0]['value'] = "This value was set programatically";user_save($user,"field_myfield"=>$myfield);
kingandy’s picture

... technically "key" => "value" (or as it seems to have changed to, "name" => "My name") is accurate, it's just that in the case of a Field API field "value" is this complex multidimensional array instead of a string. But then, "key" would not exactly be "key" anyway, it'll be replaced by whatever key is appropriate to the data value you're trying to amend, and there's certainly elements (status, mail, pass, etc) that don't use the complex Field API structure. I think it's clear from context that this is an illustration of how the function works rather than a usable code snippet.

Just for completeness I'll note that the second arg in the user_save call here should be array("field_myfield"=>$myfield). And TBH I would not personally build that in my function call. I'd do something like this:

global $user;$user_fields = user_load($user->uid);$edit['field_myfield'] = $user_fields->field_myfield;$edit['field_myfield'][LANGUAGE_NONE][0]['value'] = "This value was set programatically";user_save($user, $edit);
guy_schneerson’s picture

When searching for examples of updating existing users programmatically you find many variations in code and in most cases they all work.

The reason for this is that $edit (should contain changes only) is copied into $account by user_save().
As a result if you assign a changed field to account instead of to the $edit the result will be the same

so:

  $account = user_load($uid);

  $edit = array();
  $edit['field_first_name'][LANGUAGE_NONE][0]['value'] = 'Guy';
  $edit['field_last_name'][LANGUAGE_NONE][0]['value'] = 'Schneerson';

  user_save($account, $edit);

and

  $account = user_load($uid);
  $account->field_first_name[LANGUAGE_NONE][0]['value'] = 'Guy';
  $account->field_last_name[LANGUAGE_NONE][0]['value'] = 'Schneerson';

  $edit = array();

  user_save($account, $edit);

Will both work, however the first one is the correct way of doing things.

guy_schneerson’s picture

$edit should contain changes you want saved, however if you have a multi value element you need to include all its values
for example adding a role

Wrong way: will remove all roles except 'new role'

  $account = user_load($uid);
  $edit = array();
  $edit['roles'][NEW_ROLE] = 'new role';
  user_save($account, $edit);

Correct way: will add 'new role' to existing roles

  $account = user_load($uid);
  $edit = array();
  $edit['roles'] = $account->roles;
  $edit['roles'][NEW_ROLE] = 'new role';
  user_save($account, $edit);
Martin P.’s picture

I wanna ask you something for this part:

$account = user_load($uid); // Loading account$edit = array(
  'field_some_custom_field' => array(
    'und' => array(
      0 => array(
        'value' => $new_value,
      ),
    ),
  ),);user_save($account, $edit);

What is 'field_some_custom_field' ? Where do i find, what name i have to write there? I want to add custom hidden fields as targets for Feeds Module (to import users automatically one time a day).

Maybe somebody can help me how to add this function in the FeedsUserProcessor.inc.php

I have found out, that you have to add 2 parts of code for every target you want to add. I have found the code for Adding User Roles for example:

    if ($account->roles_list) {
     $roles = explode(',', $account->roles_list);
     foreach ($roles as $role_name) {
       $role_name = trim($role_name);
       if (!$role = user_role_load_by_name($role_name)) {
         // Create new role if role doesn't exist
         $role = new stdClass();
         $role->name = $role_name;
         user_role_save($role);
         $role = user_role_load_by_name($role->name);
     }
       $account->roles[$role->rid] = $role->name;
     }
   }

and

	  'roles_list' => array(
		'name' => t('User roles'),
		'description' => t('User roles'),
      ),

I also know, that the first part is to use / work with the the input (but i dont know where it gets saved) and the second part is for naming and descibing the target for the backend UI. But i am not good enough to use this knowledge for adding other/additional user fields.

Maybe somebody could make an example?

tinny’s picture

$account->name = 'me';$account->pass = 'xxx';$account->mail = 'x@x.com';$account->status = 1;// 3 and 4 are role id's$roles = array(3 => true, 4 => true);$account->roles = $roles;user_save($account);
skruf’s picture

Beware. I tried this and the password was saved un-encrypted in the database. You need to add it to the second argument:

user_save($account, array('pass' => 'xxx'));

asanchez75’s picture

$newUser = array(
'name' => 'username',
'pass' => 'password', // note: do not md5 the password
'mail' => 'email address',
'status' => 1,
'init' => 'email address'
);
user_save(null, $newUser);

See https://drupal.org/node/1969192

tutumlum’s picture

D7:
Fill in all of your fields for an example user and run the following code:

<?php$user = user_load(1);debug($user);?>

Then, copy the array and modify required parts...

Fernando Vesga’s picture

Or just install Devel module and go to the user page and you will see a Devel tab with al the info.
Or, after install it, paste in your code the following

<?phpdpm($user);?>
sheldonkreger’s picture

I found that if I passed the entire user object when saving an existing user, it would fail to update the user but throw no error.

For $account, you must pass an object containing ONLY the uid of the user when you want to do an update.

tamerzg’s picture

In Drupal 8 instead of user_save() you would use $user->save()

rujinxero’s picture

I need to change a users email without a confirmation email is that possible?

johnkareoke’s picture

Code:

$account = new stdClass();$account->name = 'johnny';$account->mail = 'johnny@google.com';$account->init = 'johnny@google.com';$account->pass = user_password('ferrari599');$account->status = 1;user_save(Null, $account);if ($account->uid) {
  drupal_set_message('Created new user with id %uid', array('%uid' => $account->uid));}

I get the following error:

Error: Call to undefined function field_attach_presave() in user_save() (line 468 of ./modules/user/user.module).

Really can't seem to figure this out. Any help appreciated.

kingandy’s picture

The forums are much better for this type of question, people are more likely to regularly read them and you'll also get reply notifications.

That said - passing in an object as the second parameter is Wrong. What you want to do here is build an ARRAY with your user details, and then use user_save() to create the user account object. Something like this:

$edit = array(
  'name' => 'johnny',
  'mail' => 'johnny@google.com',
  'init' => 'johnny@google.com',
  'pass' => 'ferrari599',
  'status' => 1,);$account = user_save(NULL, $edit);if ($account->uid) {
  drupal_set_message('Created new user with id %uid', array('%uid' => $account->uid));}

(Note that the 'pass' key will be automatically encrypted by user_save(), and also that user_password() generates a random password and does not in fact take a text input.)

THAT said - I'm not sure if that will be anything to do with the field_attach_presave() error you're seeing. Passing in an object would most likely silently fail (with a message in the watchdog log thanks to the try/catch block).


来自 https://api.drupal.org/api/drupal/modules!user!user.module/function/user_save/7.x







Hi, i've created some extra user-fields (Home » Administration » Configuration » People » Account settings). Now i want to store data in these fields programmatically. But whatever i try, i don't get it working...

This is what i've done:

global $user;// load user$existingUser = user_load($user->uid);// edit field-data$existingUser->field_somefield['und'][0]['value'] = 'blah';// save existing user$user = user_save((object) array('uid'=>$user->uid), (array) $existingUser);

Has anybody a hint what i do wrong? or a good example for drupal 7?

Comments

aaustin’s picture

This is what works for me:

$existing = user_load($uid);$edit = (array) $existing; $edit['field_somefield']['und'][0]['value'] = 'blah';user_save($existing, $edit);
c4mb0t’s picture

I want to do the exact same thing, but for some reason it seems to me like we are doing it wrong if we have to add ['und'][0]['value'] to a field name in order to modify it. What does that even mean? Isn't Field API supposed to make things simpler?

I guess my main question is: Is this the right way to do this?

WorldFallz’s picture

the [und] has to do with language translation ('und' = undefined iirc), the [0] is the index of the individual item in the field, and the [value] is which of the properties of field you wish to use.

c4mb0t’s picture

Thanks for the info. I thought more about my problem and distilled my question down to this:

I looked at the Field API expecting to find something like field_set_value() for setting the value of a field.

Continuing the above example, I was hoping there would be something like:
field_set_value($edit['field_somefield'], 'blah');
rather than:
$edit['field_somefield']['und'][0]['value'] = 'blah';

Is there a function like my first example or is my second example the correct way to do things?

WorldFallz’s picture

ah... interesting idea, but I don't know. Easy enough to find out though: http://api.drupal.org/api/search/7/field_

mtrolle’s picture

I totally agree - it seems like a "hacky" solution to use $edit['field_somefield']['und'][0]['value']

kevee’s picture

Every entity has a language declaration, so you can instead say:

$edit['field_somefield'][$user->language][0]['value']
diwant’s picture

Hey, use LANGUAGE_NONE instead of 'und'.

pangus’s picture

I tried the above ( user 1 - Core 7.21 ) - and it stopped accepting my password

Using this Drupal 6 suggestion...

http://drupal.org/node/976888#comment-3731202

...fixed it.

e.g.

$existing = user_load($uid);
unset($existing->pass);
$edit = (array) $existing;
$edit['field_somefield']['und'][0]['value'] = 'blah';
user_save($existing, $edit);

pangus’s picture

The code above was logging me out erratically. I should have been passing the $user obtained using global $user to user_save() - not the user obtained from user_load().

The code above is now working as...

global $user;
$existing = user_load($uid);
unset($existing->pass);
$edit = (array) $existing;
$edit['field_somefield']['und'][0]['value'] = 'blah';
user_save($user, $edit);

dlaufer’s picture

This worked for me in 2017 still. I tried a whole bunch of other ways and this was the only way I could update a user field programmatically.

jack_tux’s picture

Once you have the user object use the metadata_wrapper to work with fields.

global $user;// Can be used for all entity types$obj = entity_metadata_wrapper('user', $user);// You can now access the fields without knowing the language$obj->field_somefield = 'blah';// save changes$obj-save();

If you want to read the field data

$obj = entity_metadata_wrapper('user', $user);$val = $obj->field_somefield->value();
parisek’s picture

But you must install Entity API module (http://drupal.org/project/entity) to use this... just writing as reminder for beginners

jim_at_miramontes’s picture

Assuming anyone's still tracking this thread:

I'm kinda late to this party, but: is the entity approach better in terms of performance than the user_save thing described above? It strikes me that loading and saving the whole freakin' user object has to be pretty costly, but I don't know enough about the comparable internals to judge.

louisjimenez’s picture

Used this technique and it worked perfectly! thanks!

dharper’s picture

I'm trying to update some 'custom' user profile fields when an account is created.
I'm using shibboleth, and can get a hold on the vars I need.
I created a field named field_data_field_profile_union_code in the new drupal7 way of adding a field to user.
I have a module working.

In my module I want to call a hook after the new user is created via shibboleth. (I THINK It's hook_user_insert)
then I want to call something like the above code, where I can set my new drupal field to the shibboleth value e.g.
field_data_field_profile_union_code=>($_SERVER['User_union_code'] ), then save it and have Drupal update teh default account of the just created user with the shibboleth values for the custom fields.

I keep running into the white-screen-of-death however. I can see the shibboleth variables by calling:
...drupal_set_message("Hello, ".($_SERVER['PHP_AUTH_USER'] )." ...

I can also call global $user;

BUT as soon as I start calling user_load, I get WSOD!

Is the above code not meant for a module?

Thanks

sano’s picture

The incorrect part of the code:

// save changes
$obj-save();

The corrected version:

// save changes
$obj->save();


来自   https://www.drupal.org/forum/support/module-development-and-code-questions/2011-02-01/d7-user_save-s...





普通分类: