So, it was just a simple thing…

All my client wanted to know was the date that users were subscribing or unsubscribing to newsletters in Magento.

Magento Observers - Fix all the things

Fix All The (Magento) Things

I dove into the database to see if the newsletter subscription table had some sort of updated_at field, and there it was – change_status_at. At first I was joyful, and then I was annoyed when I saw that the field always contained NULL — the absence of happiness.

I jumped screens and used the power of Goooogle to divine an answer from the Internets. But instead of an answer, I soon found that others had run into this very issue and went away empty handed.

Digging deeper into stackoverflow, there were those who claimed that –

“it used to work, in very old versions of Magento, but doesn’t anymore”.

At a guess, I think what happened is that the table’s definition used to be setup to automagically update this field as the default timestamp on the table row (i.e. ON UPDATE CURRENT_TIMESTAMP). But somewhere, lost in a long forgotten Magento update, that setting was dropped. So, in the end, there’s no Magento code that updates this field because “It didn’t have to.”

So, I put down my beer and put on my trusty Magento Certified Developer’s thinking cap and bashed out a quick module that solves the problem by observing changes to the mystical event newsletter_subscriber_save_before and provides the missing date. It won’t bring back any data from previous users, but my client will be able to monitor newsletter activity from now on. Best of all, I was able to get back to my beer before the junior programmers got to it.

Now, I’m here to share this solution with those in the Mage Multiverse ™ who might find need of it.

Install this little gem and you can take catnaps peacefully, knowing that you now have the time and date when someone subscribed (or unsubscribed) to your site’s newsletter.

This module can be installed from Magento connect.  This module is “production ready” code and is free for you to use, but is not supported.

Behind the Scenes

Here’s the meat of what needed to be done.

Magento has a special programming pattern built into it called an “Event Observer.” This pattern allows a programmer to add in customizations to how other objects work without modifying the core object.  We’re solving the problem outlined above by adding in an observer that is activated just before the member subscription is saved to the database.

There are many observable events in the magento framework, I won’t list them here, but you should be able to easily search for them. What I’ll cover here are some very basic ones that every object model in Magento stored to the database has available (OK – there are some exceptions, but don’t worry about those now).

These are –

  • <model>_load_before
  • <model>_load_after
  • <model>_save_before
  • <model>_save_after
  • <model>_save_commit_after
  • <model>_delete_before
  • <model>_delete_after
  • <model>_delete_commit_after
  • <model>_clear

The event names are pretty self-explanatory and as just as the names indicate, these events are triggered (or fired) before and after the data is loaded, saved, deleted or destroyed.

To add an observer, edit to your module’s config.xml file in the global section, add an event node for an event, in this case – newsletter_subscriber_save_before.

[xml]
<events>
<newsletter_subscriber_save_before>
<observers>
<subscribefix_observer_subscriber>
<type>singleton</type>
<class>HE_SubscribeFix_Model_Observer</class>
<method>setUpdateDate</method>
</subscribefix_observer_subscriber>
</observers>
</newsletter_subscriber_save_before>
</events>
[/xml]

This tells Magento that just before the newsletter_subscriber model is saved to the database, call the method setUpdateDate in the class HE_SubscribeFix_Model_Observer.

The setUpdateDate method takes the model data that was about to be saved and sets the change_status_at property to the current date and time.  When that’s done, control is passed back to the regularly scheduled program and the model is saved to the database.

[php]
class HE_SubscribeFix_Model_Observer
{
/**
* Observer function to update the subscription action date
* @param Varien_Event_Observer $observer
*/
public function setUpdateDate(Varien_Event_Observer $observer)
{
$subscriber = $observer->getSubscriber();
$subscriber[‘change_status_at’] = date(“Y-m-d H:i:s”, time());
}
}
[/php]

Because this method does not add any new data (change_status_at already existed by was being ignored), no changes need to be made to any other code or to the database.

If you’re still working through how to create a module, you can download the code for this one and take a quick walk-through. It’s a clear and very simple example of how to set up a Magento observer that updates an object before it gets saved to the database

Simple, eh?  Hope you found this interesting and helps you understand Magento a little bit more.