フリーランス 技術調査ブログ

フリーランス/エンジニア Ruby Python Nodejs Vuejs React Dockerなどの調査技術調査の備忘録

Laravel Seeder

はじめに

  • シーダ(初期値設定)クラスを使用し、テストデーターをデーターベースに設定する方法を試してみる readouble.com

シーダクラス定義

  • シーダを生成するには、make:seeder Artisanコマンドを実行します。
php artisan make:seeder UsersTableSeeder
  • database/seeders/UsersTableSeeder.phpファイルが作成される
  • 下記のサンプルはusersテーブルに20件のダミーデータを登録するサンプルです。
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

class UsersTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $users = array();
        for($i = 0; $i < 20; $i++){
            array_push($users,[
                'name' => Str::random(10),
                'email' => Str::random(10).'@gmail.com',
                'password' => Hash::make('password'),
            ]);
        }
        //
        DB::table('users')->insert($users);
    }
}
  • database/seeders/DatabaseSeeder.phpファイルに作成したSeederを追記してあげる必要がある。
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        // \App\Models\User::factory(10)->create();
        $this->call(UsersTableSeeder::class);
    }
}

Seederの実行

$ php artisan db:seed
Seeding: Database\Seeders\UsersTableSeeder
Seeded:  Database\Seeders\UsersTableSeeder (1,621.02ms)
Database seeding completed successfully.

確認

  • ダミーデータが20件生成されていることを確認することができる
mysql> select * from users;
+----+-----------------+--------------------------+-------------------+--------------------------------------------------------------+----------------+---------------------+---------------------+
| id | name            | email                    | email_verified_at | password                                                     | remember_token | created_at          | updated_at          |
+----+-----------------+--------------------------+-------------------+--------------------------------------------------------------+----------------+---------------------+---------------------+
|  2 | dk9GREu3pE      | QmNE2f8zFI@gmail.com     | NULL              | $2y$10$Kds6nS.CUkPMOgyPpYnOo.BP/8YRVkW51NzKo4nwnTBpBUdrNx8j6 | NULL           | NULL                | NULL                |
|  3 | tdrCZW7Z6y      | OJyfDKXqiq@gmail.com     | NULL              | $2y$10$H9IFkphs6tq4oH07Yxqw/e7WaiAvoLEZFxQ1Yu4jTGOxK.diK3yJK | NULL           | NULL                | NULL                |
|  4 | RfV3PpEAJM      | 7mieERWGUx@gmail.com     | NULL              | $2y$10$AwB.XaNZ9VGarsEoo1mzJ.ICgngU0dGe4ki0SeILewjOOXPaAf0c6 | NULL           | NULL                | NULL                |
|  5 | pnw3o8mcBU      | wQBaDd4XtG@gmail.com     | NULL              | $2y$10$csnYNcWoe99zC9K4u1WIf.SCQ3/3JRMGuM.rUgPhCP.rbq3PpkkEu | NULL           | NULL                | NULL                |
|  6 | zL43E2MxJm      | iES7GvXbKd@gmail.com     | NULL              | $2y$10$Afx4tjz2G8nnC4sD6CqlyuFAvRsEKi3JN4dlSlvqpE0I3PSK54QNG | NULL           | NULL                | NULL                |
|  7 | j0vXF4omvb      | clW7EPH1Qv@gmail.com     | NULL              | $2y$10$WhtDNZjBDXwU3hyadPr2uetnzElHFojrJeAo342K1cNIyILffBOCC | NULL           | NULL                | NULL                |
|  8 | naJQZk0h9j      | fHBYobcIrD@gmail.com     | NULL              | $2y$10$JSfb4ylA5IFFDKovrVnW/OX4b6w8DOOFVSsKmEglXV88vWvOrURWe | NULL           | NULL                | NULL                |
|  9 | SsfNaFUsmk      | Wn6PZfjEsO@gmail.com     | NULL              | $2y$10$seL0LtIG81Me5kGF3kEXE.6MmSApCA7OhOJa/oHMmZoQuy0PGOK5C | NULL           | NULL                | NULL                |
| 10 | fRE0SvWjCw      | anTaj2hLBR@gmail.com     | NULL              | $2y$10$nT/u.DOc.rqeZbO1v1.pEeZ.S8kg7l0A0/0j2sCFr8d..I9EA/P2G | NULL           | NULL                | NULL                |
| 11 | 2xfPeOSq44      | qVVunrBnMj@gmail.com     | NULL              | $2y$10$8cauH47FfxIcugx339T8juPunNpHRg8mPGFgV2IBlM32zB60..vcS | NULL           | NULL                | NULL                |
| 12 | 1ig0wynLRW      | kMx4gxpyQk@gmail.com     | NULL              | $2y$10$3uUt2TbJsa3gTY9RzbB4aeizCB1utfRyjgyjZA6Bk5RiHsX1lctHS | NULL           | NULL                | NULL                |
| 13 | 9T8wka2QYS      | MbQoLGpxiD@gmail.com     | NULL              | $2y$10$m6yPoT.dfj03PIpmWuNF.uEk4SNVX3c8BhaH7wBi1y0aixlplwiCe | NULL           | NULL                | NULL                |
| 14 | w13yMjS1dg      | XNGacafx4n@gmail.com     | NULL              | $2y$10$dOMaqQ0Hq5TOOjJRsEQbFOZuzVsB7kjvKpjhlkICbSqiXdFkJp6kW | NULL           | NULL                | NULL                |
| 15 | uCFtvemmwm      | SlG9Xdf3ME@gmail.com     | NULL              | $2y$10$j5CbiBAGqccunLYZaQtkBeh699LhGD0n5e3P/Czbi3hxFF.AxYHYW | NULL           | NULL                | NULL                |
| 16 | KUObzrLwPQ      | MWtMtBwzi3@gmail.com     | NULL              | $2y$10$qROkCfVblRLBQ.w8cHR15OhhBlbVbIIHeff1KA1ppTU0G.1Ac5Kcy | NULL           | NULL                | NULL                |
| 17 | uwehY4hUYP      | fi0S3wbBe0@gmail.com     | NULL              | $2y$10$pAimotkAm5Vax8JsNzywtuFmpTWO9d6bNb3trBRwUWgtj.r57pBi2 | NULL           | NULL                | NULL                |
| 18 | 2RPWsZ2jck      | NTQeZVIOUg@gmail.com     | NULL              | $2y$10$DEcI5a7IciBu51AXm0YSjOcmYUsE6MQx750L15Uu8y09tP09FgPUy | NULL           | NULL                | NULL                |
| 19 | gRg8V1ALkj      | sabY861R4q@gmail.com     | NULL              | $2y$10$O5knLOkd7bFdOKj60Bqn0uiWI4EDdQBVXwdZQ.SbnlOnH5YOd2lga | NULL           | NULL                | NULL                |
| 20 | EemgcSToTO      | Lymx9MFga5@gmail.com     | NULL              | $2y$10$XH7j.oGMP9wZ6XgxFOckj.LHHZs.nrN5BA8BUHuJp6Ng8QxjgYSA6 | NULL           | NULL                | NULL                |
| 21 | xsJVieWY4C      | WB1q67CNA8@gmail.com     | NULL              | $2y$10$kY6n0cJuf2giiMDz.kv2HedVpdKofn.HKh60ihionxeB8Jd1onoi6 | NULL           | NULL                | NULL                |
+----+-----------------+--------------------------+-------------------+--------------------------------------------------------------+----------------+---------------------+---------------------+
20 rows in set (0.02 sec)

Laravel バリデーションチェック

はじめに

以前、作成した問い合わせフォームに入力チェックを追加する readouble.com

フォームリクエストの作成

  • フォームリクエストは、バリデーションロジックを含んだカスタムリクエストクラスです。 -フォームリクエストクラスを作成するには、make:request Artisan CLIコマンドを使用します。
$ php artisan make:request StoreContactForm
  • 作成したフォームリクエストはApp\Http\Requestのフォルダの直下に作成される
  • 下記のファイルに入力チェックを条件を指定する
  • 入力チェックをパイプランで指定する
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreContactForm extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return false;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            //
            'name' => 'required|string|max:20',
            'email' => 'required|email|unique:users|max:255',
            'url' => 'url|nullable',
            'age' => 'required',
            'sex' => 'required',
            'subject' => 'required|string|max:50',
            'description' => 'required|string|max:1000',
            'caution' => 'required',
        ];
    }
}

補足

  • 下記の「 This action is unauthorized. 」というエラーメッセージが表示された場合 f:id:PX-WING:20201023002019p:plain

  • 下記のauthorizeのメソッドの戻り値をtrueに変更する

class StoreContactForm extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

フォームリクエストをコントローラーに指定する

  • RequestクラスをStoreContactFormクラスに変更する
    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(StoreContactForm $request)
    {
        //
        $contact = new ContactForm;

        $contact->name = $request->input('name');
        $contact->email = $request->input('email');
        $contact->url = $request->input('url');
        $contact->sex = $request->input('sex');
        $contact->age = $request->input('age');
        $contact->subject = $request->input('subject');
        $contact->description = $request->input('description');
        $contact->save();

        return redirect('contact/index');
    }

View側にエラーメッセージを表示する処理を実装する

  • 下記の処理をエラーを表示したい個所に埋め込む
                    @if ($errors->any())
                    <div class="alert alert-danger">
                        <ul>
                            @foreach ($errors->all() as $error)
                                <li>{{ $error }}</li>
                            @endforeach
                        </ul>
                    </div>
                    @endif

動作確認

f:id:PX-WING:20201023003754p:plain

補足

  • エラーメッセージを英語から日本語に変えたい場合、resource/lang/ja/validation.phpファイルに記述する
    'attributes' => [
        'name' => '名前',
        'email' => 'メールアドレス',
        'age' => '年齢',
        'sex' => '性別',
        'subject' => '件名',
        'description' => '詳細',
        'caution' => '注意事項',
        'password' => 'パスワード'
    ],

Vue3、Typescript、JSX用のLaravelMix拡張機能について

インストール

  • 下記のパッケージをインストールする www.npmjs.com
npm install laravel-mix-vue3 --save-dev

//or

yarn add laravel-mix-vue3 -D
  • Laravel Mixがインストールに失敗した場合は、再度以下をインストールしてください
npm install @types/webpack-env @vue/compiler-sfc vue-loader@next laravel-mix-vue3  --save-dev
// or
yarn add @types/webpack-env @vue/compiler-sfc vue-loader@next laravel-mix-vue3 -D

webpack.mix.jsファイルの設定

Vue3の場合

const mix = require("laravel-mix");

require("laravel-mix-vue3");

mix.vue3("resources/js/app.js", "public/js");

TypeScriptの場合

const mix = require("laravel-mix");

require("laravel-mix-vue3");

mix.vue3("resources/js/app.ts", "public/js", {
  typescript: true,
});

JSXの場合

const mix = require("laravel-mix");

require("laravel-mix-vue3");

mix.vue3("resources/js/app.jsx", "public/js", {
  jsx: true,
});

TSXの場合

const mix = require("laravel-mix");

require("laravel-mix-vue3");

mix.vue3("resources/js/app.tsx", "public/js", {
  typescript: true,
  jsx: true,
});

サンプル

  • Vueで記述した場合
<script>
export default Vue {
  data() {
    return {
      name: '',
      locations: [],
    };
  },

  methods: {
    test(name) {
      return name + '!';
    },
  },
}
</script>
  • TypeScriptで記述した場合
<script lang="ts">
import Vue from 'vue';

export default Vue.extend({
  data() {
    return {
      name: '',
      locations: [] as string[],
    };
  },

  methods: {
    test(name: string): number {
      this.locations.push(name);
      return this.locations.length;
    },
  },
});
</script>

Laravel 問い合わせフォームを作成する③

はじめに

  • 前回の続きで、問い合わせフォームのデータを編集・削除機能を追加する px-wing.hatenablog.com

ルーティング

Route::group(['prefix'=> 'contact', 'middleware' => 'auth'], function () {
    Route::get('/index', [ContactFormController::class, 'index'])->name('contact.index');
    Route::get('/create', [ContactFormController::class, 'create'])->name('contact.create');
    Route::post('/store', [ContactFormController::class, 'store'])->name('contact.store');

    ## 前回の続きで下記のルーティングを設定する
    Route::get('/show/{id}', [ContactFormController::class, 'show'])->name('contact.show');
    Route::get('/edit/{id}', [ContactFormController::class, 'edit'])->name('contact.edit');
    Route::post('/update/{id}', [ContactFormController::class, 'update'])->name('contact.update');
    Route::post('/destroy/{id}', [ContactFormController::class, 'destroy'])->name('contact.destroy');
});

コントローラー

  • updateとdelete処理をコントローラーに追加する
    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
        $contact = ContactForm::find($id);
        $sex = $contact->gender === 1 ? '男性' : '女性';
        if ($contact->age === 1) { $age = '~19歳';};
        if ($contact->age === 2) { $age = '20歳~29歳';};
        if ($contact->age === 3) { $age = '30歳~39歳';};
        if ($contact->age === 4) { $age = '40歳~49歳';};
        if ($contact->age === 5) { $age = '50歳~59歳';};
        if ($contact->age === 6) { $age = '60歳~';};
        return view('contact.show', compact('contact','sex','age'));
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        //
        $contact = ContactForm::find($id);
        return view('contact.edit', compact('contact'));
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        //
        //
        $contact = ContactForm::find($id);

        $contact->name = $request->input('name');
        $contact->email = $request->input('email');
        $contact->url = $request->input('url');
        $contact->sex = $request->input('sex');
        $contact->age = $request->input('age');
        $contact->subject = $request->input('subject');
        $contact->description = $request->input('description');
        $contact->save();

        return redirect('contact/index');        
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
        $contact = ContactForm::find($id);
        $contact->delete();
        
        return redirect('contact/index');        
    }

View

  • show用の画面
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Dashboard') }}</div>

                <div class="card-body">
                    @if (session('status'))
                        <div class="alert alert-success" role="alert">
                            {{ session('status') }}
                        </div>
                    @endif
                    
                    {{ __('SHOWです') }}
                    {{ $contact->name}}
                    {{ $contact->email}}
                    {{ $contact->subject}}
                    {{ $contact->description}}
                    {{ $sex}}
                    {{ $age}}
                    {{ $contact->url}}
                    {{ $contact->created_at}}
                    {{ $contact->updated_at}}
                    <form method="GET" action="{{ route('contact.edit',['id' => $contact->id]) }}">
                        @csrf
                        <input class="btn btn-info" type="submit" value="変更する">
                    </form>

                    <form method="POST" action="{{ route('contact.destroy',['id' => $contact->id]) }}" id="delete_{{ $contact->id }}">
                        @csrf
                    <a href="#" class="btn btn-danger" data-id="{{$contact->id}}" onClick="deleteContact(this)">削除する</a>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
<script>
    function deleteContact(e){
        console.log(e.dataset.id);

        if (confirm('本当に削除していいですか?')){
            $('#delete_' + e.dataset.id).submit();
        }
    }
</script>

@endsection
  • 上記のViewの画面イメージ f:id:PX-WING:20201021084857p:plain

  • 編集用の画面

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Dashboard') }}</div>

                <div class="card-body">
                    @if (session('status'))
                        <div class="alert alert-success" role="alert">
                            {{ session('status') }}
                        </div>
                    @endif
                    
                    {{ __('EDITです') }}
                    <form method="POST" action="{{route('contact.update',['id'=> $contact->id])}}">
                        @csrf
                        氏名<input type="text" name="name" value="{{$contact->name}}"><br>
                        メールアドレス<input type="email" name="email" value="{{$contact->email}}"><br>
                        性別<input type="radio" name="sex" value="0" @if($contact->sex === 0) checked @endif>男性<input type="radio" name="sex" value="1" @if($contact->sex === 1) checked @endif>女性<br>
                        年齢<select name="age">
                            <option value="">選択してください</option>
                            <option value="1" @if($contact->age === 1) selected @endif>~19歳</option>
                            <option value="2" @if($contact->age === 2) selected @endif>20~29歳</option>
                            <option value="3" @if($contact->age === 3) selected @endif>30~39歳</option>
                            <option value="4" @if($contact->age === 4) selected @endif>40~49歳</option>
                            <option value="5" @if($contact->age === 5) selected @endif>50~59歳</option>
                            <option value="6" @if($contact->age === 6) selected @endif>60歳~</option>
                            </select>
                        <br>
                        URL<input type="url" name="url" value="{{$contact->url}}"><br>
                        件名<input type="text" name="subject" value="{{$contact->subject}}"><br>
                        お問い合わせ内容<textarea name="description">{{$contact->description}}</textarea><br>
                        <input class="btn btn-info" type="submit" value="更新する">
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
  • 上記のViewの画面イメージ f:id:PX-WING:20201021084932p:plain

Laravel 問い合わせフォームを作成する②

はじめに

  • 以前、作成したLaravel問い合わせフォームの作成の続きです。DB登録処理まで今回は実装する px-wing.hatenablog.com

ルーティングの設定

  • 会員のみアクセスできる問い合わせフォームを作成した場合の指定。
Route::group(['prefix'=> 'contact', 'middleware' => 'auth'], function () {
    Route::get('/index', [ContactFormController::class, 'index'])->name('contact.index');
    Route::get('/create', [ContactFormController::class, 'create'])->name('contact.create');
    Route::post('/store', [ContactFormController::class, 'store'])->name('contact.store');
});

コントローラーの設定

  • お問い合わせフォームで利用するモデルとDBふぁ## はじめに
  • 以前、作成したLaravel問い合わせフォームの作成の続きです。DB登録処理まで今回は実装する px-wing.hatenablog.com

ルーティングの設定

  • 会員のみアクセスできる問い合わせフォームを作成した場合の指定。
Route::group(['prefix'=> 'contact', 'middleware' => 'auth'], function () {
    Route::get('/index', [ContactFormController::class, 'index'])->name('contact.index');
    Route::get('/create', [ContactFormController::class, 'create'])->name('contact.create');
    Route::post('/store', [ContactFormController::class, 'store'])->name('contact.store');
});

コントローラーの設定

  • お問い合わせフォームで利用するモデルとDBファザードを追加する
use App\Models\ContactForm;
use Illuminate\Support\Facades\DB;
  • 一覧画面では登録したされた問い合わせフォームのデータを取得してViewに渡す
    public function index()
    {
        //
        $contacts = DB::table('contact_forms')->select('id','name','subject','created_at')->get();
        return view('contact.index', compact('contacts'));
    }
  • POSTで渡ってきたデータをDBに登録する
    public function store(Request $request)
    {
        //
        $contact = new ContactForm;

        $contact->name = $request->input('name');
        $contact->email = $request->input('email');
        $contact->url = $request->input('url');
        $contact->sex = $request->input('sex');
        $contact->age = $request->input('age');
        $contact->subject = $request->input('subject');
        $contact->description = $request->input('description');
        $contact->save();

        return redirect('contact/index');
    }
  • 全体のコード
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\ContactForm;
use Illuminate\Support\Facades\DB;

class ContactFormController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        //
        $contacts = DB::table('contact_forms')->select('id','name','subject','created_at')->get();
        return view('contact.index', compact('contacts'));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
        return view('contact.create');
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
        $contact = new ContactForm;

        $contact->name = $request->input('name');
        $contact->email = $request->input('email');
        $contact->url = $request->input('url');
        $contact->sex = $request->input('sex');
        $contact->age = $request->input('age');
        $contact->subject = $request->input('subject');
        $contact->description = $request->input('description');
        $contact->save();

        return redirect('contact/index');
    }

Viewの設定

  • DBに登録されているデータを一覧で表示するためのView
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-12">
            <div class="card">
                <div class="card-header">{{ __('Dashboard') }}</div>

                <div class="card-body">
                    @if (session('status'))
                        <div class="alert alert-success" role="alert">
                            {{ session('status') }}
                        </div>
                    @endif
                    <form method="get" action={{ route('contact.create') }}>
                        <button type="submit" class="btn btn-primary">
                            新規登録
                        </button>
                    </form>
                    <table class="table">
                    <thead>
                        <tr>
                        <th scope="col">#</th>
                        <th scope="col">名前</th>
                        <th scope="col">件名</th>
                        <th scope="col">作成日</th>
                        </tr>
                    </thead>
                    <tbody>
                        @foreach($contacts as $contact)
                        <tr>
                            <td>{{$contact->id}}</td>
                            <td>{{$contact->name}}</td>
                            <td>{{$contact->subject}}</td>
                            <td>{{$contact->created_at}}</td>
                        </tr>
                        @endforeach
                    </tbody>
                    </table>

                </div>
            </div>
        </div>
    </div>
</div>
@endsection
  • フォーム画面
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Dashboard') }}</div>

                <div class="card-body">
                    @if (session('status'))
                        <div class="alert alert-success" role="alert">
                            {{ session('status') }}
                        </div>
                    @endif
                    
                    {{ __('Createです') }}
                    <form method="POST" action="{{route('contact.store')}}">
                        @csrf
                        氏名<input type="text" name="name"><br>
                        メールアドレス<input type="email" name="email"><br>
                        性別<input type="radio" name="sex" value="0">男性<input type="radio" name="sex" value="1">女性<br>
                        年齢<select name="age">
                            <option value="">選択してください</option>
                            <option value="1">~19歳</option>
                            <option value="2">20~29歳</option>
                            <option value="3">30~39歳</option>
                            <option value="4">40~49歳</option>
                            <option value="5">50~59歳</option>
                            <option value="6">60歳~</option>
                            </select>
                        <br>
                        URL<input type="url" name="url"><br>
                        件名<input type="text" name="subject"><br>
                        お問い合わせ内容<textarea name="description"></textarea><br>
                        <input type="checkbox" name="caution" value="1">注意事項に同意する<br>
                        <input class="btn btn-info" type="submit" value="登録する">
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

サンプル画面

  • 一覧画面 f:id:PX-WING:20201020082616p:plain
  • 登録フォーム f:id:PX-WING:20201020082652p:plain

DB登録されていることを確認する

mysql> select * from contact_forms\G
*************************** 1. row ***************************
         id: 1
       name: 山田太郎
      email: yamada.taro@test.com
        url: http://www.yahoo.co.jp
        sex: 0
        age: 5
description: こちらはテストです。
    subject: テスト
 created_at: 2020-10-20 00:14:23
 updated_at: 2020-10-20 00:14:23
*************************** 2. row ***************************
         id: 2
       name: 鈴木一郎
      email: suzuki.ichiro@test.co.jp
        url: http://www.test.com
        sex: 0
        age: 2
description: いいいいい
いいいいいいいいいい
    subject: ああああああ
 created_at: 2020-10-20 00:15:29
 updated_at: 2020-10-20 00:15:29
2 rows in set (0.00 sec)

Laravel リソースコントローラと会員認証

はじめに

リソースコントローラ

  • リソースコントローラー作成
php artisan make:controller ContactFormController --resource

readouble.com

ルーティングの設定

  • Route::resource('contacts', ContactFormController::class);と記述すると下記のようにルーティングされる
+--------+-----------+------------------------------------------------+--------------------------------+------------------------------------------------------------------------+--------------------------------------+
| Domain | Method    | URI                                            | Name                           | Action                                                                 | Middleware                           |
+--------+-----------+------------------------------------------------+--------------------------------+------------------------------------------------------------------------+--------------------------------------+
|        | POST      | contacts                                       | contacts.store                 | App\Http\Controllers\ContactFormController@store                       | web                                  |
|        | GET|HEAD  | contacts                                       | contacts.index                 | App\Http\Controllers\ContactFormController@index                       | web                                  |
|        | GET|HEAD  | contacts/create                                | contacts.create                | App\Http\Controllers\ContactFormController@create                      | web                                  |
|        | PUT|PATCH | contacts/{contact}                             | contacts.update                | App\Http\Controllers\ContactFormController@update                      | web                                  |
|        | GET|HEAD  | contacts/{contact}                             | contacts.show                  | App\Http\Controllers\ContactFormController@show                        | web                                  |
|        | DELETE    | contacts/{contact}                             | contacts.destroy               | App\Http\Controllers\ContactFormController@destroy                     | web                                  |
|        | GET|HEAD  | contacts/{contact}/edit                        | contacts.edit                  | App\Http\Controllers\ContactFormController@edit                        | web                                  |
  • 下記のように記述すると特定のリソースだけルーティングすることが可能である。
Route::resource('contacts', ContactFormController::class)->only([
    'index', 'show'
]);
  • indexとshowだけルーティングされている
+--------+-----------+------------------------------------------------+--------------------------------+------------------------------------------------------------------------+--------------------------------------+
| Domain | Method    | URI                                            | Name                           | Action                                                                 | Middleware                           |
+--------+-----------+------------------------------------------------+--------------------------------+------------------------------------------------------------------------+--------------------------------------+
|        | GET|HEAD  | contacts                                       | contacts.index                 | App\Http\Controllers\ContactFormController@index                       | web                                  |
|        | GET|HEAD  | contacts/{contact}                             | contacts.show                  | App\Http\Controllers\ContactFormController@show                        | web                                  |
  • 対象のページを会員認証させたい場合、下記のようにmiddlwareでauth認証を行う。
Route::group(['prefix'=> 'contact', 'middleware' => 'auth'], function () {
    Route::get('/index', [ContactFormController::class, 'index']);
});

認証ディレクティブ

  • View側は下記のようにログイン認証判定を行うことができる
@guest
    // ユーザーは認証されていません。
@else
    // ユーザーは認証されています。
@endguest

readouble.com

AWS EBSボリュームを容量を増やす

はじめに

  • EC2にあるdockerを立ち上げようとしたら下記のエラーが発生した
$ docker-compose up
Failed to write all bytes for _codecs_cn.so
  • 調査してみるとディスクの容量が100%になった。 aws.amazon.com

  • ディスク容量を調べてみると8GBにすでになっている

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        2.0G     0  2.0G   0% /dev
tmpfs           2.0G     0  2.0G   0% /dev/shm
tmpfs           2.0G  472K  2.0G   1% /run
tmpfs           2.0G     0  2.0G   0% /sys/fs/cgroup
/dev/xvda1      8.0G  8.0G   24K 100% /
tmpfs           395M     0  395M   0% /run/user/1000

対処方法1 - 不要なイメージを削除する

  • 不要なdocker imagesを削除する。タグがついていない不要なdockerイメージを下記のコマンドで実行する
# docker rmi $(docker images -f dangling=true -q)

Deleted: sha256:d66f17191f3d00d519f27be8fd02cd76fadd276f7d04a8821decded77ffcfdab
Deleted: sha256:89e690b4930fffb03e49b68deb2a73d01b91fb310fde21379faccebff249dcbf
Deleted: sha256:6fa28ca68b413ed00ddc0c91641aadc6e3f4ae8acaccc5ff04d327dd90875ac6
Deleted: sha256:aa0fa3d03d72a3173b68b93f7fc192873d12f5893029d8e9d0fe6ced7a661b8c

danglingオプションはダングリング;宙ぶらりんな状態なイメージを抽出することができる

docs.docker.jp

  • 400MB空いたけど、一時的な対応に過ぎない
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        2.0G     0  2.0G   0% /dev
tmpfs           2.0G     0  2.0G   0% /dev/shm
tmpfs           2.0G  472K  2.0G   1% /run
tmpfs           2.0G     0  2.0G   0% /sys/fs/cgroup
/dev/xvda1      8.0G  7.6G  398M  96% /
tmpfs           395M     0  395M   0% /run/user/1000

対処方法2 - ディスク容量を増やす

  • 増やしたいボリュームを選択して、「ボリュームの変更」をメニューを選択する。 f:id:PX-WING:20201018080814p:plain

  • ディスク容量を再設定して変更する f:id:PX-WING:20201018081340p:plain

-完了。4~5分経過するとボリュームが増えていることを確認することができる f:id:PX-WING:20201018081525p:plain

  • ディスクが増えていることを確認できる。再起動は不要です。
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        2.0G     0  2.0G   0% /dev
tmpfs           2.0G     0  2.0G   0% /dev/shm
tmpfs           2.0G  444K  2.0G   1% /run
tmpfs           2.0G     0  2.0G   0% /sys/fs/cgroup
/dev/xvda1       16G  7.7G  8.4G  48% /
tmpfs           395M     0  395M   0% /run/user/1000

参考文献

docs.aws.amazon.com

docs.aws.amazon.com

dev.classmethod.jp