I built a blog with Laravel, but I haven't figured out how to add tags to it. I would like to avoid using packages. Here is the code I have so far:
TagsController -
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Tag;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Session;
class TagsController extends Controller
{
public function index() {
$tags = Tags::paginate(4);
return view('dashboard/tags/index', compact('tags'));
}
public function create() {
return view('dashboard/tags/create');
}
public function store() {
$tags = new Tags;
$tags->name= $request->input('name');
$tags->save();
Session::flash('flash_message', 'Tag successfully added!');
return Redirect('/dashboard/tags');
}
}
Tag Model
namespace App;
use Illuminate\Database\Eloquent\Model;
class Tag extends Model
{
public function posts()
{
return $this->belongsToMany('App\Post');
}
}
I'm not sure how to add more than one tag, so I can put it on the posts.
I'm on Laravel 5.3.
A post can have multiple/many tags and a tag can be shared by multiple/many posts. Which basically means that there is a Many-To-Many relationship between Post and Tag.
To define a many-to-many relation you will need 3 database tables
post_tag will have post_id and tag_id with migration as
class CreatePostTagPivotTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('post_tag', function(Blueprint $table)
{
$table->integer('post_id')->unsigned()->index();
$table->foreign('post_id')->references('id')->on('posts')->onUpdate('cascade')->onDelete('cascade');
$table->integer('tag_id')->unsigned()->index();
$table->foreign('tag_id')->references('id')->on('tags')->onUpdate('cascade')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('post_tag');
}
}
The you can define the relationship in respective models as
namespace App;
use Illuminate\Database\Eloquent\Model;
class Tag extends Model
{
public function posts()
{
return $this->belongsToMany('App\Post');
}
}
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public function tags()
{
return $this->belongsToMany('App\Tag');
}
}
Then you can access the relation, like you normally do $tag->with('posts')->get();
to get all posts associated with a tag and so on.
By the way there's a typo in your controller code new Tags
it should be $tag = new Tag;
. The model name that you have is Tag
.
Hope this helps.
Then in your create-post form you could have an input filed like
<input type="text" name="tags" class="form-control"/>
//here you can input ','(comma)separated tag names you want to associate with the post
And in your PostsController
public function store(Request $request)
{
$post = Post::create([
'title' => $request->get('title'),
'body' => $request->get('body')
});
if($post)
{
$tagNames = explode(',',$request->get('tags'));
$tagIds = [];
foreach($tagNames as $tagName)
{
//$post->tags()->create(['name'=>$tagName]);
//Or to take care of avoiding duplication of Tag
//you could substitute the above line as
$tag = App\Tag::firstOrCreate(['name'=>$tagName]);
if($tag)
{
$tagIds[] = $tag->id;
}
}
$post->tags()->sync($tagIds);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With