Laravel makes emailing a breeze with its own API that builds on the SwiftMailer package. If you’re just starting to dive into Laravel and haven’t sent emails yet, please refer to the documentation or this great tutorial first.
What is a mailer “service”? In this case, the term “service” simply means a class — or a series of classes — that manages the logic for a specific action or series of actions. That means a mailer service allows us to abstract all the email logic away from the controllers and models, each of which (arguably) shouldn’t be handling how an email is sent in the first place.
Let’s say we want to notify a user that they have upgraded their membership. Using Laravel’s
Mail::send() method out-of-the-box, we might do it like:
Dropping this into your controllers and/or models wherever it’s needed will work just fine; however, as your application grows and scalability becomes more of a concern, it becomes difficult to manage and maintain all the different email requests hard-coded throughout your project. By creating your own mailer service,
Mail::send() will only ever have to appear in your codebase once. For those who cry, “Black magic!”, read on.
The parent class.
Creating a “services” folder is the starting point. A conventional directory structure would be something like:
app/project_name/services/mailers/Mailer.php. Once the folders are in place, we can create the parent abstract class,
Mailer.php. Within it, we need to drop in
Mail::send(), wrapping it in a method that can be called by any child class. Lets call it
Look at how flexible
emailTo() is. To illustrate, we’ll create a
UserMailer class which will hold all the functionality needed for emailing the user. Let’s add two in our example:
No matter what kind of email we need to send the user, we simply just swap out the variables to create a new method and call it from anywhere in our application. One clean, simple line of code is all it takes. Now we’re ready to send an email through the controller. What’s the best way to do that?
Dependency injection, more or less, allows us to give a class its required objects or instance variables (dependencies) without the class instantiating and hard-coding them itself. Below is a simple example of it in action. In this case, the class is the
UsersController and its dependency is
UserMailer. We pass an instance of
UserMailer into the
UsersController through the constructor, or, injecting its dependency. Note the type-hinting of
Once it’s been instantiated through the constructor, we just call
$this->mail->upgrade(), for example, to send off the notification email that the user’s account has been upgraded. Here the instance is named
$this->mail->upgrade() is slightly more readable than
$this->UserMailer->upgrade), but it really just comes down to personal preference.
Why is this better?
“Better” is subjective, but it’s hard to argue against the benefits. Many of the reasons are outside the scope of this particular discussion, such as adherence to S.O.L.I.D. principles. Some aspects, though, should hopefully be clear. Our code is much less muddy and easier to read, with emails being sent off with a single line of code. And swapping out functionality of any
Mailer method is all done in one place now, making our app easier to maintain and scale up or down.