dmytroshved's avatar

Mailchimp: Where is the proper place to put the code to add a user to a list?

Hello

I am working with MailChimp API for adding users to list using form in my website's footer

Code works and after submitting the form user see's that he needs to verify their email through E-mail message

But I have this code inside NewsletterController and I am getting email from user from Request

My question is: Should I move this code to another place of my app? And where would you place that code

Would be grateful for your advices

0 likes
6 replies
martinbean's avatar
Level 80

@dmytro_shved When I’ve implemented this in the past, I’ve created a SubscriberService interface, and then classes that implement that interface, such as MailchimpSubscriberService. This makes it easier to swap out with say, a Campaign Monitor implementation.

The implementation would look something like this:

class MailchimpSubscriberService implements SubscriberService
{
    protected ApiClient $client;

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

    public function subscribe(string $listId, string $email): bool
    {
        $hash = md5(strtolower($email));

        $this->client->lists->setListMember($listId, $hash, [
            'email_address' => $email,
            'status_if_new' => 'pending',
        ]);

        return true;
    }
}

You can register the Mailchimp API client with the service container, so that you don‘t have to manually instantiate it and manually pass configuration values, each and every time you want to use it throughout your application:

class AppServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->singleton(ApiClient::class, function () {
            $client = new ApiClient();

            return $client->setConfig([
                'apiKey' => $this->app->make('config')->get('services.mailchimp.api_key'),
                'server' => $this->app->make('config')->get('services.mailchimp.server_prefix'),
            ]);
        });
    }
}

You should also bind your implementation to the interface in a service provider:

$this->app->singleton(SubscriptionService::class, MailchimpSubscriptionService::class);

Laravel will now resolve the bound implementation if you type-hint the interface (such as a controller). If it resolves the Mailchimp implementation, it will also see that it has a dependency on the ApiClient class, so will then resolve that via the container and inject it. That means using it in a controller looks like this:

class NewsletterSubscriptionController extends Controller
{
    protected SubscriptionService $subscriptionService;

    public function __construct(SubscriptionService $subscriptionService)
    {
        $this->subscriptionService = $subscriptionService;
    }

    public function store(StoreSubscriptionRequest $request)
    {
        $this->subscriptionService->subscribe($request->input('email'));

        // Return response...
    }
}

You’re now relying only on interfaces, and no longer having to manually instantiate API clients or other classes.

I’ve created a Gist with an example implementation: https://gist.github.com/martinbean/be48e0ec37ba59a05e52b936a5721023

1 like
martinbean's avatar

@Dmytro_Shved I tried, but the “edit” option has disappeared for me. I guess an answer can’t be edited once it’s been accepted.

Please or to participate in this conversation.