Managing users and mailing lists are not a that painful nowadays. Since we have excellent services that can cover all the needs we have, we don’t need to worry about it too much. But still, let’s take a look at how can we handle user subscriptions when Laravel fires different events.
Getting Started
First of all, we must clarify that the way we present the solutions is not GDPR compatible. The users have to confirm any actions when their data is getting processed. Just keep it in mind.
Also, if you need a fully working solution for your newsletters, you may use the Spatie package.
But for now, let’s say, we want to subscribe a user to the mailing list when it registers to the site. By default, Laravel fires the Illuminate\Auth\Events\Registered event when a user registers to our application. It means, writing a listener to this event would be enough to handle the subscription. Then, let’s move on and make that listener!
Making and Registering the Listener
With the help of the php artisan make:listener command we can easily create the event listener. Let’s name it to SubscribeUser.
Before we write the logic, we need to register the listener for the event we mentioned before. In the EventServiceProvider‘s $listen property we can pair them easily.
protected $listen = [ // ... \Illuminate\Auth\Events\Registered::class => [ \App\Listeners\SubscribeUser::class, ], // ... ];
Now whenever the registered event is being fired, we can listen to it with our listener.
Handling the Subscription in the Listener
MailChimp has a nice documentation of its API. Currently, we need the members API because we only want to subscribe a user to the list. As we see, we need to send a POST request to the given endpoint with the required credentials.
For the POST request, we will use Guzzle. We can install it with the composer require guzzlehttp/guzzle command. After it’s done we need to grab all the credentials we need: username, API key, list ID. Since the API key contains the data center we use, we can use the key to grab that information.
So, we prepared everything, now let’s see the code itself:
<?php namespace App\Listeners; use GuzzleHttp\Client; use Illuminate\Queue\InteractsWithQueue; use GuzzleHttp\Exception\ClientException; use Illuminate\Contracts\Queue\ShouldQueue; class SubscribeUser implements ShouldQueue { use InteractsWithQueue; protected $client; protected $list; protected $dc; protected $token; /** * Create the event listener. * * @return void */ public function __construct() { $this->client = new Client; $this->list = config('services.mailchimp.list'); $this->dc = collect(explode('-', config('services.mailchimp.key')))->last(); $this->token = base64_encode(sprintf('%s:%s', config('services.mailchimp.user'), config('services.mailchimp.key'))); } /** * Handle the event. * * @param \Illuminate\Auth\Events\Registered $event * @return void */ public function handle(Registered $event) { try { $this->client->post("https://{$this->dc}.api.mailchimp.com/3.0/lists/{$this->list}/members", [ 'headers' => [ 'Authorization' => "Basic {$this->token}", 'Content-type' => 'application/json', ], 'json' => [ 'status' => 'subscribed', 'email_address' => $event->user->email, 'merge_fields' => ['FNAME' => $event->user->name, 'LNAME' => ''], ], ]); } catch (ClientException $e) { // Handle errors } } }
So what happens here? In the constructor, we initialize a new Client instance. We will use this to send the POST request to the endpoint. Also, we grab the list ID from the config. Then we extract the data center (dc) from the API key.
Then we need to set the token we want to send in the header. As you see, it’s the base64 encoded format of the username + “:” + API key.
After we done with setting up the credentials, we can move on the handle method. We put the whole code in a try-catch block, in case we want to handle the errors. Then with the client, we send the request to the endpoint with the requested body and headers.
If the request succeeded, we can see the user as a subscribed member in our MailChimp dashboard.
Summary
It’s nice how easily can we perform actions like this. Of course in real life, we need a bigger thing (like the package above) to fully handle the needs. But it’s a nice example that we can easily integrate services with Laravel.