Problem
I created a form with title, body and tag input and there are 3 tables: posts, tags and post_tag.
Now I use this function to add new tags and attach them to the post
postcontroller.php
public function store(Request $request)
{
$input = $request->all(); //get inputs value
$tag = $input['tag'];
$tagdone = Tag::create(['name'=>$tag]);
$tagid = $tagdone->id; //insert tag to tags table
$posts = Posts::create($input); //insert posts table
$postid = $posts->id;
Posts::find($postid)->tags()->attach($tagid); //attach tag to the post
}
There are actually 3 actions at the same time. But I think there are better ways than this one, so I’d like some feedback on what I’ve written.
Solution
Use the following:
public function store(Request $request)
{
$input = $request->all(); //get inputs value
$tag = $input['tag'];
$tagdone = Tag::create(['name'=>$tag]);
$tagid = $tagdone->id; //insert tag to tags table
$posts = Posts::create($input); //insert posts table
$posts->tags()->attach($tagid); //attach tag to the post
}
This will reduce your database queries by one SELECT
by removing Posts::find($postid)
.
Apart from the above, is there any reason for using three database tables? Just from the code provided it doesn’t seem to be necessary and I would only use one table with all three inputs. Or at least reduce to two database tables as follows:
public function store(Request $request)
{
$input = $request->all(); //get inputs value
$tag = $input['tag'];
$tagdone = Tag::create(['name'=>$tag]); //insert tag to tags table
$input['tagid'] = $tagdone->id;
$posts = Posts::create($input); //insert posts table, including tagid
}
First, a very small thing: it would me somewhat more convention to name your model Post
instead of Posts
. If you are attached to Posts
, then Tag
should also be plural.
Currently, it appears that you create a new Tag each time, even if you already have a Tag by the same name. This could be what you want, but in case it isn’t, try changing:
$tagdone = Tag::create([‘name’=>$tag]); //insert tag to tags table
to
$tagdone = Tag::findOrCreate(['name'=>$tag]); //insert tag to tags table
Now, assuming you do want to create a new Post every time the form is submitted, you can use the relationships you define in your models to do more work for you.
Bringing together a few ideas:
public function store(Request $request)
{
$input = $request->all();
$post = Post::create($input);
$tag = Tag::findOrCreate(['name' => $input['tag']);
$post->tags()->attach($tag->id);
}
On a style note, you don’t need comments when you are doing normal things, they just make it harder to read the code. Comments should explain why you’ve done something unusual or why a future coder needs to be careful.
It looks like you’re off to a great start with Laravel! Hope your project is a success!