LoginSignup
0
2

More than 1 year has passed since last update.

【Laravel】お問い合わせフォーム【Sendgrid】

Last updated at Posted at 2022-06-08

0. はじめに

大阪のLaravel初学者サウナーこと、kazumakishimoto(@kazuma_dev)です!
SendgridでLaravelのお問い合わせフォームの作り方です!

0-1. 全体の流れ

1.Sendgrid
2.Laravel
補足
Reference

0-2. 本記事の対象者

  • SendgridでLaravelのお問い合わせフォームを作成したい方

0-3. 事前準備

  • Sendgridアカウント
  • Gmailアカウント

0-4. 要件

  • Sendgrid登録
  • Sendgridを.env記載
  • Laravel実装

0-5. 使用画像のイメージ

image.png
image.png
image.png
image.png

1. Sendgrid

  • 下記参考にAPIKEY作成(※編集中)

2. Laravel

2-1. .env

# Sendgrid
MAIL_DRIVER=smtp
MAIL_HOST=smtp.sendgrid.net
MAIL_PORT=587
MAIL_USERNAME=apikey
MAIL_PASSWORD=SG.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
MAIL_ENCRYPTION=tls
MAIL_FROM_NAME="${APP_NAME}"
MAIL_FROM_ADDRESS=hoge@gmail.com

2-2. Route

routes/web.php
# お問い合わせ
// 入力ページ
Route::get('/contact', 'ContactController@index')->name('contact.index');
// 確認ページ
Route::post('/contact/confirm', 'ContactController@confirm')->name('contact.confirm');
// 送信完了ページ
Route::post('/contact/thanks', 'ContactController@send')->name('contact.send');

2-3. Controller

app/Http/Controllers/ContactController.php
<?php

namespace App\Http\Controllers;

use App\Http\Requests\ContactRequest;
use App\Mail\ContactSendmail;

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

    public function confirm(ContactRequest $request)
    {
        $inputs = $request->all();

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

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

        if ($request->has("back")) {
            return redirect()->route('contact.index')
                ->withInput($inputs);
        }

        \Mail::to('grfl.official@gmail.com')->send(new ContactSendmail($inputs));
        $request->session()->regenerateToken();
        return view('contact.thanks');
    }
}

2-4. ContactRequest

app/Http/Requests/ContactRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class ContactRequest 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:15',
            'email' => 'required|email:strict,dns|max:255',
            'title' => 'nullable|string|max:255',
            'body'  => 'required|string|max:1000',
        ];
    }

    public function attributes()
    {
        return [
            'name' => 'お名前',
            'email' => 'メールアドレス',
            'title' => '件名',
            'body' => 'お問い合わせ内容',
        ];
    }
}

2-5. View

2-5-1. index.blade.php

resources/views/contact/index.blade.php
@extends('app')

@section('title', 'お問い合わせ - grfl')

@section('content')

@include('nav')
<header>
    <div>
        <div class="container" style="max-width: 900px;">
            <nav aria-label="breadcrumb">
                <ol class="breadcrumb bg-white small pl-0 mb-0">
                    <li class="breadcrumb-item">
                        <a href="/" class="text-teal1">grfl</a>
                    </li>
                    <li class="breadcrumb-item active" aria-current="page">
                        お問い合わせ
                    </li>
                </ol>
            </nav>
        </div>
    </div>
</header>

<main>
    <div class="bg-paper my-3">
        <div class="container p-0" style="max-width: 540px">
            <h4 class="text-center">
                    お問い合わせ
                </h4>
            <p style="font-size: 14px;">
                    grflに対するご意見ご感想お問い合わせなどございましたらお聞かせください<br>
                    お送りいただいた内容はすべて確認しておりますがご返信を差し上げることができない場合もございますのでご了承ください
                </p>
            @if (session('status'))
            <div class="card-text alert alert-success">
                {{ session('status') }}
            </div>
            @endif
            <div class="card shadow-sm mb-4">
                <div class="card-body">
                    @include('error_card_list')
                    <form method="post" action="{{ route('contact.confirm') }}">
                        @csrf
                        <p class="small">
                                (<span class="text-danger">*</span>は必須項目です)
                            </p>
                        <div class="form-group">
                            <label for="name">お名前</label>
                            <span class="text-danger">*</span>
                            <input class="form-control" type="text" id="name" name="name" required value="{{ Auth::user()->name ?? old('name') }}">
                        </div>
                        <div class="form-group">
                            <label for="email">メールアドレス</label>
                            <span class="text-danger">*</span>
                            <input class="form-control" type="email" id="email" name="email" required value="{{ Auth::user()->email ?? old('email') }}">
                        </div>
                        <div class="form-group">
                            <label for="title">ご用件</label>
                            <input class="form-control" type="title" id="title" name="title" value="{{ old('title') }}">
                        </div>
                        <div class="form-group">
                            <label for="body">お問い合わせ内容</label>
                            <span class="text-danger">*</span>
                            <textarea type="text" name="body" id="body" rows="5" class="form-control" required>{{ old('body') }}</textarea>
                            <p class="text-muted small ml-1">1000文字以内</p>
                        </div>
                        <label for="agree" class="small" role="button">
                            <span class="d-flex flex-wrap">
                                <span>
                                    <input type="checkbox" id="agree" required>
                                    <a href="{{ route('privacy') }}" class="text-teal1 ml-2" target="_blank" title="プライバシーポリシーをブラウザの別画面で開く">プライバシーポリシー</a>
                                    <span>を確認し</span>
                                </span>
                                <span>同意</span>
                                <span>
                                    <span>
                                        <span>しました</span><span class="text-danger">*</span>
                                    </span>
                                </span>
                            </span>
                        </label>
                        <button type="submit" class="btn btn-block bg-white btn-outline-teal1 text-decoration-none text-teal1 mt-4">
                            <b>送信内容を確認する</b>
                        </button>
                    </form>
                </div>
            </div>
        </div>
    </div>
</main>

@include('footer')

@endsection

2-5-2. confirm.blade.php

resources/views/contact/confirm.blade.php
@extends('app')

@section('title', 'お問い合わせ内容の確認 - grfl')

@section('content')

@include('nav')

<main>
    <div class="bg-paper my-3">
        <div class="container p-0" style="max-width: 540px">
            <h4 class="text-center">
                    お問い合わせ内容の確認
                </h4>
            <div class="card shadow-sm mb-4">
                <div class="card-body">
                    <form method="post" action="{{ route('contact.send') }}">
                        @csrf
                        <div class="form-group">
                            <label for="name" class="text-muted">
                                お名前
                            </label>
                            <p>
                                    {{ $inputs['name'] }}
                                </p>
                            <input name="name" value="{{ $inputs['name'] }}" type="hidden">
                        </div>
                        <div class="form-group">
                            <label for="email" class="text-muted">
                                メールアドレス
                            </label>
                            <p>
                                    {{ $inputs['email'] }}
                                </p>
                            <input name="email" value="{{ $inputs['email'] }}" type="hidden">
                        </div>
                        <div class="form-group">
                            <label for="title" class="text-muted">
                                ご用件
                            </label>
                            <p>
                                    @if ($inputs['title'] !== null)
                                        {{ $inputs['title'] }}
                                    @else
                                        無題
                                    @endif
                                </p>
                            <input name="title" value="{{ $inputs['title'] }}" type="hidden">
                        </div>
                        <div class="form-group">
                            <label for="body" class="text-muted">
                                お問い合わせ内容
                            </label>
                            <p>
                                    {!! nl2br(e($inputs['body'], false)) !!}
                                </p>
                            <input name="body" value="{{ $inputs['body'] }}" type="hidden">
                        </div>
                        <button type="submit" name="back" value="back" class="btn btn-block btn-teal1 mt-4">
                            入力内容修正
                        </button>
                        <button type="submit" name="action" value="submit" class="btn btn-block bg-white btn-outline-secondary text-decoration-none text-secondary mt-4">
                            送信する
                        </button>
                    </form>
                </div>
            </div>
        </div>
    </div>
</main>

@include('footer')

@endsection

2-5-3. thanks.blade.php

resources/views/contact/thanks.blade.php
@extends('app')

@section('title', 'お問い合わせメール送信完了- grfl')

@section('content')

@include('nav')

<main>
    <div class="bg-paper my-3">
        <div class="container p-0" style="max-width: 540px">
            <h4 class="text-center">お問い合わせ:送信完了</h4>
            <div class="alert alert-info" role="alert">
                <h5>
                        お問い合わせメールが送信されました!
                    </h5>
                <a class="text-decoration-none text-info" href="/">
                    ホームへ戻る<i class="fas fa-chevron-circle-right ml-1"></i>
                </a>
            </div>
        </div>
    </div>
</main>

@include('footer')

@endsection

2-5-4. mail.blade.php

resources/views/contact/mail.blade.php
お問い合わせメールを受け付けました<br>
<br>
お名前<br>
{!! $name !!}<br>
<br>
メールアドレス<br>
{!! $email !!}<br>
<br>
タイトル<br>
@if ($title !== null)
{!! $title !!}<br>
@else
無題<br>
@endif
<br>

お問い合わせ内容<br>
{!! nl2br($body) !!}<br>

補足

開発環境(FW/ツールのバージョンなど)

ツール バージョン
Vue.js 2.6.14
jQuery 3.4.1
PHP 7.4.1
Laravel 6.20.43
MySQL 5.7.36
Nginx 1.18.0
Composer 2.0.14
npm 6.14.6
Git 2.33.1
Docker 20.10.11
docker-compose v2.2.1
PHPUnit 8.0
CircleCI 2.1
heroku 7.59.4
MacBook Air M1,2020
macOS Monterey 12.3
Homebrew 3.3.8

ディレクトリ構造

【ルートディレクトリ】
├─ .circleci
│   └─ config.yml
├─ aws / CloudFormation
│   └─ ec2.yml
├─ docker
│   └─ mysql
│   └─ nginx
│   └─ php
│   └─ phpmyadmin
├─ src
│   └─ 【Laravelのパッケージ】
└─ docker-compose.yml

Reference

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2