Using real names in Drupal 7

Introduction

This article will allow you to support having both login usernames and real (as in natural language) usernames existing simulataneously in Drupal 7.  For example, my username might be mbh, but what I'd like is that it appears for myself and everyone else as Mike Harris.  There's also some code to link it into your own module.   But first some background...

Some background: why I wanted to do this...

For a project I'm doing, I recently migrated to Drupal 7.  This was no mean feat in itself: I did try to upgrade from 6 to 7, but the differences between the two meant that this really didn't work.  Luckily the site was still in development with only test data in the database, so I bit the bullet in deciding to completely ditch my work in D6 and start again from scratch in D7.  It took some time to do, but overall, the end result is better than the D6 version, not only because I implemented things better the second time round, but also because of the fact that D7 has more stuff in core that works, such as image field handling; but not, note, Views.  One wonders how come it's taken until version 7 to have custom fields and image fields as core functionality of a CMS and framework...

Anyway, a time consuming activity has been completely re-writing my bespoke module as the wise old Drupal folk have radically changed the API.  For the better I might add, but still, that was fun.

The down-side of the API changes is that loads of modules I was running are now no longer available because the author involved has obviously had better things to do with their life than port their (often somewhat flakey) Drupal module to version 7.

But a lot of folk have, and I'm pleased to say that most of the best and most useful modules are across (though often in beta still). 

For this project, my bespoke module overrides the default Drupal 7 authentication in order to authenticate users against a user table in a different legacy database.  During the authentication, the code copies the current values for the user's email, password and their real name from the legacy non-Drupal database table to the Drupal database: it also checks certain permissions and sets some roles for the user.  Here's an example of my code:

    global $user;
    $user_data = array('roles' => $edit['roles'],
               'pass'  => $me['password'],
               'mail'  => $me['mail']);
    user_save($user, $user_data);

To be able to store real names in Drupal, which doesn't do it out of the box, I was using the module Real Name in Drupal 6.  It added the feature of being able to store a separate 'real world name' for the user as well as their login username. 

In D6 erveything was quite simple.  Real Name used a table realname and stored the full username in their alongside the user's id; thus cross-referencing it to the user itself.  This real name automatically appeared in place of the login name on anything published on the web site.  In my own code, I simply queried another table and inserted lines into the realname table: possibly a bit of a hack, but it worked a treat.

Enter the D7 version of Real Name: it doesn't work like that at all, because the whole way information is stored in the database has radically changed and been more abstracted than previously.  Also it seems that not all of the CCK has come over to the core of Drupal, and this means some extra modules are needed. 

In fact it really didn't work at all, I coudn't really understand how to use it and the README.TXT file that comes with it was a pretty poor excuse for the documentation on the module.  Eventually after much hair pulling, I eventually worked it out.

The way to make it work

What I needed to do is to add an extra bespoke field to the user to store the real name in, then tell the Real Name module to use this new field to store it's information in, and then I was able to store my real name in the bespoke user field and have Real Name pick it up and use it automatically.

Modules to install

First we need to install the following Drupal modules:

  • Real Name - this allows us to edit, store and use real names for users.
  • Token - you really ought to have this installed anyway.
  • Entity - Enables modules to work with any entity type and to provide entities.
  • Entity Token - Provides token replacements for all properties that have no tokens and are known to the entity API.

In the above list, you need Real Name to handle realnames and this module is dependent upon Token, so you need that.  Then if you want to programmatically be able to store and use the realname as part of the user object, then you need to install Entity, and it's sub-module Entity Token. 

Add a field to user

Go to Configuration -> People -> Account Settings -> Manage Fields - which should take you to the path admin/config/people/accounts/fields.  Add a new field with the properties:

  • Label: your choice, but I called mine Real Name
  • Name: again your choice, but mine is called field_user_realname
  • Field: Text
  • Widget: Text Field
  • Other properties: well I set it to a maximum of 150 characters long, and as I'm using the Field Permissions module, I also checked all the boxes so that I can control what users can and cannot do with the new field.

Connect the Real Name module to the new field

Go to Configuration -> People -> Real Name - which should take you to the path admin/config/people/realname.  In the Realname pattern box enter your new field name (in my case [user:field-user-realname] ).   Note that this field should appear in the list of fields in this page.  If it doesn't, make sure you've added it in the previous step and make sure you've got both Entity and Entity Token modules enabled.

Manually editing the user's Real Name

Now when you go to edit a user, there'll be a new field Real Name where you can enter the user's realname.  As soon as you do this, then all references to the user will change from the raw username to the realname.  For example, let's say my initial user I created (with an id of 1 by default) had a username of superuser, I edit them by visiting the path user/1/edit and then enter a user name of Systems Admin, which instantly changes all instances of superuser to Systems Admin.

Setting the new Real Name field from one's own bespoke code

I needed to set realname from my own code.  This is the way I'm doing it, using a bespoke filed that's added to the user obejct:

    global $user;
    $user_data = array('roles' => $edit['roles'],
               'pass'  => $me['password'],
               'mail'  => $me['mail'],
               'field_user_realname' =>
               array('und' =>
                 array(array('value' => $me['realname'],
                     'format' => NULL,
                     'safe_value' => $me['realname']))),
               );
    user_save($user, $user_data);

And, hey presto: the user logs in using their normal login and password and their real name is fetched from the legacy database and displayed on all the Drupal pages.

Under the hood

Adding the bespoke realname field to the user object, adds the two tables field_data_field_user_realname and field_revision_field_user_realname to the Drupal database.  Here's what the first one looks like (the second one is identical to this):

+-------------+--------+---------+-----------+-------------+----------+-------+---------------------------+----------------------------+
| entity_type | bundle | deleted | entity_id | revision_id | language | delta | field_user_realname_value | field_user_realname_format |
+-------------+--------+---------+-----------+-------------+----------+-------+---------------------------+----------------------------+
| user        | user   |       0 |         1 |           1 | und      |     0 | Systems Admin             | NULL                       |
+-------------+--------+---------+-----------+-------------+----------+-------+---------------------------+----------------------------+

And the module Real Name adds the realname table, which looks like this:

+-----+-------------------------+------------+
| uid | realname                | created    |
+-----+-------------------------+------------+
|   1 | Systems Admin           | 1311245097 |
+-----+-------------------------+------------+

Display the field in a view

Now go to your view where you want to display the field.  Before you add the field, you have to create a Relationship to the User object (something that was there by default in D6, but no longer in D7).  Do this by expanding the Advanced options menu for your view and add a Relationship to ..... (note: I gotta finish this bit!)... here's some screeshots:


 

Fetching and displaying the field in a theme file

I wanted to adapt my theme to have the line Currently logged in as realname in my heade area.  This was easy to do with the following in page.tpl.php:

<span id="current-user"><?php print "Currently logged in as " . format_username($user); ?></span>