I am trying to allow users to create and add category tags to a post when creating that post in the form.
I would further want those tags to appear in the profile view and function as filter buttons to show posts according to the tag names they possess.
However, in my attempt to achieve this overall result, I am stuck because everytime I submit a post with tags, the tags array keeps showing up empty in the view.
My post table is:
<?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->unsignedBigInteger('user_id');
$table->string('caption');
$table->string('url');
$table->string('image');
$table->text('tags');
$table->timestamps();
$table->index('user_id');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
}
My Post Model is:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;
class Post extends Model
{
use \Conner\Tagging\Taggable;
use HasFactory;
protected $fillable = ['caption','url','image', 'tags'];
public function user()
{
return $this->belongsTo(User::class);
}
protected $dates = [
'created_at',
'updated_at',
];
}
My create and store methods in PostsController are:
public function create()
{
return view('posts.create');
}
public function store(Request $request)
{
$data = request()->validate([
'caption' => 'required',
'url' => 'required',
'image' => ['required', 'image'],
'tags' => 'required',
]);
$tags = explode(", ", $request->tags);
$imagePath = request('image')->store('uploads', 'public');
auth()->user()->posts()->create([
'caption' => $data['caption'],
'url' => $data['url'],
'image' => $imagePath,
'tags' => $data['tags'],
]);
return redirect('/users/' . auth()->user()->id);
}
My form to create post is:
<form action="/posts" enctype="multipart/form-data" method="post">
@csrf
<div class="form-group">
<label for="caption" class="create_caption_label">Post Caption</label>
<div class="create_caption_div">
<input id="caption"
type="text"
class="form-control @error('caption') is-invalid @enderror"
name="caption"
value="{{ old('caption') ?? '' }}"
autocomplete="caption" autofocus>
@error('caption')
<div class="invalid-feedback-div">
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
</div>
@enderror
</div>
</div>
<div class="form-group">
<label for="tags" class="create_tags_label">Tags</label>
<div class="create_tags_div">
<input id="tags"
type="text"
data-role="tagsinput"
class="form-control @error('tags') is-invalid @enderror"
name="tags"
value="{{ old('tags') ?? '' }}"
autocomplete="tags" autofocus>
@error('tags')
<div class="invalid-feedback-div">
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
</div>
@enderror
</div>
</div>
<div class="form-group">
<label for="url" class="edit_title_label">URL</label>
<div class="edit_url_div">
<input id="url"
type="text"
class="form-control @error('url') is-invalid @enderror"
name="url"
value="{{ '' }}"
autocomplete="url" autofocus>
@error('url')
<div class="invalid-feedback-div">
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
</div>
@enderror
</div>
</div>
<div class="create_post_image_div">
<label for="image" class="create_image_label">Post Image</label>
<input type="file" class="form-control-file" id="image" name="image">
@error('image')
<div class="invalid-feedback-div">
<strong>{{ $message }}</strong>
</div>
@enderror
<div class="create_post_btn_div">
<button class="create_post_btn">Save Post</button>
</div>
</div>
</form>
Finally, my view is: (This is where the tags array shows up empty after submitting a post)
@foreach( $user->posts as $post )
<div class="carousel_posts_container">
<div class="post_date_and_edit_div">
<div class="posted_date_div">
<p class="posted_date">posted: {{ $post->created_at->diffForHumans() }}</p>
</div>
<div class="post_edit_div">
<form action="/posts/{{$post->id}}/edit">
<input class="post_edit_btn" type="submit" value="• • •">
</form>
</div>
</div>
<div class="post_counter_div">
<p class="post_counter">1 like</p>
</div>
<div class="post_counter_div">
<p class="post_counter">1 comment</p>
</div>
<div class="carousel_post_img_div">
<img src="/storage/{{ $post->image }}" class="carousel_img_placeholder">
</div>
<div class="like_comment_view_container">
<div class="view_btn_div">
<form action="{{$post->url}}">
<input class="like_comment_view_btns" type="submit" value="( View Post )">
</form>
</div>
<div class="like_btn_div">
<button type="button" class="like_comment_view_btns">( Like )</button>
</div>
<div class="comment_btn_div">
<button type="button" class="like_comment_view_btns">( Comment )</button>
</div>
</div>
<div class="carousel_caption_container">
<div class="carousel_caption_div">
<p class="carousel_caption_username">{{$user->username}} - {{$post->caption}}</p>
<p class="carousel_caption">{{$post->caption}}</p>
</div>
<div class="post-tags mb-4">
<strong>Tags : </strong>
@foreach($post->tags as $tag)
<span class="badge badge-info">{{$tag->name}}</span>
@endforeach
</div>
</div>
</div>
@endforeach
How can I resolve this issue?
And furthermore, how can I allow the tags to function as filter buttons to show posts according to the tag names they possess?
You can save tags as json array in db. Then cast to array in model, so it will be automatically array when you will retrieve. When saving you will pass tags as array then it will automatically convert to json string.
protected $casts = [
'tags' => 'array',
];