Mailchimp Integration with FOSUserBundle Events


In this video we are going to use events that are generated throughout the lifecycle of a FOSUserBundle action to do interesting things inside our application.

In particular, we will be listening for a specific event - REGISTRATION_COMPLETED - and then creating an Event Listener which receives the event, and signs up the new User to our Mailchimp mailing list.

For reference, here is a complete list of all the events that are generated at various stages by FOSUserBundle. We are going to listen for this one:

    /**
     * The REGISTRATION_COMPLETED event occurs after saving the user in the registration process.
     *
     * This event allows you to access the response which will be sent.
     * The event listener method receives a FOS\UserBundle\Event\FilterUserResponseEvent instance.
     */
    const REGISTRATION_COMPLETED = 'fos_user.registration.completed';

The constant REGISTRATION_COMPLETED makes it easy for us to reference this particular event in our code. However, in the listener's service definition (info below), we will need the string - 'fos_user.registration.completed'.

To make this video as short as possible, I decided to use a third party bundle to interact with the Mailchimp API. The bundle I am using is rezzza/mailchimp which I found simply by searching Packagist for 'symfony mailchimp'.

Unfortunately, there is little in the way of documentation for this bundle. In the video I demonstrate how I figured out what was happening but largely it was just trial and error. The bundle apparently defers documentation to the Mailchimp API docs.

Update: April 2017 - This bundle is no longer maintained. The recommended alternative is to directly use the official Mailchimp API library.

That said, the bundle does the job and it didn't take too long to get up and running.

Getting Started

If you wish to follow along, I am not going to cover setting up bundle (as it is the same process as every other Symfony bundle) aside from the config I had to use inside config.yml:

# app/config/config.yml

rezzza_mail_chimp:
    # Your MailChimp API Key
    api_key:              5d56cf420f50ce2f5cc36a0364cac921-us8
    # Supported connections : http, https, stub
    connection:           rezzza.mail_chimp.connection.https

I have killed that API key. You will need to generate your own.

Make sure you have added the bundle into AppKernel.php also.

That's pretty much it for the config, nice and easy.

The Event

The event we are interested in happens just before the very end of the FOSUserBundle Registration action:

    $dispatcher->dispatch(
      FOSUserEvents::REGISTRATION_COMPLETED, 
      new FilterUserResponseEvent($user, $request, $response)
    );

I've changed the formatting slightly so it is easier to read.

Here you can see two things. Something interesting has just happened - a User has successfully completed the registration process.

We haven't yet registered our event listener, but you can see the constant we discussed earlier is being passed in to the event dispatcher as the first argument.

Any listeners registered / configured to listen for this event will shortly be getting sent something... but what will they receive?

They will receive the second parameter: new FilterUserResponseEvent($user, $request, $response).

Knowing this, we can type hint our own listener action (see below) to match this object (FilterUserResponseEvent) and immediately gain access to the User, and the Request and Response objects.

Ultimately, we don't need the Request or the Response, but you might, depending on what you are aiming to achieve.

As soon as this line is processed, the event will be dispatched / sent out.

Of course, we haven't yet registered a listener to hear about this event. So let's sort that out right now.

The Listener

We have already covered using Event Listeners in this very series. The good news is, this is going to use exactly the same syntax.

# app/config/services.yml

registration_mailing_listener:
    class: AppBundle\Event\RegistrationMailingListener
    arguments:
        - @rezzza.mail_chimp.client
    tags:
        - { name: kernel.event_listener, event: fos_user.registration.completed, method: onRegistrationCompleted }

If unsure of any of this, please watch the video

With this as our service definition, we can now go ahead and create the associated class:

<?php

// src/AppBundle/Event/RegistrationMailingListener.php

namespace AppBundle\Event;

use FOS\UserBundle\Event\FilterUserResponseEvent;
use Rezzza\MailChimpBundle\Api\Client;

class RegistrationMailingListener
{
    /**
     * @var Client
     */
    private $client;

    public function __construct(Client $client)
    {
        $this->client = $client;
    }

    public function onRegistrationCompleted(FilterUserResponseEvent $event)
    {
        $user = $event->getUser();

        $response = $this->client->getMailChimpLists()->subscribe('your-list-id', [
            'email' => $user->getEmail(),
        ]);

//        exit(dump($response));
    }
}

The mailing list ID is unfortunately not immediately obvious. Use the docs if struggling to find yours, or see how I do it in the video.

Also, the second parameter to subscribe requires an array that took me a while to figure out the format. The docs helped here also, but their use of struct threw me.

The gist of this is that we are taking the newly registered user's User object, pulling their given email address from that object, and sending that off to our Mailchimp email list ID as a newly registered user of that list.

This won't happen immediately.

You will need to wait for the user to accept being opted in to your mailing list. Surely though, as a new subscriber to your site, this should be a done deal. If you really don't want to mess with the double opt-in, you can specify double opt-in as false as one of the parameters to subscribe. See the video for a better example.

Code For This Course

Get the code for this course.

Episodes