こんにちは!タクマです。
31歳未経験からエンジニア転職に成功し、
2021年3月より都内の受託開発企業にてサーバーサイドエンジニアとして働いています!
今回は都道府県のセレクトボックスの実装方法を解説します。
「都道府県のセレクトボックスを実装したい!」
「都道府県のセレクトボックスの実装方法を知りたい!」
という方は、この記事を最後まで読めば、実装方法できるようになりますので、ぜひ、最後まで読んでください!
前提条件
都道府県マスターテーブルの作成
まずは都道府県のマスターデータとなるテーブルを作成します。
ターミナルで下記のコマンドを入力し、マイグレーションファイルを作成します。
php artisan make:migration create_mst_prefectures_table
マイグレーション ファイルを下記のように編集します。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateMstPrefecturesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('mst_prefectures', function (Blueprint $table) {
$table->id();
$table->string('name')->unique();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('mst_prefectures');
}
}
ここでポイントとなるのがunique()
と書いてある部分です。
これはユニーク制約と言い、name
カラムに重複した値を格納することを防ぐことができます。
編集したらターミナルでマイグレーションを実行します。
php artisan migrate
シーダーファイルの作成
次にシーダーファイルを作成し、先ほど作成したmst_prefectures
テーブルにデータを入れていきます。
まずはターミナルで下記のコマンドを実行し、シーダーファイルを作成します。
php artisan make:seeder MstPrefectureSeeder
作成されたシーダーファイルを下記のように編集します。
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class MstPrefectureSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
$params = [
['id' => 1, 'name' => '北海道'],
['id' => 2, 'name' => '青森県'],
['id' => 3, 'name' => '岩手県'],
['id' => 4, 'name' => '宮城県'],
['id' => 5, 'name' => '秋田県'],
['id' => 6, 'name' => '山形県'],
['id' => 7, 'name' => '福島県'],
['id' => 8, 'name' => '茨城県'],
['id' => 9, 'name' => '栃木県'],
['id' => 10, 'name' => '群馬県'],
['id' => 11, 'name' => '埼玉県'],
['id' => 12, 'name' => '千葉県'],
['id' => 13, 'name' => '東京都'],
['id' => 14, 'name' => '神奈川県'],
['id' => 15, 'name' => '新潟県'],
['id' => 16, 'name' => '富山県'],
['id' => 17, 'name' => '石川県'],
['id' => 18, 'name' => '福井県'],
['id' => 19, 'name' => '山梨県'],
['id' => 20, 'name' => '長野県'],
['id' => 21, 'name' => '岐阜県'],
['id' => 22, 'name' => '静岡県'],
['id' => 23, 'name' => '愛知県'],
['id' => 24, 'name' => '三重県'],
['id' => 25, 'name' => '滋賀県'],
['id' => 26, 'name' => '京都府'],
['id' => 27, 'name' => '大阪府'],
['id' => 28, 'name' => '兵庫県'],
['id' => 29, 'name' => '奈良県'],
['id' => 30, 'name' => '和歌山県'],
['id' => 31, 'name' => '鳥取県'],
['id' => 32, 'name' => '島根県'],
['id' => 33, 'name' => '岡山県'],
['id' => 34, 'name' => '広島県'],
['id' => 35, 'name' => '山口県'],
['id' => 36, 'name' => '徳島県'],
['id' => 37, 'name' => '香川県'],
['id' => 38, 'name' => '愛媛県'],
['id' => 39, 'name' => '高知県'],
['id' => 40, 'name' => '福岡県'],
['id' => 41, 'name' => '佐賀県'],
['id' => 42, 'name' => '長崎県'],
['id' => 43, 'name' => '熊本県'],
['id' => 44, 'name' => '大分県'],
['id' => 45, 'name' => '宮崎県'],
['id' => 46, 'name' => '鹿児島県'],
['id' => 47, 'name' => '沖縄県'],
];
DB::table('mst_prefectures')->insert($params);
}
}
次に、シーダーの親ファイルに作成したMstPrefectureSeeder
を登録します。
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Database\Seeders\MstPrefectureSeeder;
class DatabaseSeeder extends Seeder
{
/** 実行したいSeederをここに登録 */
private const SEEDERS = [
MstPrefectureSeeder::class,
];
/**
* Seed the application's database.
*
* @return void
*/
public function run()
{
foreach(self::SEEDERS as $seeder) {
$this->call($seeder);
}
}
}
このように親シーダー(DatabaseSeeder
)ファイルに登録することで、登録してあるシーダーファイルをコマンド一発で全て実行することができます。
なので、シーダーファイルが増えれば増えるほど、親シーダー(DatabaseSeeder
)ファイルに登録しておくと便利になります。
親シーダー(DatabaseSeeder
)ファイルに登録が終わったら、シーダーを実行します。
#親シーダー(DatabaseSeeder)ファイルに登録してあるシーダー全てを実行する場合
php artisan db:seed
#特定のシーダーファイルのみを実行する場合
php artisan db:seed --class=MstPrefectureSeeder
シーダーを実行したので、以上でデータの作成が完了しました。
モデルの作成
次にモデルを作成します。
php artisan make:model MstPrefecture
作成されたモデルを下記のように編集します。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class MstPrefecture extends Model
{
use HasFactory;
protected $fillable = [
'name',
];
/**
* 都道府県に紐付く投稿の取得(Postモデルとのリレーション)
*/
public function posts()
{
return $this->hasMany(post::class, 'prefecture_id', 'id');
}
}
次にpost
モデルにmst_prefecture
テーブルとのリレーションを記述します。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class Post extends Model
{
use HasFactory;
protected $fillable = [
#他のカラム名はあなたのカラム名を書いてください
'prefecture_id',
];
/**
* 投稿の都道府県の取得(MstPrefectureモデルとのリレーション)
*/
public function prefecture()
{
return $this->belongsTo(MstPrefecture::class);
}
}
以上でモデルの作成、およびPosts
モデルとMstPrefectures
モデルのリレーションが完了です。
※なおLaravel8においてはリレーション時にuse
宣言は必要ありません。(参考文献)
tinkerにてデータの確認
では、先ほどシーダーで作成したデータが本当に作成されているか見てみましょう。
ターミナルで下記のコードを実行し、tinker
を起動します。
php artisan tinker
#tinkerが起動すると下記のような出力がされます。
Psy Shell v0.10.8 (PHP 8.0.1 — cli) by Justin Hileman
>>>
tinker
が起動したら下記のコマンドを実行します。
>>> App\Models\MstPrefecture::all();
データが作成されていれば下記のように表示されます。
=> Illuminate\Database\Eloquent\Collection {#4514
all: [
App\Models\MstPrefecture {#4515
id: 1,
name: "北海道",
created_at: null,
updated_at: null,
},
App\Models\MstPrefecture {#4516
id: 2,
name: "青森県",
created_at: null,
updated_at: null,
},
App\Models\MstPrefecture {#4517
id: 3,
name: "岩手県",
created_at: null,
updated_at: null,
},
App\Models\MstPrefecture {#4518
id: 4,
name: "宮城県",
created_at: null,
updated_at: null,
},
#以下省略
以上でデータの確認ができました。
コントローラーにて都道府県マスターデータの取得
では次にPostController
のcreate
とedit
メソッドに記述を追加します。
<?php
namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\MstPrefecture;
class PostController extends Controller
{
/**
* 投稿作成
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function create()
{
// 都道府県テーブルの全データを取得する
$prefectures = MstPrefecture::all();
return view('post.create')
->with([
'prefectures' => $prefectures,
]);
}
/**
* 投稿編集
* @param Request $request
* @param int
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function edit(Post $post)
{
// 都道府県テーブルの全データを取得する
$prefectures = MstPrefecture::all();
return view('post.edit')
->with([
'prefectures' => $prefectures,
'post' => $post,
]);
}
}
Viewファイルに都道府県セレクトボックスの設置
ではセレクトボックスを作ります。
post
フォルダの中のcreate.blade.php
とedit.blade.php
に下記の記述をします。(どちらも下記コードで大丈夫です。)
<div>
<label>都道府県</label>
<small class="text-red">※必須</small>
<select type="text" class="form-control" name="prefecture_id" required>
<option disabled style='display:none;' @if (empty($post->prefecture_id)) selected @endif>選択してください</option>
@foreach($prefectures as $pref)
<option value="{{ $pref->id }}" @if (isset($post->prefecture_id) && ($post->prefecture_id === $pref->id)) selected @endif>{{ $pref->name }}</option>
@endforeach
</select>
</div>
上記のコードによってこのようなセレクトボックスができます。

セレクトボックスを開くとこのように都道府県が出てきます。(画像では鳥取県で途切れていますが、ちゃんと沖縄県までありますので、ご心配なく。)

ではコードについて解説していきます。
<option disabled style='display:none;' @if (empty($post->prefecture_id)) selected @endif>選択してください</option>
上記の記述によりcreate.blade.php
ではセレクトボックスの初期表示が「選択してください」となります。
でもdisabled style='display:none;
によりセレクトボックスの選択肢の中には「選択してください」は表示されません。
<option value="{{ $pref->id }}" @if (isset($institution->prefecture_id) && ($institution->prefecture_id === $pref->id)) selected @endif>{{ $pref->name }}</option>
上記の記述により、edit.blade.php
ではセレクトボックスが、保存されている都道府県名を選択した状態になります。
投稿詳細ページでの都道府県名の表示方法
投稿詳細ページでは都道府県名を下記のように表示させることができます。
// $postという変数がコントローラから渡せている前提で
{{ $post->prefecture->name }}
// prefecture_idが1で保存されていたら北海道と表示される
なぜのこの記述で都道府県名を表示させることができるのかと言うと、先ほどMstPrefecture
モデルとのリレーションで
/**
* 投稿の都道府県の取得(MstPrefectureモデルとのリレーション)
*/
public function prefecture()
{
return $this->belongsTo(MstPrefecture::class);
}
という記述をしているからです。
リレーションとして定義したメソッドは()
なしで呼び出すことができます。
さいごに
いかがでしたでしょう?
都道府県のセレクトボックスの実装ができましたでしょうか?
ご質問やご指摘等ある方はコメントしていただければ返信させていただきます。
これからもエンジニアの方、プログラミング初学者の方に役に立つ記事を更新していきますのでよろしくお願いします!
Twitterでも情報発信をしていますので、よかったらフォローをお願いします(^^)