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?

More than 1 year has passed since last update.

【備忘録】【Laravel8】ファン交流サイトを作ってみよう①

Last updated at Posted at 2021-12-05

Laravel学習中の者です。
実際にアプリを作りながら習得していくことを目的として、
ファン交流サイトを作ってみます。

ER図

未作成

前提

このプログラムは下記環境で作成しています。

  • MacOS
  • ターミナル
  • composer
  • php7.3以上
  • MySQL
    が必要になります。

composerのインストール

composerがインストールされていない場合、インストールが必要です。
▼インストールはこちらから(公式ページ)
https://getcomposer.org/doc/00-intro.md

公式だと難しいと思う方は「Mac composer インストール」で検索すると、インストール記事が見つかります。

ターミナルを開いて
composer --version
を実行してバージョン情報が表示されればOK。

php7.3 and MySQL

MacにphpとMySQLをインストールするにはMAMPが最も簡単です。
MAMPはMac用のアプリで、PHP, MySQL, Apacheといった開発に必要なサーバー側のソフトウェアを一発でインストールできるスグレモノです。

Laravel8はPHP7.3以上でないと動かないのでPHPは7.3以上をインストールする必要があります。

MAMPをMacにインストールしたらターミナルから php -v を実行してPHPのバージョンを確認します。

ターミナル
php -v
PHP 7.4.25 (cli) (built: Oct 23 2021 15:38:15) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.25, Copyright (c), by Zend Technologies

基本設定

composerでプロジェクトを作成する

それでは1からファン交流サイトを作っていきます!

ホームディレクトリ直下に新規ディレクトリを作って移動します。

ターミナル
cd ~
mkdir program
cd program

以下のcomposerコマンドを実行します。
Laravelのバージョンは8.*の最新
プロジェクト名はfan_siteとしました。

ターミナル
composer create-project laravel/laravel=8.* fan_site

composerでプロジェクトが作成されたら、作成されたディレクトリでcomposer installを行いましょう。

ターミナル
cd fan_site 
composer install

ロケールをJPにする

VScodeなどのエディタでconfig/app.phpファイルを変更します。

例:
vi config/app.php

70行目近辺
'timezone' => 'Asia/Tokyo',

83行目近辺
'locale' => 'ja',
↑この設定をすることでエラーメッセージなどが日本語に切り替わります。

109行目近辺
'faker_locale' => 'ja_JP',
↑この設定をするとテスト用データを作成するときに人の名前を日本人っぽい名前にしてくれます。

MySQLでデータベースを作成する

データベースはMySQLを使用します。
MySQLにコマンドラインでログインしてユーザーとデータベースを作成します。
MySQLに「fan_site」という名前のユーザーを作成し、fan_siteユーザーがアクセス出来る「fan_site」データベースを作成します。
使用するデータベースの作成方法はご自分の好みの方法で構いませんが、
ここではMAMPのphpMyAdminを使用していきます。

MAMPのユーザアカウント機能を使って、ユーザーとデータベースを一括で作成してしまいましょう。

入力項目は下記の通り。

ユーザ名 fan_site
ホスト名 localhost
[パスワードを生成する] ボタンをクリック(生成されたパスワードはどこかにメモしておく)
同名のデータベースを作成してすべての権限を与える。にチェックを入れる

一番下にある[実行] ボタンをクリックします。

.envを設定

.envファイルとはプロジェクトで使用する設定定義ファイルです。秘匿にすべきパスワード情報なども入っています。取り扱い要注意です。

ターミナル
cp -p .env.example .env

上記を実行して.envを用意します。

以下の設定は例です。ご自分のMySQLに合わせて設定を行ってください。

.env
変更箇所のみ抜粋
APP_NAME=ファン交流サイト

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=fan_site
DB_USERNAME=fan_site
DB_PASSWORD=#mypassword#

key generate と laravel/uiのインストール

Laravel8の認証機能を使うために以下のコマンドを実行します。

ターミナル
php artisan key:generate
composer require laravel/ui
composer install
php artisan ui vue --auth

試しに migration してみる

基本的なデータベース設定が済んだところでちゃんと接続できるか試してみましょう。

以下のコマンドを実行します。

ターミナル
php artisan migrate

すると、私の場合はこんなエラーが出ました。

スクリーンショット 2021-11-24 0.09.13.png

エラーメッセージで検索して、こちらの記事を参考に進めたところ解消できました。
https://qiita.com/mineaki27th/items/5effcc2605fe90ff6997

修正した箇所

①.env

DB_PASSWORD="パスワード" ←ダブルクォーテーションでパスワードを囲む

②database.php

mysqlのunix_socketの箇所を下記に変更
'unix_socket' => '/Applications/MAMP/tmp/mysql/mysql.sock',

③キャッシュクリア

$ php artisan config:cache
$ php artisan cache:clear

その上で再度以下のコマンドを実行します。

ターミナル
php artisan migrate

今度は成功しました!
phpMyAdminを見てみると、usersテーブル等が作成されています。

データベースアクセスクラスの用意

artisan make:modelコマンドで、データベースにアクセスする用のクラスを作成していきます。

まずはPostsテーブルを作成

ターミナル
php artisan make:model Post --migration

成功すると以下のような表示になります。

php artisan make:model Post --migration
Model created successfully.
Created Migration: 2021_11_24_020205_create_posts_table

php artisan make:model Role --migrationを実行したときに以下のファイルが作られます。

database/migrations/#YYYY_MM_DD_NNNN#_create_posts_table.php
app/Models/Post.php

YYYY_MM_DD_NNNN#_create_posts_table.phpは、投稿テーブルpostsの定義ファイルです。

Post.phpはpostsテーブルにアクセスするためのEloquentモデルクラスファイルです。
EloquentとはLaravelのデータベースアクセスクラスです。
EloquentとはLaravelの一部で、データベースにアクセスする機能がまとまっているファイルです。データベースの1テーブルに対して1つのファイルを作ります。

postsテーブルの定義

マイグレーションファイルはartisanコマンドで作った直後にはidとtimestampsカラムしかありません。
postsテーブルにtitleとbodyカラムを追加します。

2021_11_24_020205_create_posts_table.php
<?php

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

class CreatePostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title', 8)->comment('タイトル');  // ← 追記 *********
            $table->text('body')->comment('本文');  // ← 追記 *********
            $table->timestamps();
        });
    }

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

$table->string('title', 8)->comment('タイトル'); の部分がカラムの定義になります。
('title', 8)の「8」は●●●●を意味しています。
Blueprintクラスのインスタンス $tableに対して stringメソッドを呼んで文字列型のカラムを追加しています。

$table->integer('amount');のようにintegerメソッドを呼ぶと数値型を格納するカラムを追加出来ます。

他にもDateなど日付を扱う指定もできます。

テーブル定義が出来たところで migrate:refreshしてみる

ターミナル
php artisan migrate:refresh

マイグレーションが実行されてテーブルが作成されました。

ファクトリの作成(割愛)

ファクトリはテスト用にダミーデータを作る仕組みです。TDDでの開発が楽に出来るようになりますが、必須ではないので今回は割愛します。

シーダーの作成

seederというテスト用データ作成クラスを作ります。今回はシーダーを使って会員情報、投稿内容を作っていきます。
以下のコマンドを実行してシーダークラスを作成します。

php artisan make:seeder UsersTableSeeder
php artisan make:seeder PostsTableSeeder

UsersTableSeederの編集

UsersTableSeeder.php
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB; // ← 追記 *********

class UsersTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        // ↓追記 ***メールアドレスを受信可能なものに設定すると通知メール試験でメールを受け取れます***
        DB::table('users')->insert(['id' => 1, 'name' => '山田花子', 'email' => 'sute1@example.com', 'email_verified_at' => "2021-09-15 15:22:10", 'password' => bcrypt('password')]);
        DB::table('users')->insert(['id' => 2, 'name' => '畠山まさみ', 'email' => 'sute2@example.com', 'email_verified_at' => "2021-10-12 16:22:10", 'password' => bcrypt('password')]);
        DB::table('users')->insert(['id' => 3, 'name' => '伊藤順子', 'email' => 'sute3@example.com', 'email_verified_at' => "2021-11-14 17:22:10", 'password' => bcrypt('password')]);
        DB::table('users')->insert(['id' => 4, 'name' => '西岡京子', 'email' => 'sute4@example.com', 'email_verified_at' => "2021-11-22 18:22:10", 'password' => bcrypt('password')]);
    }
}

PostsTableSeederの編集

PostsTableSeeder.php
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB; // ← 追記 *********

class PostsTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        // ↓ 追記 *********
        DB::table('posts')->insert(['id'=>1,'title'=>'大橋担','body'=>'お友達になりませんか?']); // ← 追記 *********
        DB::table('posts')->insert(['id'=>2,'title'=>'高橋担','body'=>'語り合いましょう']); // ← 追記 *********
        DB::table('posts')->insert(['id'=>3,'title'=>'西畑担','body'=>'お話ししましょ']); // ← 追記 *********
        DB::table('posts')->insert(['id'=>4,'title'=>'大西担','body'=>'よろしくお願いします!']); // ← 追記 *********
    }
}

デフォルトで定義されているDatabaseSeeder.phpに、実行するシーダーを登録

DatabaseSeederクラスのrun関数にある $this->callの引数に実行するシーダークラスを追記します。
それによりシードの実行順序を制御できます。

DatabaseSeeder.php
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        // $this->call(UsersTableSeeder::class);
        $this->call([
        UsersTableSeeder::class,
        PostsTableSeeder::class,
    ]);
    }
}

試しにマイグレーション

ターミナル
php artisan migrate:refresh

シーダーを実行してみる

ターミナル
php artisan db:seed

phpMyAdminを確認すると、こんな感じでシーダーで設定したデータが登録されているはずです。

スクリーンショット 2021-11-24 14.05.17.png

ブラウザで表示してみる

ポート番号を指定できるので指定します。省略すると8000ポートが使われます。

ターミナル
php artisan serve --port=9999

スクリーンショット 2021-12-04 17.56.46.png

デフォルトのWelcome画面が表示されます。

Log inを押すと、Bootstrapが反映されておらず質素なページになっています。

スクリーンショット 2021-12-04 22.27.06.png

なので反映させていきます。
下記コマンドを実施してください。

ターミナル
npm install
npm run dev //1回目
npm run dev //2回目

確認してみると、今度はちゃんと反映されました。
スクリーンショット 2021-12-04 22.36.37.png

前もって作っておいたid 1番の人のemailとpasswordを入れて、ログインしてみると...
スクリーンショット 2021-12-04 22.40.47.png

ログインできました!

新規投稿ページの作成

まずはルーティング

では、次に新規投稿ページを設定していきましょう。
まずはweb.phpを開き、こちらを追加します。

web.php
Route::get('/post/create', [App\Http\Controllers\PostController::class, 'create'])->name('create');

localhost:9999/post/createにアクセスすると、PostControllerのcreateメソッドを呼び出す設定になります。
name('create')とすることで、任意のnameを設定できますが、これは後ほどコントローラーやビューで活かされます。

次はコントローラー

PostController.phpファイルを作成します。

ターミナル
php artisan make:controller PostController --resource --model=Post

--resource オプションを入れることで PostControllerに予めCRUD処理を行う関数が作成されます。
--modelはこのコントローラーで操作するModelを指定します。投稿(Post)を扱うため Postモデルを指定します。

PostControllerを開いてみましょう。
下記のように記述されているはずです。

PostController.php
<?php

namespace App\Http\Controllers;

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

class PostController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        //
    }

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

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

    /**
     * Display the specified resource.
     *
     * @param  \App\Models\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function show(Post $post)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Models\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function edit(Post $post)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Post $post)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function destroy(Post $post)
    {
        //
    }
}

createメソッド編集

試しに下記のようにcreateメソッドの箇所を編集して、

PostController.php
public function create()
    {
        {
            return '新規投稿ページです';
        };
    }

localhost:9999/post/createにアクセスしてみてください。↓
スクリーンショット 2021-12-04 23.30.58.png

後ほど、入力フォームを追加していきます。

indexメソッド

次にindexメソッドを編集して、投稿が一覧表示されるようにしていきます。

まずはルーティングから

web.php
Route::get('/post/index', [App\Http\Controllers\PostController::class, 'index'])->name('index');

次にコントローラー

Postモデルを使いたいので、頭のほうで

PostController.php
use App\Model\Post;

としておいてください。

PostController.php
public function index()
    {
        $query = Post::query();

        //全件取得
        $posts = $query->get();

        //ページネーション
        $posts = $query->orderBy('id','desc')->paginate(10);

     //post/index.blade.phpに$postsという変数を渡す場合
        return view('post/index', ['posts' => $posts]);
    }

view(ビューファイル名,ビューに渡したいもの)とすることでコントローラからビューへ指示を出すことができます。
postsがビューで使うときの変数名、$postsはコントローラ内で定義した変数になります。
コントローラの中では、ビューで使う用の変数名に$をつけませんが、viewファイル内(bladeファイル)では変数の$をつけたものを使います。ややこしいので注意!

下記のような書き方も可能です。

PostController.php
public function index()
    {
        $query = Post::query();

        //全件取得
        $posts = $query->get();

        //ページネーション
        $posts = $query->orderBy('id','desc')->paginate(10);

     //post/index.blade.phpに$postsという変数を渡す場合
        return view('post.index')->with('posts',$posts);
    }

一覧だけなら、posts=Post::all();とかでもいいのですが、ここではqueryオブジェクトを生成して対応しています(その理由は検索機能の実装等で便利だからですが、ここでは触れません)。

またせっかくなので、orderByで最新登録が先頭に来るようにしているのと、10行毎にページ処理をしています。

取得したデータはcompact()等で返してもいいのですが、わかりやすく-with()を利用しています。

view('view名')-with('viewでの変数名','実データ'); という形式になります。

ビューの編集

postディレクトリを作成して、その中にindexファイルを作成します。
下記のように編集してみましょう。

post/index.blade.php
@extends('layouts.app')
@section('content')
   <h1>一覧表示</h1>

    <table class="table table-striped">
    @foreach($posts as $post)
        <tr>
            <td>{{$post->title}}</td>
            <td>{{$post->body}}</td>
        </tr>
    @endforeach
    </table>

    <!-- page control -->
    {!! $posts->render() !!}
@endsection

localhost:9999/post/indexを開いてみましょう。
予めDBに登録しておいたpostデータが表示されたはずです。

投稿の保存

ここからは、入力フォームの内容をDBに保存できるように実装していきたいと思います。
▼参考記事
https://nodoame.net/archives/11612

まずはルーティングから

web.php
Route::post('/post/store', [App\Http\Controllers\PostController::class, 'store'])->name('store');

※storeメソッドはPOST送信になります。

コントローラー

createメソッドとstoreメソッドを使用することになりますが、storeメソッドの方は最も重要な箇所です。
まずはcreateメソッド。

PostController.php
public function create()
    {
        //createに転送
        return view('post.create');
    }

基本的に、postディレクトリのcreate.blade.phpファイルに処理を転送しているだけになります。

そして、store。
createが投げてきた値を受け取り、DBに保存。そして、一覧表示へリダイレクトさせています。

PostController.php
public function store(Request $request)
    {
        //postオブジェクト生成
        $post = Post::create();

        //値の登録。
     //右側はviewのnameから持ってきたもの
     //左側はモデルのカラム名
        $post->title = $request->title;
        $post->body = $request->body;

        //保存
        $post->save();

        //一覧にリダイレクト
        return redirect()->to('/post/index');
    }

入力フォームを作って見た目を整える

createアクション用のビューを作っていきます。
post/create.blade.phpを作成し、下記のように編集してみましょう。

post/create.blade.php
@extends('layouts.app')

@section('content')

    <h1>新規投稿</h1>

    <div class="row">
        <div class="col-sm-12">
            <a href="/post/index" class="btn btn-primary" style="margin:20px;">一覧に戻る</a>
        </div>
    </div>

    <!-- form -->
    <form method="post" action="/post/store">

        <div class="form-group">
            <label>タイトル</label>
            <input type="string" name="title" value="" class="form-control">
        </div>

        <div class="form-group">
            <label>本文</label>
            <input type="text" name="body" value="" class="form-control">
        </div>

        <input type="hidden" name="_token" value="{{csrf_token()}}">

        <input type="submit" value="投稿" class="btn btn-primary">

    </form>

@stop

post先(action)はstore(/post/store)。methodはpost。
hiddenでLaravelでpostするときに原則必要となるcsrf_tokenを送っています。

▼参考記事

動作確認として、入力フォームに値を入れて投稿してみます。
残念。エラーです。

スクリーンショット 2021-12-05 13.56.10.png

解決するためには、DBの厳密モードを変更する必要があります。無効にするには、以下の手順に従ってください。

①Config/database.phpを開きます
②find 'strict'値をtrueからfalseに変更して、再試行します

これで無事にDBに入力フォームの値が保存されました。

今回の記事ではリレーションの設定については割愛しました。
また別の記事にて投稿したいと思います。


その他学習したこと

フォームから受け取った値を一度加工してからDBに格納するためにはEloquentが必要。

Eloquentとは

DB のデータを操作する機能のこと。
▼参考記事
https://laraweb.net/knowledge/2324/

DBに保存する方法として、
fillメソッドとsaveメソッドがありますが、
メソッドチェーンで連結しています。

fillメソッド

実行するSQL文のプレースホルダに値をバインドする処理

saveメソッド

insertする処理
です。

プレースホルダとは

実際の内容を後から挿入するために、とりあえず仮に確保した場所のこと。 また、そのことを示す標識などのこと。

バインドとは

束縛(する)、拘束(する)、結びつける、関連付ける、などの意味を持つ英単語。 ITの分野では、何らかの要素やデータ、ファイルなどが相互に関連付けられている状態や、そのような状態を実現する機能などのことを指すことが多い。

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?