Passing Data between Two Snippets V

Pass data between two snippets using User Settings


Variable values don't persist across different snippets, even when they're on the same page or in the same template. In the previous article, we looked at using a cookies to pass data to another snippet. In this one, we'll see how to do it with User Settings.

MODX logo

User Settings

When we discussed cookies in the previous article, you may have noticed that they are used almost exclusively to store user-specific data &mdash data that is for and about a single user. If you need to save and retrieve user-specific data User Setting are often a better choice. They are easy to retrieve, don't require that the user have cookies enabled, work in private and incognito mode, and can't be deleted in the browser.

Before diving into User Settings, I want to mention the obvious option of using the extended field of the User Profile object to store user-specific data. Frankly, the extended field is not a good place to store data. It's a pain to store data there in code (if you do it wrong, you can wipe out other settings). It's a pain to create them, it's a pain to retrieve them, you can't get them with MODX tags, and they are unreliable and slow for searching and sorting. User Settings or a custom database table are almost always a better option.

User Settings are essentially System Settings that only apply to a single user. They may have the same name as System Settings (e.g., manager_language or cultureKey), in which case they will override the System Setting of the same name. You can also create User Settings that have unique names and use them for whatever you want. They will be available throughout the site and can be retrieved with standard setting tags:

[[++UserSettingName]]

You can also retrieve them in code with $modx->getOption()

$value = $modx->getOption('UserSettingName', null, 'default', true);

User Setting values are permanent (unless you delete them), and will survive updates to MODX and any extras. Cookies do have a few advantages over User Settings, but for many use cases, these are not significant. Settings have no expiration date, and unlike cookies, they can't be limited to just part of a domain. On the other hand, unlike cookies, they can't be viewed or edited by the user unless you create code to display and/or update them, so they are generally more secure and reliable than cookies and can hold sensitive data about the user. I suspect that with the stringent European Union (EU) laws regarding cookies, more and more sites will move to storing user data in the database.

One other drawback to User Settings it that (like extended fields) you need to create them for each user on your site, but you can do this as part of the registration process with a postHook on the Register snippet. You can also do it in the code you use to set the setting value (more on this in a bit). For existing users, you can create them with a simple utility snippet like this one:

$settings = array(
    /* '' is the value of the setting, change it if you need to */
    'Setting One' => array(
        'name' = 'Setting One',
        'key'  => 'setting_one',
        'description' => 'This is setting one',
        'namespace' => 'core',
        'value' => '',
        'xtype' => 'textfield',
    ),

    'Setting Two' => array(
        'name' = 'Setting Two',
        'key'  => 'setting_two',
        'description' => 'This is setting two',
        'namespace' => 'core',
        'value' => '',
        'xtype' => 'textfield',
    ),
    'Setting Three' => array(
        'name' = 'Setting Three',
        'key'  => 'setting_three',
        'description' => 'This is setting Three',
        'namespace' => 'core',
        'value' => '0',
        'xtype' => 'combo-boolean', // Yes/No setting
    ),
);

$users = $modx->getCollection('modUser');
foreach ($users as $user) {
    $userId = $user->get('id');
    foreach($settings as $settingName => $fields) {
        $fields['user'] = $userId;
        $modx->runProcessor('security/user/setting/create', $fields);
    }
}

You may worry that since MODX loads settings into memory that your settings will take up a lot of memory if you have many users, but MODX only loads the User Settings for the current user when the user logs in.


Setting User Settings in Code

To update the value of a User Setting, you need to retrieve it, set the value and save it. That looks like this:

$settingKey = 'setting_one';
$value = 'some value';
$userId = $modx->user->get('id');
// or, for another user: $userId = 12;

$fields = array(
    'classKey' => 'modUserSetting',
    'user' => $userId,
    'key' => $settingKey,
);

$setting = $modx->getObject('modUserSetting', $fields);
if ($setting) {
    $setting->set('value', $value);
    $setting->save();
} else {
    $modx->log(modX::LOG_LEVEL_ERROR, 'Setting ' . $settingKey .
        ' not found for user ' . $userId);
}

Creating While Setting

To avoid using the utility snippet we saw earlier in this article, we can borrow some code from it and just create the setting if it doesn't exist, then set its value:

$settingKey = 'setting_one';
$value = 'some value';
$userId = $modx->user->get('id');
// or, for another user: $userId = 12;

$fields = array(
    'user' => $userId,
    'key' => $settingKey,
);

$setting = $modx->getObject('modUserSetting', $fields);

if (! $setting) { // we have to create it
    $fields => array(
        'name' = 'Setting One',
        'key'  => $settingKey,
        'user' => $userId,
        'description' => 'This is setting one',
        'namespace' => 'core',
        'value' => $value,
        'xtype' => 'textfield',
    );

    $setting = $modx->newObject('modUserSetting');
    $setting->fromArray($fields, "", false, true);
}

$setting->set('value', $value);
$setting->save();

/* Make the setting available immediately */
$modx->reloadConfig();

Getting the Value

Since MODX loads the User Settings for the current user, once the user is logged in you can always get the setting value with a setting tag, using the key (*not* the name) of the setting:

[[++setting_one]]

To pass a setting value set in one snippet to another, you can set a snippet property using the setting tag:

[[!Snippet2? &settingValue=`[[++setting_one]]` ]]

This is seldom done, however, because it's faster and more convenient to get the value for the current user with $modx->getOption():

$settingValue = $modx->getOption('setting_one', null, 'default value', true);

Coming Up

In the next article, we'll look at passing user-specific data to another snippet using a custom database table, which will persist across different visits to the site.



Looking for high-quality, MODX-friendly hosting? As of May 2016, Bob's Guides is hosted at A2 hosting. (More information in the box below.)



Comments (0)


Please login to comment.

  (Login)