皆さん、こんにちは。管理人です。今回はシリーズ「Laravel で電子掲示板を作ろう」の第7回目となります。
コメントの編集ボタンと削除ボタンを横に並べる
まずは、コメントの編集ボタンと削除ボタンを横に並べるところから始めようと思います。そのために
<div class="flex flex-row-reverse mt-1">
</div>
という要素を作り、この中に編集ボタンと削除ボタンを入れます。resources/views/post.blade.php を次のようにして下さい。(なお、余白調整のため、10行目を少し変更しました。)
<x-guest-layout>
<x-slot name="title">{{ $post['title'] }}</x-slot>
<h1>{{ $post['title'] }}</h1>
<p>{{ $post['content'] }}</p>
<h2>みんなのコメント</h2>
@forelse ($comments as $comment)
<div class="bg-gray-300 p-2 mb-4">
<p class="m-0">{{ $comment['content'] }}</p>
@auth
@if ($comment->user->id === Auth::id())
<div class="flex flex-row-reverse mt-1">
<form method='POST' action="{{ route('delete_comment', $comment['id']) }}">
@csrf
<button type='submit' class="bg-red-600 hover:bg-red-500 text-white rounded px-4 py-2"
onclick='return confirm("コメント「{{ $comment->content }}」を削除しますか?");'>
削除
</button>
</form>
<button class="bg-green-600 hover:bg-green-500 text-white rounded px-4 py-2 mr-2"
type="button" onclick="location.href='{{ route('edit_comment', $comment['id']) }}'">
編集
</button>
</div>
@endif
@endauth
</div>
@empty
<p>コメントはまだありません。</p>
@endforelse
@auth
<h2>コメントを投稿する</h2>
<form class="grid grid-cols-1 gap-6 text-black" method='POST' action="{{ route('store_comment') }}" enctype="multipart/form-data">
@csrf
<input type='hidden' name='post_id' value="{{ $post['id'] }}">
<label class="block">
<textarea name='content'
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"
rows="3"></textarea>
</label>
<button type='submit' class="w-20 bg-blue-600 hover:bg-blue-500 text-white rounded px-4 py-2">投稿</button>
</form>
@else
<p>ログインするとコメントを投稿することができます。</p>
@endauth
</x-guest-layout>
改行を反映させる
続いて、記事の本文やコメント内での改行が現状では半角スペースになってしまっているので、改行が反映されるようにしたいと思います。そのためには、pre タグを使います。resources/views/post.blade.php を次のように編集します。(なお、not-prose を忘れるとその要素の背景が黒くなってしまうので注意しましょう。)
<x-guest-layout>
<x-slot name="title">{{ $post['title'] }}</x-slot>
<h1>{{ $post['title'] }}</h1>
<div class="not-prose">
<pre>{{ $post['content'] }}</pre>
</div>
<h2>みんなのコメント</h2>
@forelse ($comments as $comment)
<div class="bg-gray-300 p-2 mb-4 not-prose">
<pre>{{ $comment['content'] }}</pre>
@auth
@if ($comment->user->id === Auth::id())
<div class="flex flex-row-reverse mt-1">
<form method='POST' action="{{ route('delete_comment', $comment['id']) }}">
@csrf
<button type='submit' class="bg-red-600 hover:bg-red-500 text-white rounded px-4 py-2"
onclick='return confirm("コメント「{{ $comment->content }}」を削除しますか?");'>
削除
</button>
</form>
<button class="bg-green-600 hover:bg-green-500 text-white rounded px-4 py-2 mr-2"
type="button" onclick="location.href='{{ route('edit_comment', $comment['id']) }}'">
編集
</button>
</div>
@endif
@endauth
</div>
@empty
<p>コメントはまだありません。</p>
@endforelse
@auth
<h2>コメントを投稿する</h2>
<form class="grid grid-cols-1 gap-6 text-black" method='POST' action="{{ route('store_comment') }}" enctype="multipart/form-data">
@csrf
<input type='hidden' name='post_id' value="{{ $post['id'] }}">
<label class="block">
<textarea name='content'
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"
rows="3"></textarea>
</label>
<button type='submit' class="w-20 bg-blue-600 hover:bg-blue-500 text-white rounded px-4 py-2">投稿</button>
</form>
@else
<p>ログインするとコメントを投稿することができます。</p>
@endauth
</x-guest-layout>
記事に著者のユーザー名と記事の作成日・更新日を表示させる
続きまして、記事の上のほうに、著者のユーザー名と記事の作成日、更新日を表示したいと思います。そのために、ユーザーと記事を紐づけたいので、app/Models/User.php と app/Models/Post.php を次のようにします。
<?php
namespace App\Models;
use App\Models\Comment;
use App\Models\Post; // 追記
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Fortify\TwoFactorAuthenticatable;
use Laravel\Jetstream\HasProfilePhoto;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens;
use HasFactory;
use HasProfilePhoto;
use Notifiable;
use TwoFactorAuthenticatable;
/**
* The attributes that are mass assignable.
*
* @var string[]
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* @var array
*/
protected $hidden = [
'password',
'remember_token',
'two_factor_recovery_codes',
'two_factor_secret',
];
/**
* The attributes that should be cast.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
/**
* The accessors to append to the model's array form.
*
* @var array
*/
protected $appends = [
'profile_photo_url',
];
public function comments()
{
return $this->hasMany(Comment::class);
}
/**
* 追記
*/
public function posts()
{
return $this->hasMany(Post::class);
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Models\Comment;
use App\Models\User; // 追記
class Post extends Model
{
use HasFactory;
public function comments()
{
return $this->hasMany(Comment::class);
}
/**
* 追記
*/
public function user()
{
return $this->belongsTo(User::class);
}
}
そして、resources/views/post.blade.php を次のように編集します。(なお、18行目と25行目の whitespace-pre-wrap は、テキストが長い場合に右端で折り返して表示させるために入れました。)
<x-guest-layout>
<x-slot name="title">{{ $post['title'] }}</x-slot>
<h1>{{ $post['title'] }}</h1>
<!-- この div タグを追加 -->
<div class="bg-orange-300 font-bold p-2 mb-2">
著 者:{{ $post->user->name }}<br>
<time datetime="{{ $post['created_at'] }}" itemprop="datepublished">
作 成:{{ (new DateTime($post['created_at']))->format("Y年m月d日") }}<br>
</time>
<time datetime="{{ $post['updated_at'] }}" itemprop="modified">
最終更新:{{ (new DateTime($post['updated_at']))->format("Y年m月d日") }}
</time>
</div>
<div class="not-prose">
<pre class="whitespace-pre-wrap">{{ $post['content'] }}</pre>
</div>
<h2>みんなのコメント</h2>
@forelse ($comments as $comment)
<div class="bg-gray-300 p-2 mb-4 not-prose">
<span class="text-blue-700">{{ $comment->user->name }} さんのコメント:</span><br>
<pre class="whitespace-pre-wrap">{{ $comment['content'] }}</pre>
@auth
@if ($comment->user->id === Auth::id())
<div class="flex flex-row-reverse mt-1">
<form method='POST' action="{{ route('delete_comment', $comment['id']) }}">
@csrf
<button type='submit' class="bg-red-600 hover:bg-red-500 text-white rounded px-4 py-2"
onclick='return confirm("コメント「{{ $comment->content }}」を削除しますか?");'>
削除
</button>
</form>
<button class="bg-green-600 hover:bg-green-500 text-white rounded px-4 py-2 mr-2"
type="button" onclick="location.href='{{ route('edit_comment', $comment['id']) }}'">
編集
</button>
</div>
@endif
@endauth
</div>
@empty
<p>コメントはまだありません。</p>
@endforelse
@auth
<h2>コメントを投稿する</h2>
<form class="grid grid-cols-1 gap-6 text-black" method='POST' action="{{ route('store_comment') }}" enctype="multipart/form-data">
@csrf
<input type='hidden' name='post_id' value="{{ $post['id'] }}">
<label class="block">
<textarea name='content'
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"
rows="3"></textarea>
</label>
<button type='submit' class="w-20 bg-blue-600 hover:bg-blue-500 text-white rounded px-4 py-2">投稿</button>
</form>
@else
<p>ログインするとコメントを投稿することができます。</p>
@endauth
</x-guest-layout>
コメント