Never Use the id Field of the User Profile to Retrieve a MODX User’s Profile

This article is about a very insidious MODX error. It iMODX logonvolves using the id field of the user profile to retrieve a user’s profile. It will often work at first, but it can create an unholy mess over time.

 

 

 

The fact is that the id field of the user profile is completely arbitrary. It reflects the order in which the profile records were created and has no real relationship to the users whose profiles are stored there. The profile records are connected to their users by the profile’s internalKey field. The internalKey field is guaranteed to hold the user ID of the user related to that profile.

Here’s the confusing thing: because the users and their profiles are usually created at the same time, the profile’s id field often matches the user ID of that profile’s user. So if you try to get the current user’s profile with this code, it will often work:

[code language=”php”]
$profile = $modx->getObject(‘modUserProfile’, $modx->user->get(‘id’));
[/code]

Unfortunately, the two are almost certain to diverge over time as users and profiles are created and deleted. Eventually, you will get a user profile with this code, but it won’t be the profile of the user you think it is. If you then modify the profile, you’ll be modifying the profile of the wrong user without knowing it. After a while, you’ll have a giant, unrepairable mess on your hands.

 

Some Solutions

Luckily, avoiding this problem is easy. You just need to get the user profile the right way.

If you have the user object (or want the profile of the current user), you can use the getOne() method:

[code language=”php”]
/* If you have retrieved the user object yourself */
$profile = $user->getOne(‘Profile’);

/* If you want the profile of the current logged-in user */
$profile = $modx->user->getOne(‘Profile’);
[/code]

Note the capital ‘P’ in ‘Profile’. Profile is the xPDO alias for the modUserProfile object. Similarly, if you have the user profile and want to get the user object, you can do this:

[code language=”php”]
$user = $profile->getOne(‘User’);
[/code]

What if you have the user’s ID, but not the user object? You might, for example, be using the createdby, editedby, or publishedby field of the current resource. Those fields hold the user ID of the relevant user. Maybe you want to display the full name of the user who created the current resource. You could do this:

[code language=”php”]
$id = $modx->resource->get(‘createdby’);
$user = $modx->getObject(‘modUser’, $id);
$profile = $user->getOne(‘Profile’);
if ($profile) {
return $profile->get(‘fullname’);
}
[/code]

But notice that in the code above, you don’t really need the user object. It’s wasteful to retrieve the user object when all you need is the profile. Remember that the internalKey field of the user profile always holds the correct user ID, so you can do this instead and make your snippet much more efficient:

[code language=”php”]
$id = $modx->resource->get(‘createdby’);
$profile = $modx->getObject(‘modUserProfile’, array(‘internalKey’ => $id));
if ($profile) {
return $profile->get(‘fullname’);
}
[/code]

 

Final Notes

By now you should know never to use the id field of the user profile, but you might be wondering about the if ($profile) line in the code above. It’s unlikely, but possible, for a user to have no user profile. Users created with “New User” in the Manager will always have a profile (though it may be empty except for the user’s email address, which is required). Users created in code, though, can exist with no profile. They have a user ID, but there’s no corresponding record in the user profile table. If you don’t check to see if you got the profile before calling the profile’s get() method, you risk having the site visitor experience a fatal, and fairly ugly, PHP error (or a blank screen) when get() is called on a non-object.

 


For more information on how to use MODX to create a web site, see my web site Bob’s Guides, or
better yet, buy my book: MODX: The Official Guide.

Looking for quality MODX Web Hosting? Look no further than Arvixe Web Hosting!

Tags: , , , | Posted under MODX, MODX | RSS 2.0

Author Spotlight

Bob Ray

Bob Ray is the author of MODX: The Official Guide and over 30 MODX add-on components. He hosts Bob's Guides, a source of valuable information for MODX users, and has been very active in the MODX Forums with over 19,000 posts.

2 Comments on Never Use the id Field of the User Profile to Retrieve a MODX User’s Profile

  1. Some very good points!

    I believe the underlying issue,is whether or not developers are indeed using the built in constructs for accessing modUser and modUserProfile. I believe the safest mechanism is to “ride the relationships” defined in the schematic. This would include the creation is users using the built in processors and controllers which would ensure a profile is created for every user.

    $userProfileObj = $modx->resource->CreatedBy->Profile;

    Basically, let MODX handle it, which would help avoid simple oversights like the one mentioned in Bob’s article. We use a CMS for a reason.

    • Bob Ray says:

      Good advice, but I don’t think it necessarily solves the problem. While it’s a good idea to use the processors, you can’t count on every extra developer to do it. Even if they did, as you delete and create users, I don’t think you can count on MySQL to keep the Profile’s id and internalKey fields the same. The Profile’s internalKey field is guaranteed to match the User’s ID, so it’s safest to always use that to retrieve the Profile. Remember too, that you sometime want just the Profile without having to get the User object (say, to get the email address of a resource’s creator). If you know the user ID, it’s significantly faster to just grab the Profile using the internalKey field.

Leave a Reply

Your email address will not be published. Required fields are marked *