LoginSignup
1
1

More than 1 year has passed since last update.

laravelでCRUDを理解するためにまたTodoを作った!

Last updated at Posted at 2023-01-29

LaravelでCRUDするのにやったこと

Laravelを使うための環境設定は別の記事で紹介します。

今回はXampp環境で最小構成のTodoを作成しました。

作成・修正を行ったファイルとその意味について整理します。

フォルダが多くてきついと思っていた!

一通り作ると結構すくないもんなんだな。

使用ファイル

  • マイグレーションファイル
  • フロント用bladeファイル
  • コントローラファイル
  • ルーティングファイル:web.php
  • modelファイル
  • 使う人には.env

マイグレーション:DBテーブルの作成

マイグレーションは、アプリフォルダ内にDBの構成を記録しておくファイルです。

xamppの環境下であればphp artisan migrateコマンドを打てば、DBが自動で作成されるため便利です。

今回は、テーブル名のposts、カラム名(id,title,content,timestamp)のDBを作成します。

database\migrationsフォルダの中にあるよ。

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('content');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('posts');
    }
};

尚、マイグレーションがうまくいかないときは、.envファイルをいじるよ!

以下参考まで。

APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:********************************************
APP_DEBUG=true
APP_URL=http://localhost

LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
 DB_DATABASE=laravel
 DB_DATABASE=laravel_posting_app
DB_USERNAME=root
DB_PASSWORD=

bladeファイル:MVCのV(View)Laravelで使うhtmlはこのファイルに書き込みます。

hoge.blade.phpのように、ファイル名と拡張子の間にbladeという文字が挟まれます。

@foreach@if等の制御文が書け、マスタッシュ構文{{}}にてDBの中身を出力したりできます。

resources\views\postsフォルダの中にあるよ!

Todoのいいところは大体のアプリの材料になるよ!

フロントのここら辺をいじれば、chatにも掲示板にもなるよ!

 @foreach($posts as $post)
                 <div>
                     <div>
                         <h2>{{ $post->title }}</h2>
                         <p>{{ $post->content }}</p>  
                         <div>
                            <a href="{{ route('posts.show', $post) }}">詳細</a>                                
                            <a href="{{ route('posts.edit', $post) }}">編集</a>            
                            
                            <form action="{{ route('posts.destroy', $post) }}" method="post">
                                @csrf
                                @method('delete')                                        
                                <button type="submit">削除</button>
                            </form>
                        </div>
                     </div>
                 </div>
                @endforeach

index.blade.php:初期表示画面

`
<!DOCTYPE html>
 <html lang="ja">
 
 <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <title>投稿一覧</title>
 </head>
 
 <body>
     <header>
         <nav>
             <div>
           
             </div>
         </nav>
     </header>
     <a href="{{ route('posts.index') }}">投稿アプリ</a>            
     <main>
         <article>
             <div>                
                 <h1>投稿一覧</h1>
                 
                 @if (session('flash_message'))
                     <p>{{ session('flash_message') }}</p>
                 @endif
 
                 <div>
                     <a href="{{ route('posts.create') }}">新規投稿</a>                                   
                 </div>   
                 
                 @foreach($posts as $post)
                 <div>
                     <div>
                         <h2>{{ $post->title }}</h2>
                         <p>{{ $post->content }}</p>  
                         <div>
                            <a href="{{ route('posts.show', $post) }}">詳細</a>                                
                            <a href="{{ route('posts.edit', $post) }}">編集</a>            
                            
                            <form action="{{ route('posts.destroy', $post) }}" method="post">
                                @csrf
                                @method('delete')                                        
                                <button type="submit">削除</button>
                            </form>
                        </div>
                     </div>
                 </div>
                @endforeach 
             </div>
         </article>
     </main>
 
     <footer>        
         <p>&copy; 投稿アプリ All rights reserved.</p>
     </footer>
 </body>
 
 </html>

create.blade.php:新規投稿画面

`
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>新規投稿</title>    
</head>

<body>
    <header>
        <nav>
            <div>                
                <a href="{{ route('posts.index') }}">投稿アプリ</a>          
            </div>
        </nav>
    </header>

    <main>
        <article>
            <div>                
                <h1>新規投稿</h1> 
                
                @if ($errors->any())
                    <div>
                        <ul>
                            @foreach ($errors->all() as $error)
                                <li>{{ $error }}</li>
                            @endforeach
                        </ul>
                    </div>
                @endif
                
                <div>
                    <a href="{{ route('posts.index') }}">&lt; 戻る</a>                                  
                </div>

                <form action="{{ route('posts.store') }}" method="post">
                    @csrf
                    <div>
                        <label for="title">タイトル</label>
                        <input type="text" name="title" value="{{ old('title') }}">
                    </div>
                    <div>
                        <label for="content">本文</label>
                        <textarea name="content">{{ old('content') }}</textarea>
                    </div>
                    <button type="submit">投稿</button>
                </form>
            </div>
        </article>
    </main>

    <footer>        
        <p>&copy; 投稿アプリ All rights reserved.</p>
    </footer>
</body>

</html>

edit.blade.php:投稿編集画面

`
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>投稿編集</title>    
</head>

<body>
    <header>
        <nav>
            <div>                
                <a href="{{ route('posts.index') }}">投稿アプリ</a>          
            </div>
        </nav>
    </header>

    <main>
        <article>
            <div>                
                <h1>投稿編集</h1>
                
                @if ($errors->any())
                    <div>
                        <ul>
                            @foreach ($errors->all() as $error)
                                <li>{{ $error }}</li>
                            @endforeach
                        </ul>
                    </div>
                @endif 
                
                <div>
                    <a href="{{ route('posts.index') }}">&lt; 戻る</a>                                  
                </div>
                
                <form action="{{ route('posts.update', $post) }}" method="post">
                    @csrf
                    @method('patch')
                    <div>
                        <label for="title">タイトル</label>
                        <input type="text" name="title" value="{{ $post->title }}">
                    </div>
                    <div>
                        <label for="content">本文</label>
                        <textarea name="content">{{ $post->content }}</textarea>
                    </div>
                    <button type="submit">更新</button>
                </form>
            </div>
        </article>
    </main>

    <footer>        
        <p>&copy; 投稿アプリ All rights reserved.</p>
    </footer>
</body>

</html>

show.blade.php:詳細画面表示

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>投稿詳細</title>
</head>

<body>
    <header>
        <nav>
            <div>                
                <a href="{{ route('posts.index') }}">投稿アプリ</a>          
            </div>
        </nav>
    </header>

    <main>
        <article>
            <div>                
                <h1>投稿詳細</h1>  

                @if (session('flash_message'))
                    <p>{{ session('flash_message') }}</p>
                 @endif

                <div>    
                    <a href="{{ route('posts.index') }}">&lt; 戻る</a>                              
                </div>

                <div>
                    <div>
                        <h2>{{ $post->title }}</h2>
                        <p>{{ $post->content }}</p>
                    </div>
                        <div>                            
                            <a href="{{ route('posts.edit', $post) }}">編集</a>
                            
                            <form action="{{ route('posts.destroy', $post) }}" method="post">
                                //↓クロスサイトリクエストフォージェリ対策
																@csrf
                                @method('delete')                                        
                                <button type="submit">削除</button>
                            </form>
                        
                        </div>
                </div>                 
            </div>
        </article>
    </main>

    <footer>        
        <p>&copy; 投稿アプリ All rights reserved.</p>
    </footer>
</body>

</html>

コントローラ:MVCのC!VとMを制御するよ!

php artisan make:controller コントローラ名 で生成する。

コントローラ名は、やり取りするモデルに合わせて名前を変えるのが一般的。

今回は、postモデルとやり取りするので、Postcontrollerとする。

app/Http/Controllersフォルダの中にあるよ!

`<?php

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

class PostController extends Controller {
    // 一覧ページ
    public function index() {        
        $posts = Post::latest()->get();
 
        return view('posts.index', compact('posts'));
   }
     // 作成ページ
    public function create() {
            return view('posts.create');
    }
     // 作成機能
     // 作成機能
     public function store(Request $request) {
        $request->validate([
            'title' => 'required',
            'content' => 'required',
        ]);
        
        $post = new Post();
        $post->title = $request->input('title');
        $post->content = $request->input('content');
        $post->save();

        return redirect()->route('posts.index')->with('flash_message', '投稿が完了しました。');
    }

      // 詳細ページ
      public function show(Post $post) {
        return view('posts.show', compact('post'));
    }

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

    // 更新機能
    public function update(Request $request, Post $post) {
        $post->title = $request->input('title');
        $post->content = $request->input('content');
        $post->save();

        return redirect()->route('posts.show', $post)->with('flash_message', '投稿を編集しました。');
    }

    // 削除機能
    public function destroy(Post $post) {
        $post->delete();

        return redirect()->route('posts.index')->with('flash_message', '投稿を削除しました。');
    }
    
}

ルーティング:経路制御をするよ!

「このURLにアクセスしたときは○○コントローラの□□アクションを実行する」のように、ユーザーからのリクエストに応じてコントローラを選択する役割を担う。

routes\web.phpに記述するよ!

基本コードは

`Route::HTTPリクエストメソッド名('URL', [コントローラ名::class, 'アクション名']);
//例えばPostコントローラのindexアクションであれば
Route::get('/posts', [PostController::class, 'index']);

設定する際に以下のようにname()メソッドを使うことで、そのルートに名前を付けられる

`
Route::get('/posts', [PostController::class, 'index'])->name('posts.index');

ルートに名前を設定すると、bladeファイルにて、route()ヘルパーを使うことで簡易に呼び出すことができる。

`<!-- 通常のリンク -->
<a href="/posts">投稿アプリ</a>

<!-- 名前付きルート -->
<a href="{{ route('posts.index') }}">投稿アプリ</a>

また、use宣言でルーティングを設定するコントローラを宣言するを忘れないこと!

`// ルーティングを設定するコントローラを宣言する
 use App\Http\Controllers\PostController;

ルーティングの中身

`web.php
<?php

use Illuminate\Support\Facades\Route;
 // ルーティングを設定するコントローラを宣言する
use App\Http\Controllers\PostController;

Route::get('/', function () {
    return view('welcome');
});

/// 投稿の一覧ページ
Route::get('/posts', [PostController::class, 'index'])->name('posts.index');

// 投稿の作成ページ
Route::get('/posts/create', [PostController::class, 'create'])->name('posts.create');

// 投稿の作成機能
Route::post('/posts', [PostController::class, 'store'])->name('posts.store');

// 投稿の詳細ページ
Route::get('/posts/{post}', [PostController::class, 'show'])->name('posts.show');

// 投稿の更新ページ
Route::get('/posts/{post}/edit', [PostController::class, 'edit'])->name('posts.edit');

// 投稿の更新機能
Route::patch('/posts/{post}', [PostController::class, 'update'])->name('posts.update');
// 投稿の削除機能
Route::delete('/posts/{post}', [PostController::class, 'destroy'])->name('posts.destroy');

モデルの作成:データベースとやりとりしてデータの作成、読み取り、更新、削除といった処理を行う

php artisan make:model モデル名というコマンドを打つと、

app/Models

のフォルダの中に生成されるよ。

モデル名は必ずテーブル名の単数形にすること。(今回:posts⇒post)

そうすると不思議機能でDBとやり取りしてくれる。

DBの数だけモデルがいるよ!

びっくりするくらい記述が少ないけどなぜか動くよ!

`post.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasFactory;
}

一応これで最小構成のTodoアプリが作れるはず?

お好みで、BootStrapで成形してやってね!

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