エンジニ屋.com(エンジニヤドットコム)

日々得たWebエンジニアに関する情報をアウトプットしてます!

【Laravel8】お問い合わせフォームの作り方 メール送信まで解説

Laravel8では7と比べ若干の仕様の違いで、今まで通りにコードを書くとエラーが発生します。 本記事では、Laravel8でのお問い合わせフォームの作成方法をまとめました。

作成ページ

  • トップページ
  • フォーム確認画面
  • メール送信機能
  • 送信完了ページ
    これらを作成していきます。

開発環境

  • Laravel8

ルーティングを作成

web.phpにルーティングを作成します。
トップページのルートから順を追って解説していきたいと思います。
routes/web.php

<?php

use App\Http\Controllers\ContactController;

//トップページ
Route::get('/',[ContactController::class, 'index'])->name('index');

Controller内でurl('index')で遷移出来るようにname()もあらかじめ定義しています。 Laravel8ではControllerクラスをuseで呼び出す必要があります。

コントローラを作成

次にContactController.phpを作成していきます。 コマンドで'php artisan make controller ContactController'を実行します。
App\Http\Controllers\ContactController

<?php

namespace App\Http\Controllers;

class ContactController extends Controller
{
    public function index()
    {
        return view('top');
    }
}

トップページを表示させるだけなので、非常にシンプルです。

トップページを作成

twigを作成します。 ※入力項目部分のみ抜き出して記述しています。実際の開発では、他の箇所もそうですが、追加の項目やhtmlタグの追加などして見た目を整えて下さい。
resources/views/top.blade.php

<form method="POST" action="{{ route('confirm') }}" >
    @csrf
    @method('POST')
    <div class="form-inner">
        <div class="form-cont">
            <div class="mg-b_40">
                <label for="name" class="required-tag">担当者名</label><br>
                <input type="text" placeholder="山田太郎" id="name" name="name" value="{{ old('name') }}">
                @if($errors->has('name'))
                  <p class="required">{{ $errors->first('name') }}</p>
                @endif
            </div>
            <div class="mg-b_40">
                <label for="cname" class="required-tag">フリガナ</label><br>
                <input type="text" placeholder="ヤマダタロウ" id="cname" name="cname" value="{{ old('cname') }}">
                @if($errors->has('cname'))
                  <p class="required">{{ $errors->first('cname') }}</p>
                @endif
            </div>
            <div class="mg-b_40">
                <label for="tel" class="required-tag">電話番号</label><br>
                <input type="tel" placeholder="0123456789" id="tel" name="tel" value="{{ old('tel') }}">
                @if($errors->has('tel'))
                  <p class="required">{{ $errors->first('tel') }}</p>
                @endif
            </div>
            <div class="mg-b_40">
                <label for="email" class="required-tag lg-label">メールアドレス</label><br>
                <input type="email" placeholder="sample@example.com" id="mail" name="email" class="mg-b_10" value="{{ old('email') }}">
                <input type="email" placeholder="確認のため再度入力してください" id="mail" name="email_confirmation">
                @if($errors->has('email'))
                  <p class="required">{{ $errors->first('email') }}</p>
                @endif
                @if($errors->has('email2'))
                  <p class="required">{{ $errors->first('email2') }}</p>
                @endif
            </div>
            <div class="mg-b_40">
                <label for="content" class="lg-label">お問い合わせ内容</label><br>
                <textarea name="content" id="content" cols="30" rows="10" placeholder="Message">{{ old('content') }}</textarea>
            </div>
        </div>
    </div>

route(confirm)でフォームの内容がrouteへ遷移するよう定義しています。 value="{{ old('name') }}"では、エラーが返った時に値は入力されたままになるように定義してます。 @if($errors->has('name'))…の部分では、エラーが返ってきたときに、エラー文を表示させるためです。

web.phpにconfirm を追加

routes/web.php

//確認ページ
Route::get('/confirm',[CotactController::class, 'confirm']);
Route::post('/confirm',[CotactController::class, 'confirm'])->name('confirm');

confirmメソッドをController内で作成

App\Http\Controllers\ContactController.php

//17:
 public function confirm(Request $request)
    {

      $inputs = $request->all();

        if(!$inputs){
            return redirect()->route('index');
        }

        $request->validate([
           'name' => 'required',
            'cname' => 'required',
            'tel' => ['required', 'numeric', 'digits_between:8,11'],
            'email' => ['required','email','confirmed'],
            'messgae' => 'max:4000'
        ]);

        return view('confirm',[
            'inputs' => $inputs,
        ]);
    }

20行目から解説すると、postで渡されたdataを$request->all()で取得して$inputsの格納しています。22行目で、もし$inputsに値が格納されていなければ、indexにリダイレクトさせます。例えば、直接、confirmのurlにアクセスされた場合があるのでこのような記述をしています。 26行目からそれぞれの項目にバリデーションを行っています。 もしバリデーションに引っかかった場合は、エラーを返します。

confirmページを作成

resources/view/confirm.blade.php

<form method="POST" action="{{ route('send') }}" class="confirm__ar">
    {{ csrf_field() }}
    {{ method_field('POST') }}
      <dt class="confirm__tag">担当者名</dt>
      <dd>{{ $inputs['name'] }}</dd>
      <input type="hidden" name="name" value="{{ $inputs['name'] }}">
    </dl>
    <dl>
      <dt class="confirm__tag">フリガナ</dt>
      <dd>{{ $inputs['cname'] }}</dd>
      <input type="hidden" name="cname" value="{{ $inputs['cname'] }}">
    </dl>
    <dl>
      <dt class="confirm__tag">電話番号</dt>
      <dd>{{ $inputs['tel'] }}</dd>
      <input type="hidden" name="tel" value="{{ $inputs['tel'] }}">
    </dl>
    <dl>
      <dt class="confirm__tag">メールアドレス</dt>
      <dd>{{ $inputs['email'] }}</dd>
      <input type="hidden" name="email" value="{{ $inputs['email'] }}">
  </dl>
    <dl>
      <dt class="confirm__tag">お問い合わせ内容</dt>
      <dd>
        {!! nl2br(e($inputs['content'])) !!}
        <input type="hidden" name="content" value="{{ $inputs['content'] }}">
      </dd>
    </dl>

    <div class="confirm_bk">
      <a href="{{ route('index') }}" class="back_btn"><span class="f-bold">戻る</span></a>
      <input onclick="submit();" type="button" value="この内容で送信する" class="confirm_btn">
    </div>
  </form>

formの部分のみ抜き出して記載しています。 それぞれの値を$input[name名]で呼び出して表示させてます。 inputタグでは、typeをhiddenにして表側では表示させずに、submitで入力の値を渡しています。routeは('send')を指定しているので、送信ボタンを押すとname('send')を通ります。

メール送信行うためのrouteを記述

//送信完了ページ
Route::get('/thanks',[CotactController::class, 'send']);
Route::post('/thanks',[ContactController::class, 'send'])->name('send');

Controllerにsendメソッドを作成

public function send(Request $request)
    {
        $inputs = $request->all();

        if(!$inputs){
            return redirect()->route('index');
        }

          \Mail::to($inputs['email'])->send(new ContactSendMail($inputs);

        $request->session()->regenerateToken(); //2回メール送信を防ぐため

        return view('thanks');
    }

最初の部分はconfirmと同じく、$inputsに全値を格納します。inputsに値が格納されていない場合は、トップページへリダイレクトします。

\Mailとあるのは、Laravelが提供しているメールを送信する為に必要なMailファサードです。\Mailで呼び出すことができます。因みに\Mailで呼び出すことができるのは、 configのディレクトリ内のapp.phpに274行目あたりに'Mail' => Illuminate\Support\Facades\Mail::class,とエイリアスが定義されているからです。 先ずは、to() の中に宛先のメールをアドレスを記述します。 フォームで入力されているアドレスを$input['email'] で取得します。 メールの内容は、Mailableクラスを使用します。 Controllerの5行目あたりにContactSendMailを使用できるようにuseを記述します。

use App\Mail\ContactSendMail;

ContacdtSendMail.phpを作成

php artisan make:mail ContacdtSendMailとコマンドを実行します。 app/Http/MailにContactSendMail.phpのファイルが作成されいるので、内容を下記のように変更します。

<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class ContactSendMail extends Mailable
{
    use Queueable, SerializesModels;

    private $name;
    private $cname;
    private $tel;
    private $emal;
    private $message;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct($inputs,$type)
    {
        $this->name  = $inputs['name'];
        $this->cname  = $inputs['cname'];
        $this->tel  = $inputs['tel'];
        $this->email = $inputs['email'];
        $this->content = $inputs['content'];
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this
            ->subject('お問い合わせありがとうございます')
            ->view('emails.urer')
            ->with([
                'name' => $this->name,
                'cname' => $this->cname,
                'tel' => $this->tel,
                'email' => $this->email,
                'content' => $this->content ? $this->content : null
        ]);
    }
}

$inputsに格納されている値をwith()で配列として値を渡します。

メールの内容をtwigで作成

resources/emails/user.blade.php

【このメールはシステムからの自動返信です。】<br>
<br>
<br>
{{ $name }} 様<br>
<br>
この度は、お問い合わせいただき、誠にありがとう御座います。<br>
お送り頂いた内容を確認の上、担当者より折り返しご連絡させていただきます。<br>
<br>
担当者名: {{ $name }}<br>
フリガナ: {{ $cname }}<br>
電話番号: {{ $tel }}<br>
メールアドレス: {{ $email }}<br>
お問い合わせ内容:<br>
{!! nl2br($content) !!}<br>
<br>

非常にシンプルですが、基本的な内容のメール文です。

最後にメール送信が完了したあとに送信完了ページを resources/emails/thanks.blade.phpで作成したら一連の流れは完了です。

以上となります。 途中でも説明もしていますが、CSSやhtmlタグやフォームの項目などは必要用途に応じて整えてください。

Have a development day!!