spatie / mailcoach-support

Questions and support for Mailcoach
https://mailcoach.app
31 stars 2 forks source link

PR Proposal: Add mailable_arguments to the Campaign model #154

Closed jbraband closed 4 years ago

jbraband commented 4 years ago

My thinking with this is to add a mailable_arguments column to mailcoach_campaigns database table. It'll be the json datatype.

Campaign::useMailable() becomes this

public function useMailable(string $mailableClass, array $mailableArguments = []): self
  {
      $this->ensureUpdatable();

      if (! is_a($mailableClass, CampaignMail::class, true)) {
          throw CouldNotSendCampaign::invalidMailableClass($this, $mailableClass);
      }

      $this->update(['mailable_class' => $mailableClass, 'mailable_arguments' => $mailableArguments]);

      return $this;
  }

Campaign::getMailable() becomes this

public function getMailable(): CampaignMail
  {
    $mailableClass = $this->mailable_class ?? CampaignMail::class;

    $mailableArguments = $this->mailable_arguments ?? [];

      return app($mailableClass, $mailableArguments);
  }

CampaignMail would need a constructor to take the arguments array and set it to a protected property. Now the build() method of our custom mailables have arguments injected into it from the Campaign.

I'm willing to put this together. I need this functionality and I think it makes sense to allow custom mailables to be parameterized from the developer's application.

my use case for parameterized Mailables is a campaign that sends emails about one specific article on our website. That article's id would be passed as an argument in this manner:

$campaign->useMailable(MyCustomMailable::class, ['article_id' => $article_id]);

Any modifications to this idea before I get to work on it?

jbraband commented 4 years ago

PR is submitted. I'm more than willing to help refine it!

https://github.com/spatie/laravel-mailcoach/pull/217

jbraband commented 4 years ago

Here is how that is used. A sample custom Mailable:

<?php

namespace App\Mails;

use Illuminate\Queue\SerializesModels;

use Spatie\Mailcoach\Mails\CampaignMail;

class SingleArticle extends CampaignMail
{
    use SerializesModels;

    protected int $article_id;

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

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
      $article = code_fetch_article_data($this->article_id);

      return $this->view('single-article', compact('article'));
    }
}

And this code to build the campaign and pass the Mailable and arguments:

$campaign = Campaign::create()
                       ->useMailable(SingleArticle::class, ['article_id' => 1000]);
freekmurze commented 4 years ago

We'll merge the PR when we'll start working on v3 in a couple of months.