0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

LaravelでCRUDしたいので情報を集める

Posted at

この記事で書くこと

  • Laravel + Vite(vue)で scss
  • Laravel の CRUD
  • model の作成
  • バリデーションメッセージの日本語化

scss の導入

src# npm add -D sass-embedded

model と migration の同時作成

src# php artisan make:model Book --migration
  • migration の書き方

    public function up(): void
    {
        Schema::create('skill_lists', function (Blueprint $table) {
            $table->id();
            $table->unsignedBigInteger('user_id'); //外部キー
            $table->unsignedBigInteger('skill_id'); //外部キー
            $table->integer('level');
            $table->integer('exp');
            $table->timestamps();

            $table->foreign('user_id')->references('id')->on('users');
            $table->foreign('skill_id')->references('id')->on('skills');
        });
    }
  • 指定したファイルの migration
src# php artisan migrate --path=/database/migrations/2024_12_08_053317_create_skills_table.php
  • seeder の作成
src# php artisan make:seeder SkillsTableSeeder
  • seeder の編集
/database/seeders/SkillListsTableSeeder.php
use Illuminate\Support\Facades\DB;

...
    public function run(): void
    {
        DB::table('skill_lists')->insert([
            [
                'user_id' => 1,
                'skill_id' => 1,
                'level' => 2,
                'exp' => 200,
                'created_at' => "2024-12-09"
            ],
            [
                'user_id' => 1,
                'skill_id' => 2,
                'level' => 3,
                'exp' => 300,
                'created_at' => "2024-12-09"
            ],
            [
                'user_id' => 2,
                'skill_id' => 1,
                'level' => 4,
                'exp' => 100,
                'created_at' => "2024-12-09"
            ],
        ]);
    }
/database/seeders/DatabaseSeeder.php
public function run(): void {
  $this->call(SkillListsTableSeeder::class);
}
  • 指定した seeder の実行
src# php artisan db:seed --class=CalendarsTableSeeder
  • timezone の設定(今更)
.env
APP_TIMEZONE=Asia/Tokyo

// app.phpが読んで適用する

crud 処理 (UPDATE と DELETE はまた今度)

  • 今回の ER 図
    er.png

  • fillable で追加を許可する、hasMany は 1 対多の関係(function 名は複数)

app/Models/skills.php
use Illuminate\Database\Eloquent\Relations\HasMany;

class Skill extends Model
{

    protected $fillable = [
        'name',
        'created_at'
    ];

    public function skill_lists(): HasMany
    {
        return $this->hasMany(SkillList::class);
    }
    public function calendars(): HasMany
    {
        return $this->hasMany(Calendar::class);
    }
}
app/Models/Calendar.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Calendar extends Model
{

    protected $fillable = [
        'user_id',
        'skill_id',
        'exp',
        'created_at',
    ];

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }
    public function skill(): BelongsTo
    {
        return $this->belongsTo(Skill::class);
    }
}
  • belongsTo の書き方(function 名は単数)
app/Models/SkillList.php
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class SkillList extends Model
{
    protected $fillable = [
        'user_id',
        'skill_id',
        'exp',
        'created_at',
    ];
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }
    public function skill(): BelongsTo
    {
        return $this->belongsTo(Skill::class);
    }
}
  • controller の作成
/src# php artisan make:controller CalendarController
app/Http/Controllers/CalendarController.php
class CalendarController extends Controller
{
    public function index(Request $request)
    {
        // 主←従 (READ)
        // $skillLists = SkillList::find(3)->user->name;
        // $skillLists = "a";
        // dd($skillLists);
    }

    public function create()
    {
        return view('calendar.create');
    }

    public function store(Request $request)
    {
        $request->validate([
            'name' => 'required|max:25'
        ]);
        Skill::create([
            'name' => $request->input('name'),
            'created_at' => now(),
        ]);
        return redirect()->route('calendar.index')
            ->with('success', 'Post created successfully.');
    }
}
  • routing の編集
routes/web.php
use App\Http\Controllers\CalendarController;

Route::get('/calendar/create', CalendarController::class . '@create')->name('calendar.create');
// adds a post to the database
Route::post('/calendar', CalendarController::class . '@store')->name('calendar.store');
// returns a page that shows a full post
  • view の作成
src# php artisan make:view calendar.create
resources/views/calendar.blade.php
<div class="container h-100 mt-5">
  <div class="row h-100 justify-content-center align-items-center">
    <div class="col-10 col-md-8 col-lg-6">
      <h3>Add a skill</h3>
      <form action="{{ route('calendar.store') }}" method="post">
        @csrf
        <div class="form-group">
          <label for="name">name</label>
          <input type="text" class="form-control" id="name" name="name" required>
        </div>
        <br>
        <button type="submit" class="btn btn-primary">Create skill</button>
      </form>
      //エラーハンドリング
      @if ($errors->any())
        <div class="text-red-500">
            <ul>
                @foreach ($errors->all() as $error)
                    <li>{{ $error }}</li>
                @endforeach
            </ul>
        </div>
      @endif
    </div>
  </div>
</div>
  • localhost/calendar/create にアクセス、skill が追加できることを確認

  • プルダウンの作成

app/Http/Controllers/CalendarController.php
  ...
    public function create()
    {
        $skills = Skill::pluck('name', 'id'); // modelから読み込み、配列にする
        return view('calendar.create', compact('skills'));
    }

    public function store(Request $request)
    {
        $request->validate([
            'exp' => 'required|max:25'
        ]);
        Calendar::create([
            'user_id' => 2, //user2が存在している前提
            'skill_id' => $request->input('skill'),
            'exp' => $request->input('exp'),
            'created_at' => now(),
        ]);
        return redirect()->route('calendar.index')
            ->with('success', 'Post created successfully.');
    }
  ...
resources/views/calendar/create.blade.php
        ...
        <h3>Add exp</h3>
        <form action="{{ route('calendar.store') }}" method="post">
          @csrf
          <div class="form-group">
            <label for="skill">skill</label>
            <select class="form-control" id="skill" name="skill">
              <option value="">選択してください</option>
              @foreach ($skills as $index => $name)
                  <option value="{{ $index }}">{{ $name }}</option>
              @endforeach
            </select>
          </div>
          <div class="form-group">
            <label for="exp">exp</label>
            <input type="text" class="form-control" id="exp" name="exp" required>
          </div>
          <button type="submit" class="btn btn-primary">add exp!</button>
        </form>
        ...
  • プルダウンが作成される
    スクリーンショット 2024-12-15 10.24.55.jpg

  • validation の日本語化

resources/lang/ja/validation.php
<?php

return [

  /*
    |--------------------------------------------------------------------------
    | Validation Language Lines
    |--------------------------------------------------------------------------
    |
    | The following language lines contain the default error messages used by
    | the validator class. Some of these rules have multiple versions such
    | as the size rules. Feel free to tweak each of these messages here.
    |
    */
  'attributes' => [
    'name' => '名前',
  ],

  'accepted'        => ':attributeを承認してください。',
  'active_url'      => ':attributeは、有効なURLではありません。',
  'after'           => ':attributeには、:dateより後の日付を指定してください。',
  'after_or_equal'  => ':attributeには、:date以降の日付を指定してください。',
  'alpha'           => ':attributeには、アルファベッドのみ使用できます。',
  'alpha_dash'      => ":attributeには、英数字('A-Z','a-z','0-9')とハイフンと下線('-','_')が使用できます。",
  'alpha_num'       => ":attributeには、英数字('A-Z','a-z','0-9')が使用できます。",
  'array'           => ':attributeには、配列を指定してください。',
  'before'          => ':attributeには、:dateより前の日付を指定してください。',
  'before_or_equal' => ':attributeには、:date以前の日付を指定してください。',
  'between'         => [
    'numeric' => ':attributeには、:minから、:maxまでの数字を指定してください。',
    'file'    => ':attributeには、:min KBから:max KBまでのサイズのファイルを指定してください。',
    'string'  => ':attributeは、:min文字から:max文字にしてください。',
    'array'   => ':attributeの項目は、:min個から:max個にしてください。',
  ],
  'boolean'              => ":attributeには、'true'か'false'を指定してください。",
  'confirmed'            => ':attributeと:attribute確認が一致しません。',
  'date'                 => ':attributeは、正しい日付ではありません。',
  'date_equals'          => ':attributeは:dateに等しい日付でなければなりません。',
  'date_format'          => ":attributeの形式は、':format'と合いません。",
  'different'            => ':attributeと:otherには、異なるものを指定してください。',
  'digits'               => ':attributeは、:digits桁にしてください。',
  'digits_between'       => ':attributeは、:min桁から:max桁にしてください。',
  'dimensions'           => ':attributeの画像サイズが無効です',
  'distinct'             => ':attributeの値が重複しています。',
  'email'                => ':attributeは、有効なメールアドレス形式で指定してください。',
  'ends_with'            => 'The :attribute must end with one of the following: :values',
  'exists'               => '選択された:attributeは、有効ではありません。',
  'file'                 => ':attributeはファイルでなければいけません。',
  'filled'               => ':attributeは必須です。',
  'gt'                   => [
    'numeric' => ':attributeは、:valueより大きくなければなりません。',
    'file'    => ':attributeは、:value KBより大きくなければなりません。',
    'string'  => ':attributeは、:value文字より大きくなければなりません。',
    'array'   => ':attributeの項目数は、:value個より大きくなければなりません。',
  ],
  'gte'                  => [
    'numeric' => ':attributeは、:value以上でなければなりません。',
    'file'    => ':attributeは、:value KB以上でなければなりません。',
    'string'  => ':attributeは、:value文字以上でなければなりません。',
    'array'   => ':attributeの項目数は、:value個以上でなければなりません。',
  ],
  'image'                => ':attributeには、画像を指定してください。',
  'in'                   => '選択された:attributeは、有効ではありません。',
  'in_array'             => ':attributeが:otherに存在しません。',
  'integer'              => ':attributeには、整数を指定してください。',
  'ip'                   => ':attributeには、有効なIPアドレスを指定してください。',
  'ipv4'                 => ':attributeはIPv4アドレスを指定してください。',
  'ipv6'                 => ':attributeはIPv6アドレスを指定してください。',
  'json'                 => ':attributeには、有効なJSON文字列を指定してください。',
  'lt'                   => [
    'numeric' => ':attributeは、:valueより小さくなければなりません。',
    'file'    => ':attributeは、:value KBより小さくなければなりません。',
    'string'  => ':attributeは、:value文字より小さくなければなりません。',
    'array'   => ':attributeの項目数は、:value個より小さくなければなりません。',
  ],
  'lte'                  => [
    'numeric' => ':attributeは、:value以下でなければなりません。',
    'file'    => ':attributeは、:value KB以下でなければなりません。',
    'string'  => ':attributeは、:value文字以下でなければなりません。',
    'array'   => ':attributeの項目数は、:value個以下でなければなりません。',
  ],
  'max'                  => [
    'numeric' => ':attributeには、:max以下の数字を指定してください。',
    'file'    => ':attributeには、:max KB以下のファイルを指定してください。',
    'string'  => ':attributeは、:max文字以下にしてください。',
    'array'   => ':attributeの項目は、:max個以下にしてください。',
  ],
  'mimes'                => ':attributeには、:valuesタイプのファイルを指定してください。',
  'mimetypes'            => ':attributeには、:valuesタイプのファイルを指定してください。',
  'min'                  => [
    'numeric' => ':attributeには、:min以上の数字を指定してください。',
    'file'    => ':attributeには、:min KB以上のファイルを指定してください。',
    'string'  => ':attributeは、:min文字以上にしてください。',
    'array'   => ':attributeの項目は、:min個以上にしてください。',
  ],
  'not_in'               => '選択された:attributeは、有効ではありません。',
  'not_regex'            => ':attributeの形式が無効です。',
  'numeric'              => ':attributeには、数字を指定してください。',
  'password'             => ':attributeが間違っています',
  'present'              => ':attributeが存在している必要があります。',
  'regex'                => ':attributeには、有効な正規表現を指定してください。',
  'required'             => ':attributeは、必ず指定してください。',
  'required_if'          => ':otherが:valueの場合、:attributeを指定してください。',
  'required_unless'      => ':otherが:values以外の場合、:attributeを指定してください。',
  'required_with'        => ':valuesが指定されている場合、:attributeも指定してください。',
  'required_with_all'    => ':valuesが全て指定されている場合、:attributeも指定してください。',
  'required_without'     => ':valuesが指定されていない場合、:attributeを指定してください。',
  'required_without_all' => ':valuesが全て指定されていない場合、:attributeを指定してください。',
  'same'                 => ':attributeと:otherが一致しません。',
  'size'                 => [
    'numeric' => ':attributeには、:sizeを指定してください。',
    'file'    => ':attributeには、:size KBのファイルを指定してください。',
    'string'  => ':attributeは、:size文字にしてください。',
    'array'   => ':attributeの項目は、:size個にしてください。',
  ],
  'starts_with'          => ':attributeは、次のいずれかで始まる必要があります。:values',
  'string'               => ':attributeには、文字を指定してください。',
  'timezone'             => ':attributeには、有効なタイムゾーンを指定してください。',
  'unique'               => '指定の:attributeは既に使用されています。',
  'uploaded'             => ':attributeのアップロードに失敗しました。',
  'url'                  => ':attributeは、有効なURL形式で指定してください。',
  'uuid'                 => ':attributeは、有効なUUIDでなければなりません。',

  /*
    |--------------------------------------------------------------------------
    | Custom Validation Language Lines
    |--------------------------------------------------------------------------
    |
    | Here you may specify custom validation messages for attributes using the
    | convention "attribute.rule" to name the lines. This makes it quick to
    | specify a specific custom language line for a given attribute rule.
    |
    */

  'custom' => [
    'attribute-name' => [
      'rule-name' => 'custom-message',
    ],
  ],

  /*
    |--------------------------------------------------------------------------
    | Custom Validation Attributes
    |--------------------------------------------------------------------------
    |
    | The following language lines are used to swap our attribute placeholder
    | with something more reader friendly such as "E-Mail Address" instead
    | of "email". This simply helps us make our message more expressive.
    |
    */
];

今思った

  • データベースの skill はユーザー id をつけていない。
  • よって他のユーザーの skill も見れるけど、プルダウンにすると多すぎる
  • プルダウンを辞める or 自分のスキルだけに変更したい

ユーザー管理

  • 別記事にする予定

参考にした記事

  • session について

  • Laravel11 でのユーザー認証

  • テーブルの接続

  • laravel の crud

  • validation の日本語化

  • プルダウンの作り方

0
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?