この記事は、PHPのフレームワーク「Laravel」でお問い合わせフォームを作成するための解説記事です。
私(わや@wayasblog)自身、Laravelを最近勉強し始めたので、かなり丁寧に解説した初心者向けの記事となっています。
コードだけ見たい!という方は、こちら(GitHub)からどうぞ。
» Laravelで作成したアプリやアウトプットの一覧はこちら
スポンサーリンク
Laravelで作るお問い合わせフォームのイメージ
スクリーンショットで紹介していきます。
今回は、Bootstrapで簡単にスタイルを作成しました。
お問い合わせページ
お問い合わせページのバリデーション
確認ページ
完了ページ
お問い合わせ受け付けメール
初期設定
初期設定は、お問い合わせフォームに限らず毎回実施することです。
Laravelのインストール
composer create-project --prefer-dist laravel/laravel contact_form
phpMyAdimnでDB作成
今回は「contact」というDBを作成しました。
.envファイルの設定
DBとメールの設定のため、.envファイルを編集します。
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=contact DB_USERNAME=root DB_PASSWORD=root MAIL_MAILER=smtp MAIL_HOST=smtp.mailtrap.io MAIL_PORT=2525 MAIL_USERNAME=XXXXX MAIL_PASSWORD=XXXXX MAIL_ENCRYPTION=null MAIL_FROM_ADDRESS=test@test.com MAIL_FROM_NAME="${APP_NAME}"
今回メールは「MialTrap」を使用しています。
使い方は以下の記事を参考にしてみてください。
» メールの環境設定(ララ帳)
configファイルの設定
config/app.php
で日本語と時間の設定をします。
'timezone' => 'Asia/Tokyo',
'locale' => 'ja',
以上で、初期設定は終わりです。
コントローラーの作成
コントローラーの役割は、以下の通りです。
- ルートから受け取った情報をモデルに処理をお願いする
- モデルから受け取った情報をビューに表示する
具体的には、DBとの接続と処理、メール送信、バリデーション等を書いていきます。
php artisan make:controller ContactsController
※Laravelの規約に従うため、コントローラー名は必ず複数形にします。
app/Http/Controllers/ContactsController.php
が作成されました。
ここに、以下のfunction
を作っていきます。
- index
- confirm
- process
- complete
※process
は、DB挿入とメール送信のためのものでページは作成しないので、viewは渡しません。
namespace App\Http\Controllers; use Illuminate\Http\Request; class ContactsController extends Controller { public function index() { return view('contacts.index'); } public function confirm() { return view('contacts.confirm'); } public function process() { } public function complete() { return view('contacts.complete'); } }
ルーティングの設定
routes/web.php
を編集します。
// お問い合わせ入力ページ Route::get('/', 'ContactsController@index')->name('contact'); // 確認ページ Route::post('/confirm', 'ContactsController@confirm')->name('confirm'); // DB挿入、メール送信 Route::post('/process', 'ContactsController@process')->name('process'); // 完了ページ Route::get('/complete', 'ContactsController@complete')->name('complete');
ビューの作成
まず、resources/views
にcontactsフォルダを作成し、
- index
- confirm
- complete
以上の3つのbladeテンプレート作成します。
フォームは「Laravel Collective」の「Forms & HTML」を使うので、インストールします。
※参考:Laravel Collective
composer require laravelcollective/html
index.blade.php
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>お問い合わせ</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous"> </head> <body> <div class="container"> <h1 class="text-center mt-2 mb-5">お問い合わせ</h1> <div class="container"> {!! Form::open(['route' => 'confirm', 'method' => 'POST']) !!} {{ csrf_field() }} <div class="form-group row"> <p class="col-sm-4 col-form-label">お名前(10文字以内)<span class="badge badge-danger ml-1">必須</span></p> <div class="col-sm-8"> {{ Form::text('name', null, ['class' => 'form-control']) }} </div> </div> <div class="form-group row"> <p class="col-sm-4 col-form-label">メールアドレス<span class="badge badge-danger ml-1">必須</span></p> <div class="col-sm-8"> {{ Form::text('email', null, ['class' => 'form-control']) }} </div> </div> <div class="form-group row"> <p class="col-sm-4 col-form-label">電話番号</p> <div class="col-sm-8"> {{ Form::text('tel', null, ['class' => 'form-control']) }} </div> </div> <div class="form-group row"> <p class="col-sm-4 col-form-label">性別<span class="badge badge-danger ml-1">必須</span></p> <div class="col-sm-8"> <label>{{ Form::radio('gender', "男性") }}男性</label> <label>{{ Form::radio('gender', "女性") }}女性</label> </div> </div> <div class="form-group row"> <p class="col-sm-4 col-form-label">お問い合わせ内容<span class="badge badge-danger ml-1">必須</span></p> <div class="col-sm-8"> {{ Form::textarea('contents', null, ['class' => 'form-control']) }} </div> </div> <div class="text-center"> {{ Form::submit('確認画面へ', ['class' => 'btn btn-primary']) }} </div> {!! Form::close() !!} </div> </div> </body> </html>
confirm.blade.php
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>お問い合わせ - 確認</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous"> </head> <body> <div class="container"> <h1 class="text-center mt-2 mb-5">お問い合わせ確認</h1> <div class="container"> {!! Form::open(['route' => 'process', 'method' => 'POST']) !!} {{ csrf_field() }} <div class="form-group row"> <p class="col-sm-4 col-form-label">お名前(10文字以内)<span class="badge badge-danger ml-1">必須</span></p> <div class="col-sm-8"> </div> </div> <div class="form-group row"> <p class="col-sm-4 col-form-label">メールアドレス<span class="badge badge-danger ml-1">必須</span></p> <div class="col-sm-8"> </div> </div> <div class="form-group row"> <p class="col-sm-4 col-form-label">電話番号</p> <div class="col-sm-8"> </div> </div> <div class="form-group row"> <p class="col-sm-4 col-form-label">性別<span class="badge badge-danger ml-1">必須</span></p> <div class="col-sm-8"> </div> </div> <div class="form-group row"> <p class="col-sm-4 col-form-label">お問い合わせ内容<span class="badge badge-danger ml-1">必須</span></p> <div class="col-sm-8"> </div> </div> <div class="text-center"> <button name="action" type="submit" value="return" class="btn btn-dark">入力画面に戻る</button> <button name="action" type="submit" value="submit" class="btn btn-primary">送信</button> </div> {!! Form::close() !!} </div> </div> </body> </html>
complete.blade.php
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>お問い合わせ - 完了</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous"> </head> <body> <div class="text-center"> <h1 class="text-center mt-2 mb-5">お問い合わせありがとうございました。</h1> <a href="{{ route('contact') }}" class="btn btn-primary">お問い合わせ入力画面に戻る</a> </div> </body> </html>
レイアウトを共通化する
すべてのファイルに共通している部分を、共通化していきます。
resources/views
にlayout.blade.php
を作成します。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>{{ $title }}</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous"> </head> <body> <div class="container"> @yield('content') </div> </body> </html>
先ほど作成した以下のファイルに、埋め込んでいきます。
- index
- confirm
- complete
たとえば、index.blade.php
の場合は、以下の通り。
@php $title = 'お問い合わせ'; @endphp @extends('layout') @section('content') <h1 class="text-center mt-2 mb-5">お問い合わせ</h1> 〜略〜 </div> @endsection
モデルとマイグレーションの作成
モデルはDBとの連携を行う機能で、マイグレーションはDBを管理する機能です。
php artisan make:model Contact -m
※Laravelの規約に従うため、モデル名は必ず単数形にします。そしてここの名前は、先ほど作成したDB名と統一しておきます。
app/Contact.php
が作成されるので、中身を書いていきましょう。
namespace App; use Illuminate\Database\Eloquent\Model; class Contact extends Model { // Primary Key public $primaryKey = 'id'; // Timestamps public $timestamps = true; protected $fillable = [ 'name', 'email', 'tel', 'gender', 'contents', ]; }
コマンドで-m
を付けると、database/migrations
にマイグレーションファイルも一緒に作られるので、中身を書いていきます。
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateContactsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('contacts', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('name'); $table->string('email'); $table->string('tel')->nullable(); $table->string('gender'); $table->string('contents'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('contacts'); } }
ここまで完了したら、以下のコマンドでDBにテーブルが作成されます。
php artisan migrate
バリデーションの設定
app/Http/Controllers/ContactsController.php
のconfirm
の中に書いていきます。
public function confirm(Request $request) { $request->validate([ 'name' => 'required|max:10', 'email' => 'required|email', 'tel' => 'nullable|numeric', 'gender' => 'required', 'contents' => 'required', ]); return view('contacts.confirm'); }
index.blade.php
にエラーを表示させます。
@php $title = 'お問い合わせ'; @endphp @extends('layout') @section('content') <h1 class="text-center mt-2 mb-5">お問い合わせ</h1> <div class="container"> {!! Form::open(['route' => 'confirm', 'method' => 'POST']) !!} {{ csrf_field() }} <div class="form-group row"> <p class="col-sm-4 col-form-label">お名前(10文字以内)<span class="badge badge-danger ml-1">必須</span></p> <div class="col-sm-8"> {{ Form::text('name', null, ['class' => 'form-control']) }} </div> </div> @if ($errors->has('name')) <p class="alert alert-danger">{{ $errors->first('name') }}</p> @endif <div class="form-group row"> <p class="col-sm-4 col-form-label">メールアドレス<span class="badge badge-danger ml-1">必須</span></p> <div class="col-sm-8"> {{ Form::text('email', null, ['class' => 'form-control']) }} </div> </div> @if ($errors->has('email')) <p class="alert alert-danger">{{ $errors->first('email') }}</p> @endif <div class="form-group row"> <p class="col-sm-4 col-form-label">電話番号</p> <div class="col-sm-8"> {{ Form::text('tel', null, ['class' => 'form-control']) }} </div> </div> @if ($errors->has('tel')) <p class="alert alert-danger">{{ $errors->first('tel') }}</p> @endif <div class="form-group row"> <p class="col-sm-4 col-form-label">性別<span class="badge badge-danger ml-1">必須</span></p> <div class="col-sm-8"> <label>{{ Form::radio('gender', "男性") }}男性</label> <label>{{ Form::radio('gender', "女性") }}女性</label> </div> </div> @if ($errors->has('gender')) <p class="alert alert-danger">{{ $errors->first('gender') }}</p> @endif <div class="form-group row"> <p class="col-sm-4 col-form-label">お問い合わせ内容<span class="badge badge-danger ml-1">必須</span></p> <div class="col-sm-8"> {{ Form::textarea('contents', null, ['class' => 'form-control']) }} </div> </div> @if ($errors->has('contents')) <p class="alert alert-danger">{{ $errors->first('contents') }}</p> @endif <div class="text-center"> {{ Form::submit('確認画面へ', ['class' => 'btn btn-primary']) }} </div> {!! Form::close() !!} </div> @endsection
このままだと英語で表示されるので、日本語化していきます。
resources/lang
のenフォルダと同階層にjaフォルダを作成し、validation.php
をコピペ。
修正した箇所は以下の通りです。
'email' => ':attributeが正しくありません。', 'max' => [ 'string' => ':attributeは:max文字以内で入力してください。', ], 'numeric' => ':attributeは数字で入力してください。', 'required' => ':attributeは必須項目です。', 'attributes' => [ 'name' => 'お名前', 'email' => 'メールアドレス', 'tel' => '電話番号', 'gender' => '性別', 'contents' => 'お問い合わせ内容', ],
お問い合わせで入力した情報を、確認画面で表示する
app/Http/Controllers/ContactsController.php
のconfirm
に追記します。
public function confirm(Request $request) { $request->validate([ 'name' => 'required|max:10', 'email' => 'required|email', 'tel' => 'nullable|numeric', 'gender' => 'required', 'contents' => 'required', ]); // ここを追記 // フォームから受け取ったすべてのinputの値を取得 $inputs = $request->all(); return view('contacts.confirm', ['inputs' => $inputs]); }
DBに挿入するために、confirm.blade.php
にhidden
でインプット内容を保持しておきます。
@php $title = 'お問い合わせ - 確認'; @endphp @extends('layout') @section('content') <h1 class="text-center mt-2 mb-5">お問い合わせ確認</h1> <div class="container"> {!! Form::open(['route' => 'process', 'method' => 'POST']) !!} {{ csrf_field() }} <div class="form-group row"> <p class="col-sm-4 col-form-label">お名前(10文字以内)<span class="badge badge-danger ml-1">必須</span></p> <div class="col-sm-8"> {{ $inputs['name'] }} </div> </div> <input type="hidden" name="name" value="{{ $inputs['name'] }}"> <div class="form-group row"> <p class="col-sm-4 col-form-label">メールアドレス<span class="badge badge-danger ml-1">必須</span></p> <div class="col-sm-8"> {{ $inputs['email'] }} </div> </div> <input type="hidden" name="email" value="{{ $inputs['email'] }}"> <div class="form-group row"> <p class="col-sm-4 col-form-label">電話番号</p> <div class="col-sm-8"> {{ $inputs['tel'] }} </div> </div> <input type="hidden" name="tel" value="{{ $inputs['tel'] }}"> <div class="form-group row"> <p class="col-sm-4 col-form-label">性別<span class="badge badge-danger ml-1">必須</span></p> <div class="col-sm-8"> {{ $inputs['gender'] }} </div> </div> <input type="hidden" name="gender" value="{{ $inputs['gender'] }}"> <div class="form-group row"> <p class="col-sm-4 col-form-label">お問い合わせ内容<span class="badge badge-danger ml-1">必須</span></p> <div class="col-sm-8"> {{ $inputs['contents'] }} </div> </div> <input type="hidden" name="contents" value="{{ $inputs['contents'] }}"> <div class="text-center"> <button name="action" type="submit" value="return" class="btn btn-dark">入力画面に戻る</button> <button name="action" type="submit" value="submit" class="btn btn-primary">送信</button> </div> {!! Form::close() !!} </div> @endsection
DBにデータ保存、メール送信
app/Http/Controllers/ContactsController.php
のprocess
にDBにデータ保存、メール送信、入力画面に戻るボタンの動作を記述します。
public function process(Request $request) { $action = $request->get('action', 'return'); $input = $request->except('action'); if($action === 'submit') { // DBにデータを保存 $contact = new Contact(); $contact->fill($input); $contact->save(); // メール送信 Mail::to($input['email'])->send(new ContactMail('mails.contact', 'お問い合わせありがとうございます', $input)); return redirect()->route('complete'); } else { return redirect()->route('contact')->withInput($input); } }
Mailableクラス作成
メール送信のためのMailableクラスを作成します。
php artisan make:mail ContactMail
これで、app/Mail/ContactMail.php
が作成されるので、編集していきます。
namespace App\Mail; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; class ContactMail extends Mailable { use Queueable, SerializesModels; public $view; public $subject; public $data; /** * Create a new message instance. * * @return void */ public function __construct($template, $subject, $data) { $this->template = $template; $this->subject = $subject; $this->data = $data; } /** * Build the message. * * @return $this */ public function build() { return $this->text($this->template)->subject($this->subject); } }
resources/views/mails/contact.blade.php
を作成し、送信するメールを書いていきます。
{{ $data["name"] }} 様 お問い合わせありがとうございます。 以下の内容で受け付けました。 ================= お名前: {{ $data["name"] }} メールアドレス: {{ $data["email"] }} 電話番号: {{ $data["tel"] }} 性別: {{ $data["gender"] }} お問い合わせ内容: {{ $data["contents"] }} =================
app/Http/Controllers/ContactsController.php
にuse宣言も忘れずに書きましょう。
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Mail; use App\Contact; use App\Mail\ContactMail;
以上で、お問合せフォームが完成です。
お疲れさまでした\(^o^)/
【まとめ】お問い合わせフォームの作成手順【Laravel7】
初めてLaravelでお問合せフォームを作ってみたので、アウトプットしてみました。
コードだけ見たい!という方は、こちら(GitHub)からどうぞ。
Laravelの基礎的な知識は、以下のYouTube動画にお世話になりました。
2つ目は英語ですが、コードを見ながらであれば理解できると思います。
以上です。
最後まで見てくださり、ありがとうございました。
Laravelでいろいろ作っていこうと思っているので、またアウトプットします。
» Laravelで作成したアプリやアウトプットの一覧はこちら
最後に宣伝
ココナラで、コーディングの相談を受け付けています。
- CSSが上手く作れない
- JavaScriptが思ったように動かない
- ブログのデザインを修正したい
- 勉強中でわからないところがあるから教えてほしい
このようなお悩みを解決していますので、「こんなの解決できる?」ということがあったら、ぜひ質問だけでも以下のリンクよりどうぞ。
コメント