Avoid Trashing Properties with setProperties()

Suppose that you want to change the value of a single property of a MODX element (usually a snippet) in code. There is no setProperty() method, but you would expect this code to do the job:

<?php
/* Don't use this code! */
$props = $snippet->getProperties();
$props['someKey'] = 'someValue';
$snippet->setProperties($props);

It looks innocent enough but it will trash all the properties of the snippet (including the one you’re trying to set).

Why?

The problem is that the modElement class’s getProperties() and setProperties() methods are not symmetrical. The getProperties() method gets only the name (key) and value fields. Usually, that’s all you want, but there are a number of other fields such as the description, lexicon, and type field, which getProperties() does not retrieve. The setProperties() method, on the other hand, sets *all* the fields of each property from the array you send it. If they are missing from the array you send, they will either be saved blank or set to their default values. Worse yet, you can’t send them because you don’t have them.

The type field, for example defaults to textfield, so with the code above, every property of the snippet will have its type field set to textfield, including any Yes/No or List properties. Those properties will no longer work as expected in MODX.

Even if your property is the only one the snippet has and it’s a textfield property, the code above will still cause problems because the description, lexicon, and area fields will be saved blank.

The Solution

Preventing this disaster is easy enough. You just need to send a second argument to the setProperties() method.

<?php
/* This code is fine */
$props = $snippet->getProperties();
$props['someKey'] = 'someValue';
$snippet->setProperties($props, true);

Sending true as the second argument in the setProperties() call tells MODX to merge the properties you are sending with the existing ones. That will prevent any of the current values from being trashed. It’s easy to do, but also easy to forget.

What About Using get(‘properties’)?

You can also solve the problem by using get('properties') instead of getProperties(), but it’s a little less convenient. When you call get('properties'), MODX returns an array of arrays rather than a simple array of keys and values. With getProperties(), you get an array like this:

array(
    'name1' => 'value1',
    'name2' => 'value2,
}

With get('properties'), you get an array like this:

array {
    'name1' = array(
        'name' => 'name1'
        'value' => 'value1',
        /* more fields here */
    ),
    'name2' = array(
        'name' => 'name1'
        'value' => 'value1',
        /* more fields here */
    ),
)

Since each array member is a property with an array of fields, using get('properties') means that setting the value requires code like this:

$props['name1']['value'] = 'someValue'

Since you seldom want to set any field other than the value field, it’s usually easier just to use getProperties() and setProperties($properties, true).


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

I am the author of MODX: The Official Guide and over 30 MODX add-on components. I host Bob's Guides, a source of valuable information for MODX users, and I've been very active in the MODX Forums with over 14,000 posts.

Leave a Reply

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


8 − 1 =

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>