Laravel 新規立ち上げ以降 CRUDの処理を実行まで

①認証機能設定


composer require laravel/ui
php artisan ui bootstrap --auth

②Bootstrapの公式ページにて、Compiled CSS and JS ファイルをダウンロード
https://getbootstrap.jp/docs/4.4/getting-started/download/
JSフォルダの中のbootstrap.min.js 、CSSフォルダの中のbootstrap.min.cssを取り出し、プロジェクトのpublicフォルダの中にjsフォルダ、cssフォルダをそれぞれ作り、この中にいれる

③resources/layouts/app.blade.phpファイルを開き以下追加

   {{-- 追加する --}}
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<link href="{{ asset('css/bootstrap.min.css') }}" rel="stylesheet">
<script src="{{ asset('js/bootstrap.min.js') }}" defer></script>

④タイムゾーンと言語の変更
config内のapp.phpファイルを開き70行目あたりに ‘timezone’を ‘Asia/Tokyo’ とし83行目あたりの ‘locale’ を ‘ja’ とする

⑤プロジェクトの日本語化
https://github.com/Laravel-Lang/lang 【Code】からDownload ZIPを実行
locales/ja/ja.jsonファイルを取り出しresource/langの中にいれる。

⑥警告メッセージの日本語化 
下記を順番に実行


php -r "copy('https://readouble.com/laravel/8.x/ja/install-ja-lang-files.php', 'install-ja-lang.php');"

php -f install-ja-lang.php

php -r "unlink('install-ja-lang.php');"

⑦ルート設定の変更
app/Providersの中のRouteServiceProvider.phpファイルを開く
29行目の// protected の//を外して有効にする

⑧モデルとDB作成
下記を実行


php artisan make:model Post -m

コマンド実施後、databaseフォルダの中の【本日の日付_create_posts_table.php】ファイルを開き下記のように入力


    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('body');
            $table->text('image')->nullable();
            $table->timestamps();
        });
    }

マイグレートを実行
php artisan migrate

実行したマイグレーションの操作をやり直したい時は、ロールバックコマンド
php artisan migrate:rollback

⑨リレーションの設定
app/Models から Post.php ファイルを開き

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Auth;
を入れる

12行目あたりに、次のコードを入れる

【Post.php】


class Post extends Model
{
    use HasFactory;

    public function user() {
        return $this->belongsTo('App\Models\User');
    }
}

次に app/ModelsからUser.phpファイルを開き、下記を入れる

【User.php】


    public function posts() {
        return $this->hasMany('App\Models\Post');
    }

⑩作成したテーブルの中にカラムを追加する


php artisan make:migration add_column_user_id_to_posts_table --table=posts

実行後、databaseフォルダの中に【本日の日付 add_column_user_table_to_posts_table.php】ファイルができるのでファイルを開き、17行目あたりに、新たなuser_idカラムを追加

【日付 add_column_user_table_to_posts_table.php】


    public function up()
    {
        Schema::table('posts', function (Blueprint $table) {
            $table->unsignedBigInteger('user_id')->after('image');
        });
    }

ファイル下部の public function down に、取り消した場合の処理を入れる

【日付 add_column_user_table_to_users_table.php】


    public function down()
    {
        Schema::table('posts', function (Blueprint $table) {
            $table->dropColumn('user_id');
        });
    }

準備ができたら、

php artisan migrate

phpMyAdminにログインして、postsテーブルにuser_idカラムが追加されてるか確認

11 Laravelのビューファイルの作成
resources/viewsのなかに、【post】フォルダを作りこの中に 【create.blade.php】ファイルを作る

【create.blade.php】

@extends('layouts.app')
@section('content')

<div class="row">
    <div class="col-md-10 mt-6">
        <div class="card-body">
            <h1 class="mt-4">新規投稿</h1>
            @if ($errors->any())
            <div class="alert alert-danger">
                <ul>
                    @foreach ($errors->all() as $error)
                    <li>{{ $error }}</li>
                    @endforeach
                    @if(empty($errors->first('image')))
                    <li>画像ファイルがあれば、再度、選択してください。</li>
                    @endif
                </ul>
            </div>
            @endif

            @if(session('message'))
            <div class="alert alert-success">{{session('message')}}</div>
            @endif

            <form method="post" action="{{route('post.store')}}" enctype="multipart/form-data">
                @csrf
                <div class="form-group">
                    <label for="title">件名</label>
                    <input type="text" name="title" class="form-control" id="title" value="{{old('title')}}" placeholder="Enter Title">
                </div>

                <div class="form-group">
                    <label for="body">本文</label>
                    <textarea name="body" class="form-control" id="body" cols="30" rows="10">{{old('body')}}</textarea>
                </div>

                <div class="form-group">
                    <label for="image">画像(1MBまで)</label>

                    <div class="col-md-6">
                        <input id="image" type="file" name="image">
                    </div>
                </div>

                <button type="submit" class="btn btn-success">送信する</button>
            </form>
        </div>
    </div>
</div>
    
@endsection

12. リソースコントローラー作成


php artisan make:controller PostController --resource

コマンド実行後、app/Http/Controller の中に PostController.php ファイルができる

PostController.phpファイルを開きuse文の下にもう一つ、下記のuse宣言を入れておく


use Illuminate\Http\Request;
use App\Models\Post;

createメソッドに、次のように入力

【PostController.php】


class PostController extends Controller
{
    
    public function create()
    {
            return view('post.create');
    }
}

13. ルート設定

routes の中のweb.phpファイルをひらきファイルの一番下に、下記を追加

【web.php】


Route::resource('/post', 'PostController');

14. 投稿データを保存するためのコントローラーの処理

app/modelsの中のPost.phpファイルを開き、use HasFactory;のすぐ下に下記を入力


class Post extends Model
{
    use HasFactory;
    protected $fillable = [
        'title',
        'body',
        'user_id',
        'image',
    ];

app/Http/Controllersの中のPostControllerを開く

storeメソッドの一番最初に、下記を入れる


   public function store(Request $request)
    {
        $inputs=$request->validate([
            'title'=>'required|max:255',
            'body'=>'required|max:255',
            'image'=>'image|max:1024'
        ]);
        $post=new Post();
        $post->title=$inputs['title'];
        $post->body=$inputs['body'];
        $post->user_id=auth()->user()->id;
        $post->save();
        return back()->with('message', '投稿を作成しました');
    }

15 画像の保存
storageフォルダに保存した画像をpublicフォルダを通じてアクセスするために、publicフォルダにstorageフォルダのシンボリックリンクが必要

プロジェクトフォルダ内で


php artisan storage:link

実行
コマンド実行後、publicフォルダを開くとstorageフォルダへのリンクが貼られます。

16 画像保存処理を追加

app/Http/Controllersの中のPostControllerを開き


   public function store(Request $request)
    {

        $inputs=request()->validate([
            'title'=>'required|max:255',
            'body'=>'required|max:255',
            'image'=>'image|max:1024'
        ]);
        $post=new Post();
        $post->title=$inputs['title'];
        $post->body=$inputs['body'];
        $post->user_id=auth()->user()->id;

        if (request('image')){
            $original = request()->file('image')->getClientOriginalName();
             // 日時追加
            $name = date('Ymd_His').'_'.$original;
            request()->file('image')->move('storage/images', $name);
            $post->image = $name;
        }

        $post->save();
        return back()->with('message', '投稿を作成しました');
    }

① 元々のファイル名を取得し、これを$nameに代入する
② $nameの名前で画像ファイルを指定した場所に保存する
③ $nameの名前で画像ファイルのファイル名をデータベースに保存する

画像の送信テストをおこないアップロード後、データベースをチェックpostsテーブルを確認
元々のファイル名で画像ファイルが登録されていれば、成功

publicフォルダの中のstorageへのリンクをクリックし
imageフォルダが出来ており、imageフォルダの中に投稿した画像が保存されていれば成功

17  一覧画面の作成

home画面を使って、一覧画面を表示する

routesの中のweb.phpファイル


Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');

設定の最後に、上記のように ->name(‘home’)を付けておく

次に、app/Http/Controllersの中の HomeController.php を開く

下記のuse宣言を加える


use App\Models\Post;

HomeController内のindexメソッドを編集

【HomeController.php】

    public function index(){

        $posts=Post::all();
        $user=auth()->user();
        return view('home', compact('posts', 'user'));
    }

18 一覧画面表示ファイルを作成

resources/viewsの中の home.blade.phpファイルを開き次のコードを入れる

@extends('layouts.app')
@section('content')
{{$user->name}}さん、こんにちは!
@foreach ($posts as $post)
<div class="container-fluid mt-20" style="margin-left:-10px;">
    <div class="row">
        <div class="col-md-12">
            <div class="card mb-4">
                <div class="card-header">
                    <div class="media flex-wrap w-100 align-items-center">
                        <div class="media-body ml-3"> {{ $post->title }} 
                            <div class="text-muted small"> {{ $post->user->name }}</div>
                        </div>
                        <div class="text-muted small ml-3">
                            <div>投稿日</div>
                            <div><strong>{{$post->created_at->diffForHumans()}}</strong></div>
                        </div>
                    </div>
                </div>
                <div class="card-body">
                    <p>{{$post->body}} </p>
                </div>
            </div>
        </div>
    </div>
</div>
@endforeach
@endsection

19 データの並び順を変える

【HomeController.php】

    public function index(){

        $posts=Post::orderBy('created_at','desc')->get();
        $user=auth()->user();
        return view('home', compact('posts', 'user'));
    }

20 CSSの適用
テンプレートを取得
BBBootstrap Forum discussion:
https://bbbootstrap.com/snippets/forum-discussion-template-65198141
上記サイトを開き、CSSタブのコードをコピー

Laravelのプロジェクト内のpublic/css フォルダの中にforum.cssファイルを作成
作成したforum.cssファイルに、先ほどコピーしたCSSコードを貼り付け

forum.cssファイルをプロジェクトに紐づけ
resources/views/layouts の中の app.blade.phpファイルを開き
タグの前あたり

【app.blade.php】

    <!-- Styles -->
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
    <link href="{{ asset('css/forum.css') }}" rel="stylesheet">
</head>
<body>

21 サイドバー用のビューページを作成

resources/views/layoutsの中に、sidebar.blade.phpファイルを新規作成

【sidebar.blade.php】

  <div class="list-group"> 
    <a href="{{route('home')}}" class='list-group-item'>
        <i class="fas fa-home pr-2"></i><span>一覧表示</span>
    </a>
    <a href="{{route('post.create')}}" class='list-group-item'>
        <i class="fas fa-pen-nib pr-2"></i><span>新規投稿</span>
    </a>
</div>

22 サイドバーをテンプレートページに入れ込む
resouces/reviews/layouts の中のapp.blade.phpを開き

ファイル下のほうのmainタグのあたりを下記のように変更

【app.blade.php】

        <main class="py-4">
            <div class="container">
                <div class="row">
                    <div class="col-12 col-md-4 col-lg-3">
                    @include('layouts.sidebar')
                    </div>
                    <div class="col-12 col-md-8  col-lg-9">                 
                    @yield('content')
                    </div>
                </div>
            </div>
        </main>

現在地のメニューの色を変える方法
今いるメニューの色を変えたりしたい場合には、sidebar.blade.phpファイルを次のように変えましょう。

【sidebar.blade.php】

 <div class="list-group"> 
    <a href="{{route('home')}}"
    class="list-group-item {{url()->current()==route('home')? 'active' : ''}}">
        <i class="fas fa-home pr-2"></i><span>一覧表示</span>
    </a>
    <a href="{{route('post.create')}}"
    class="list-group-item {{url()->current()==route('post.create')? 'active' : ''}}">
        <i class="fas fa-pen-nib pr-2"></i><span>新規投稿</span>
    </a>
</div>

23. 投稿を個別表示
投稿の一覧表示のタイトルにリンクを付けておき、タイトルをクリックすると個別ページに飛ぶようにする

resources/viewsの中の home.blade.phpファイルを開く

【home.blade.php】

<a href="{{route('post.show', $post)}}">{{ $post->title }}</a>

個別表示ページのコントローラ作成

app/Http/Controllersの中のPostController.phpを開く

【PostController.php】

    public function show(Post $post)
    {
        return view('post.show', compact('post'));
    }

個別ページのビュー作成

resources/views/post の中に show.blade.phpファイルを作成

【show.blade.php】

@extends('layouts.app')
@section('content')

<div class="card mb-4">
    <div class="card-header">
        <div class="text-muted small mr-3"> 
            {{$post->user->name}}
        </div>
        <h4>{{$post->title}}</h4>
    </div>
    <div class="card-body">
        <p class="card-text">
            {{$post->body}}
        </p>
        @if ($post->image)
        <div>
            (画像ファイル:{{$post->image}})
        </div>
        <img src="{{asset('storage/images/'.$post->image)}}" 
        class="img-fluid mx-auto d-block" style="height:300px;">
        @endif
    </div>
    <div class="card-footer">
        <span class="mr-2 float-right">
            投稿日時 {{$post->created_at->diffForHumans()}}
        </span>
    </div>
</div>

@endsection

24   投稿の編集

個別ページにボタンを付け、ボタンをクリックしたら編集ページが表示されるようにする

resources/views/post の中の show.blade.phpファイルを開く
{{$post->title}} の下に、下記のコードを追加
【show.blade.php】

      <h4>{{ $post->title }}</h4>
        <span class="ml-auto">
        <a href="{{route('post.edit', $post)}}"><button class="btn btn-primary">編集</button></a>
        </span>

編集用のコントローラーを作成

app/Http/Controllersの中の PostController.phpを開き、editメソッドを次のように編集

   public function edit(Post $post)
    {
        return view('post.edit', compact('post'));
    }

編集ページの作成

resources/views/postの中に、edit.blade.phpファイルを作成
以前作成した create.blade.phpファイルをそのままコピーして貼り付け

件名部分に、現在データベースに保存されている内容が表示されるようにする。
inputタグ内のvalue属性の中にあるold()関数の第2引数に、次のように $post->title を加える

old関数を使うことで、バリデーションエラーが起こったときには、エラー前に入力した値が表示され、それ以外のときには、第2引数の値が表示されるようになる

@extends('layouts.app')
@section('content')

<div class="row">
    <div class="col-md-10 mt-6">
        <div class="card-body">
            <h1 class="mt4">投稿編集</h1>
            @if ($errors->any())
            <div class="alert alert-danger">
                <ul>
                    @foreach ($errors->all() as $error)
                    <li>{{ $error }}</li>
                    @endforeach
                    @if(empty($errors->first('image')))
                    <li>画像ファイルがあれば、再度、選択してください。</li>
                    @endif
                </ul>
            </div>
            @endif

            @if(session('message'))
            <div class="alert alert-success">{{session('message')}}</div>
            @endif

            <form method="post" action="{{route('post.store')}}" enctype="multipart/form-data">
                @csrf
                <div class="form-group">
                    <label for="title">件名</label>
                    <input type="text" name="title" class="form-control" 
                        value="{{old('title', $post->title)}}" id="title" placeholder="Enter Title">
                </div>

                <div class="form-group">
                    <label for="body">本文</label>
                     <textarea name="body" class="form-control" id="body" cols="30" rows="10">{{old('body', $post->body)}}
                        </textarea>
                </div>

                <div class="form-group">
                    <div>
                        @if($post->image)
                        <img src="{{ asset('storage/images/'.$post->image)}}" 
                        class="img-fluid rmx-auto d-block" style="height:200px;">
                        @endif
                    </div>
                    <label for="image">画像(1MBまで)</label>
                    <div class="col-md-6">
                        <input id="image" type="file" name="image">
                    </div>
                </div>   

                <button type="submit" class="btn btn-success">送信する</button>
            </form>
        </div>
    </div>
</div>
    
@endsection

25 投稿の更新

上記のedit.blade.phpファイルのフォームタグを次のように修正

            <form method="post" action="{{route('post.update', $post)}}" enctype="multipart/form-data">
                @csrf
                @method('put')

コントローラーの編集

app/Http/Controllersの中のPostController.phpを開く

【PostController.php】

    public function update(Request $request, Post $post)
    {  
        $inputs=$request->validate([
            'title'=>'required|max:255',
            'body'=>'required|max:255',
            'image'=>'image|max:1024'
        ]);

        $post->title=$inputs['title'];
        $post->body=$inputs['body'];
                
        if(request('image')){
            $original=request()->file('image')->getClientOriginalName();
            $name=date('Ymd_His').'_'.$original;
            $file=request()->file('image')->move('storage/images', $name);
            $post->image=$name;
        }

        $post->save();

        return back()->with('message', '投稿を更新しました');
    }

26 投稿の削除

resources/views/postの中の show.blade.phpファイルに削除ボタンを追加

【show.blade.php】

       <span class="ml-auto">
          <a href="{{route('post.edit', $post)}}"><button class="btn btn-primary">編集</button></a>
        </span>
        <span class="ml-2">
          <form method="post" action="{{route('post.destroy', $post)}}">
            @csrf
            @method('delete')
            <button type="submit" class="btn btn-danger" onClick="return confirm('本当に削除しますか?');">削除</button>
          </form>
        </span>

formタグのmethod属性にはpost を指定して、form開始タグの下に @method(‘delete’) を入れる
またルート設定の中に $post パラメータを設置

コントローラーの編集

app/Http/Controllersの中のPostController.phpを開く

destroyメソッドに、次のようにコードを加える

【PostController.php】

   public function destroy(Post $post)
    {        
        $post->delete();
        return redirect()->route('home')->with('message', '投稿を削除しました');
    }

処理が終わった後はredirectを使って、投稿一覧画面に戻る

resources/views の中の home.blade.php ファイルの上部に、メッセージを表示するためのコードを入れる

【home.blade.php】

@extends('layouts.app')
@section('content')

@if(session('message'))
<div class="alert alert-success">{{session('message')}}</div>
@endif

<div class="ml-2 mb-3">
    home
</div>

コメント

タイトルとURLをコピーしました