Laravel11でメール送信処理を書く
2024.08.13 09:00
2024.08.13 09:22

Laravel11とMailableでフォーム送信処理を書いてみました。
今回はお問い合わせフォームを作る想定でやってみます。
ファイル構成はこんな感じ。
今回はメール送信処理なので、入力画面と完了画面は省略します。
|-/
|-app/
|-Http/
|-Controllers/
|-ContactController.php
|-Requests/
|-Contact/
|-SendRequest.php
|-UseCases/
|-Contact/
|-SendUseCase.php
|-Models/
|-Contact/
|-MailForAdmin.php
|-MailForCustomer.php
|-resources/
|-views/
|-contact/
|-index.blade.php
|-mail_admin.blade.php
|-mail_customer.blade.php
|-comp.blade.php
|-routes
|-web.php
処理によってリクエストやユースケース、ドメインにそれぞれ分けています。
最初にroutes.php。
<?php
use Illuminate\Support\Facades\Route;
$namespace = '\App\Http\Controllers';
Route::get('/contact', $namespace . '\ContactController@index').name('contact.index');
Route::post('/contact', $namespace . '\ContactController@send').name('contact.send');
Route::get('/contact_comp', $namespace . '\ContactController@comp').name('contact.comp');
次にContactController.php。
<?php declare(strict_types=1);
namespace app\Http\Controllers;
use Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\View\View;
use app\Http\Requests\Contact\SendRequest;
use app\Http\UseCases\Contact\SendUseCase;
class ContactController extends Controller
{
public function index(): View
{
// ビューに変数セットして表示
return view('general::contact.index.contents');
}
/**
* @param SendRequest $request
* @param SendUseCase $useCase
* @return RedirectResponse
*/
public function send(SendRequest $request, SendUseCase $useCase): RedirectResponse
{
// 二重送信防止
$request->session()->regenerateToken();
// 登録・メール送信処理
$useCase($request);
// 完了画面へ移動
return redirect(route('contact.comp'));
}
/**
* @return View
*/
public function comp(): View
{
// ビューに変数セットして表示
return view('general::contact.comp.contents');
}
}
コントローラーは処理の割り振りに特化しています。
次にリクエスト。
<?php declare(strict_types=1);
namespace app\Http\Requests\Contact;
use Illuminate\Foundation\Http\FormRequest;
class SendRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => 'required|string|max:255',
'email' => 'required|email|string',
'msg' => 'required|string',
'g-recaptcha-response' => 'required|recaptchav3:contact,0.5'
];
}
/**
* Set custom messages for validator errors.
*
* @return array
*/
public function messages()
{
return [
'name.required' => ':attributeは必須です',
'email.required' => ':attributeは必須です',
'email.email' => ':attributeの型が正しくありません',
'msg.required' => ':attributeは必須です',
'g-recaptcha-response.required' => '処理ができませんでした',
'g-recaptcha-response.recaptcha' => '処理ができませんでした.',
];
}
/**
* Set custom attributes for validator errors.
*
* @return array
*/
public function attributes()
{
return [
'name' => 'お名前',
'email' => 'メールアドレス',
'msg' => 'お問い合わせ内容',
'validation.recaptchav3' => '投稿スコア',
];
}
}
POSTされたデータをチェックします。
データにはGoogleReCAPTCHAのチェックも入れている他、
コントローラーで二重投稿防止の役目も果たしています。
次にユースケース。
<?php declare(strict_types=1);
namespace app\Http\UseCases\Contact;
use app\Models\Contact\Contact;
use app\Models\Contact\MailForAdmin;
use app\Models\Contact\MailForCustomer;
use app\Http\Requests\Contact\SendRequest;
use Illuminate\Support\Facades\Mail;
class SendUseCase
{
/**
* @var SendRequest
*/
private SendRequest $request;
/**
* @param SendRequest $request
* @return bool
*/
public function __invoke(SendRequest $request): bool
{
// データをドメインオブジェクトにして返す
$contact = new Contact($request->all());
// メールを送信する
try {
// 管理者に送る
Mail::send(new MailForAdmin($contact));
// ユーザーにレシートメールを送る
Mail::send(new MailForCustomer($contact));
// 処理完了でtrueを返す
return true;
} catch (\Exception $e) {
// エラーがあればログを書き込む
Logger($e->getMessage());
// エラー処理をここに書きます。
}
}
}
ユースケースは実際のお問い合わせ処理の流れを書いています。
コントローラーに実際の処理を書かせないためにユースケースに切り出しています。
次にモデルです。送信するメールを作成するモデルを2つ作成します。
まずは管理者用。
<?php
namespace app\Models\Contact;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class MailForAdmin extends Mailable
{
use Queueable, SerializesModels;
// 引数で受け取ったデータ用の変数
protected Array $data;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct(array $data)
{
$this->data = $contact;
}
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
$sendToAddress = '送信先の管理者用アドレスを入れます';
$fromName = $this->data['name'];
$fromAddress = '送信元のアドレスを入れます';
return new Envelope(
// 送信元のメールアドレスを指定
from: new Address($fromAddress, $fromName),
// 送信先のメールアドレスを指定
to: $sendToAddress,
// 返信時のメールアドレスを指定
replyTo: [
new Address($fromAddress, $fromName),
],
// 件名を指定
subject: 'お問い合わせを受け付けました',
);
}
/**
* Get the attachments for the message.
*
* @return array
*/
public function attachments(): array
{
return [];
}
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
// メールに使うviewを指定
text: 'contact.send.mail_admin',
// viewに入れるデータを指定
with: [
'data' => [
'name' => $this->data['name'],
'email' => $this->data['name'],
'msg' => $this->data['name'],
]
]
);
}
}
次にユーザー用。
<?php
namespace app\Models\Contact;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class MailForCustomer extends Mailable
{
use Queueable, SerializesModels;
// 引数で受け取ったデータ用の変数
protected Array $data;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct(Contact $contact)
{
$this->data = $contact;
}
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
$sendToAddress = $this->data['email'];
$fromName = $this->data['name'];
$fromAddress = '送信元のアドレスを入れます';
return new Envelope(
// 送信元のメールアドレスを指定
from: new Address($fromAddress, $fromName),
// 送信先のメールアドレスを指定
to: $sendToAddress,
// 返信時のメールアドレスを指定
replyTo: [
new Address($fromAddress, $fromName),
],
// 件名を指定
subject: 'お問い合わせを受け付けました',
);
}
/**
* Get the attachments for the message.
*
* @return array
*/
public function attachments(): array
{
return [];
}
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
// メールに使うviewを指定
text: 'contact.send.mail_customer',
// viewに入れるデータを指定
with: [
'data' => [
'name' => $this->data['name'],
'email' => $this->data['name'],
'msg' => $this->data['name'],
]
]
);
}
}
それぞれ送り先や送信元、件名、送るメールの文面などをここで作っています。
次にメールの文面のviewです。
まずは管理者用。
━━━━━━━━━━━━━━━━━
お問い合わせを受信
━━━━━━━━━━━━━━━━━
受付日時 <?php echo date("Y年m月d日 H時i分") . "\n"?>
お名前
{{$data['name']}} 様
メールアドレス
{{$data['email']}}
お問い合わせ内容
{{$data['msg']}}
--------------------------
署名
--------------------------
次にユーザー用。
━━━━━━━━━━━━━━━━━
お問い合わせを受付しました
━━━━━━━━━━━━━━━━━
受付日時 <?php echo date("Y年m月d日 H時i分") . "\n"?>
お名前
{{$data['name']}} 様
メールアドレス
{{$data['email']}}
お問い合わせ内容
{{$data['msg']}}
--------------------------
署名
--------------------------
これで送信処理が完成しました。
ブロックごとに切り分けているので、改修もしやすいですね。
今回は以上です!