Many To Many relationship - belongsToMany() - Laravel Eloquent Relationships

Một chú ý đặc biệt về cách đặt key cho belongsToMany

app\Models\Admin.php

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class Admin extends Authenticatable
{
    use HasFactory, Notifiable;
    public $timestamp = false;
    protected $table = 'tbl_admin';
    protected $primaryKey = 'admin_id';
    protected $fillable = [
        'admin_email',
        'admin_password',
        'admin_name',
        'admin_phone'
    ];
    public function getAuthPassword(){
        return $this->admin_password;
    }
    public function roles()
    {
        return $this->belongsToMany(Role::class, 'admin_roles');
    }
    public function hasRole($role){
        if($this->roles()->where('name',$role)->first()){
            return true;
        }
        return false;
    }
}

app\Models\Role.php

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
    use HasFactory;
    public $timestamps = false;
    protected $table = 'tbl_roles';
    protected $primaryKey = 'roles_id';
    protected $fillable = [
        'name'
    ];
}

app\Http\Controllers\UserController.php

<?php
namespace App\Http\Controllers;
use App\Models\Admin;
use App\Imports\UsersImport;
use App\Exports\UsersExport;
use Maatwebsite\Excel\Facades\Excel;
use App\Http\Controllers\Controller;
class UserController extends Controller {
    public function __construct()
    {
        $this->middleware('auth');
    }
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $admin = Admin::with('roles')->orderBy('admin_id','DESC')->paginate(5);
        return view('admin.users.all_users')->with(compact('admin'));
    }
    public function import()
    {
        Excel::import(new UsersImport, storage_path('users.xlsx'));
        return redirect('/')->with('success', 'All good!');
    }
    public function export()
    {
        return Excel::download(new UsersExport, 'tests.xlsx');
    }
}

Ví dụ 1: Create Tag

<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
 */

Route::get('/', function () {
  return view('welcome');
});
Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');
// Route::get('/user', function(){
//   factory(\App\User::class,5)->create();
// });
Route::get('/user', function () {
	// $user  = factory(\App\User::class)->create();
	// \App\Address::create([
	// 	"user_id" => $user->id,
	// 	"country" => "Ha Nam 10"
	// ]);
	// $user->address()->create([
	// 	"country" => "Ha Nam 9"
	// ]);
  // $users = \App\User::all();
  // $addresses = \App\Address::all();
  // $users = \App\User::with('addresses')->get();
  // $users = \App\User::get();
  // Hoặc dùng cách khác 
  // $users = \App\User::with('posts')->get();
  // $users = \App\User::has('posts','>=',2)->with('posts')->get();
  // $users = \App\User::whereHas('posts',function($query) {
  // 	$query->where('title','like','%Post 2%');
  // })->with('posts')->get();
  $users = \App\User::doesntHave('posts')->with('posts')->get();
  // $users[0]->posts()->create([
  // 	"title" => "Post 1 Test"
  // ]);
  // $users[2]->posts()->create([
  // 	"title" => "Post 2 Test"
  // ]);
  return view('users.index', compact('users'));
});
Route::get('/posts', function () {
	// \App\Post::create([
	// 	'user_id' => 1,
	// 	'title' => 'Post title 1'
	// ]);
	// $posts = \App\Post::get();
  \App\Tag::create([
    'name' => 'Lavarel'
  ]);
  \App\Tag::create([
    'name' => 'PHP'
  ]);
  \App\Tag::create([
    'name' => 'Javascript'
  ]);
  \App\Tag::create([
    'name' => 'VueJs'
  ]);
	// return view('posts.index',compact('posts'));
});

Ví dụ 2: Tạo post_tag

<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
 */

Route::get('/', function () {
  return view('welcome');
});
Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');
// Route::get('/user', function(){
//   factory(\App\User::class,5)->create();
// });
Route::get('/user', function () {
	// $user  = factory(\App\User::class)->create();
	// \App\Address::create([
	// 	"user_id" => $user->id,
	// 	"country" => "Ha Nam 10"
	// ]);
	// $user->address()->create([
	// 	"country" => "Ha Nam 9"
	// ]);
  // $users = \App\User::all();
  // $addresses = \App\Address::all();
  // $users = \App\User::with('addresses')->get();
  // $users = \App\User::get();
  // Hoặc dùng cách khác 
  // $users = \App\User::with('posts')->get();
  // $users = \App\User::has('posts','>=',2)->with('posts')->get();
  // $users = \App\User::whereHas('posts',function($query) {
  // 	$query->where('title','like','%Post 2%');
  // })->with('posts')->get();
  $users = \App\User::doesntHave('posts')->with('posts')->get();
  // $users[0]->posts()->create([
  // 	"title" => "Post 1 Test"
  // ]);
  // $users[2]->posts()->create([
  // 	"title" => "Post 2 Test"
  // ]);
  return view('users.index', compact('users'));
});
Route::get('/posts', function () {
	// \App\Post::create([
	// 	'user_id' => 1,
	// 	'title' => 'Post title 1'
	// ]);
	// $posts = \App\Post::get();
  // \App\Tag::create([
  //   'name' => 'Lavarel'
  // ]);
  // \App\Tag::create([
  //   'name' => 'PHP'
  // ]);
  // \App\Tag::create([
  //   'name' => 'Javascript'
  // ]);
  // \App\Tag::create([
  //   'name' => 'VueJs'
  // ]);
  // $tag = \App\Tag::first();
  $post = \App\Post::first();
  // $post->tags()->attach($tag);
  $post->tags()->attach([1,2,3,4]); //$post->tags()->sync([1,2,3,4]);
	// return view('posts.index',compact('posts'));
});

Ngoài ra chúng ta cũng có thể sử dụng $post->tags()->sync([1,2,3,4]); để update tag

Đặc biệt chúng ta có thể viết ngắn gọn

Thay vì viết:
$tag = \App\Tag::first(); $post = \App\Post::first();
Chúng ta viết:
$post = \App\Post::with('tags')->first();

Ví dụ 3: Get tags of post

<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
 */

Route::get('/', function () {
  return view('welcome');
});
Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');
// Route::get('/user', function(){
//   factory(\App\User::class,5)->create();
// });
Route::get('/user', function () {
	// $user  = factory(\App\User::class)->create();
	// \App\Address::create([
	// 	"user_id" => $user->id,
	// 	"country" => "Ha Nam 10"
	// ]);
	// $user->address()->create([
	// 	"country" => "Ha Nam 9"
	// ]);
  // $users = \App\User::all();
  // $addresses = \App\Address::all();
  // $users = \App\User::with('addresses')->get();
  // $users = \App\User::get();
  // Hoặc dùng cách khác 
  // $users = \App\User::with('posts')->get();
  // $users = \App\User::has('posts','>=',2)->with('posts')->get();
  // $users = \App\User::whereHas('posts',function($query) {
  // 	$query->where('title','like','%Post 2%');
  // })->with('posts')->get();
  $users = \App\User::doesntHave('posts')->with('posts')->get();
  // $users[0]->posts()->create([
  // 	"title" => "Post 1 Test"
  // ]);
  // $users[2]->posts()->create([
  // 	"title" => "Post 2 Test"
  // ]);
  return view('users.index', compact('users'));
});
Route::get('/posts', function () {
	// \App\Post::create([
	// 	'user_id' => 1,
	// 	'title' => 'Post title 1'
	// ]);
	// $posts = \App\Post::get();
  // \App\Tag::create([
  //   'name' => 'Lavarel'
  // ]);
  // \App\Tag::create([
  //   'name' => 'PHP'
  // ]);
  // \App\Tag::create([
  //   'name' => 'Javascript'
  // ]);
  // \App\Tag::create([
  //   'name' => 'VueJs'
  // ]);
  // $tag = \App\Tag::first();
  // $post = \App\Post::first();
  // // $post->tags()->attach($tag);
  // $post->tags()->attach([1,2,3,4]);
  $posts = \App\Post::with(['user','tags'])->get();
	return view('posts.index',compact('posts'));
});

Ví dụ 4: Delete tags of post

<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
 */

Route::get('/', function () {
  return view('welcome');
});
Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');
// Route::get('/user', function(){
//   factory(\App\User::class,5)->create();
// });
Route::get('/user', function () {
	// $user  = factory(\App\User::class)->create();
	// \App\Address::create([
	// 	"user_id" => $user->id,
	// 	"country" => "Ha Nam 10"
	// ]);
	// $user->address()->create([
	// 	"country" => "Ha Nam 9"
	// ]);
  // $users = \App\User::all();
  // $addresses = \App\Address::all();
  // $users = \App\User::with('addresses')->get();
  // $users = \App\User::get();
  // Hoặc dùng cách khác 
  // $users = \App\User::with('posts')->get();
  // $users = \App\User::has('posts','>=',2)->with('posts')->get();
  // $users = \App\User::whereHas('posts',function($query) {
  // 	$query->where('title','like','%Post 2%');
  // })->with('posts')->get();
  $users = \App\User::doesntHave('posts')->with('posts')->get();
  // $users[0]->posts()->create([
  // 	"title" => "Post 1 Test"
  // ]);
  // $users[2]->posts()->create([
  // 	"title" => "Post 2 Test"
  // ]);
  return view('users.index', compact('users'));
});
Route::get('/posts', function () {
	// \App\Post::create([
	// 	'user_id' => 1,
	// 	'title' => 'Post title 1'
	// ]);
	// $posts = \App\Post::get();
  // \App\Tag::create([
  //   'name' => 'Lavarel'
  // ]);
  // \App\Tag::create([
  //   'name' => 'PHP'
  // ]);
  // \App\Tag::create([
  //   'name' => 'Javascript'
  // ]);
  // \App\Tag::create([
  //   'name' => 'VueJs'
  // ]);
  // $tag = \App\Tag::first();
  $post = \App\Post::first();
  // $post->tags()->attach($tag);
  // $post->tags()->attach([1,2,3,4]);
  $post->tags()->detach([1]);
  $posts = \App\Post::with(['user','tags'])->get();
	return view('posts.index',compact('posts'));
});

Ví dụ 5: belongsToMany

C:\xampp\htdocs\hanam.com\app\Tag.php

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Tag extends Model
{
  protected $fillable = [
    'name' 
  ];
  public function posts(){
    return $this->belongsToMany(Post::class);
    // return $this->belongsToMany(Post::class,'post_tag','tag_id','post_id'); chưa hiểu rõ
  }
}

C:\xampp\htdocs\hanam.com\resources\views\tags\index.blade.php

@extends('layouts.app')
@section('content')
<div class="row justify-content-center">
	<div class="col-md-8">
		<div class="card">
			@foreach ($tags as $tag)
				<h1>{{$tag->name}}</h1>
					@foreach ($tag->posts as $post)
						<li>{{$post->title}}</li>
					@endforeach
			@endforeach
		</div>
	</div>
</div>
@endsection

C:\xampp\htdocs\hanam.com\routes\web.php

<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
 */

Route::get('/', function () {
  return view('welcome');
});
Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');
// Route::get('/user', function(){
//   factory(\App\User::class,5)->create();
// });
Route::get('/user', function () {
	// $user  = factory(\App\User::class)->create();
	// \App\Address::create([
	// 	"user_id" => $user->id,
	// 	"country" => "Ha Nam 10"
	// ]);
	// $user->address()->create([
	// 	"country" => "Ha Nam 9"
	// ]);
  // $users = \App\User::all();
  // $addresses = \App\Address::all();
  // $users = \App\User::with('addresses')->get();
  // $users = \App\User::get();
  // Hoặc dùng cách khác 
  // $users = \App\User::with('posts')->get();
  // $users = \App\User::has('posts','>=',2)->with('posts')->get();
  // $users = \App\User::whereHas('posts',function($query) {
  // 	$query->where('title','like','%Post 2%');
  // })->with('posts')->get();
  $users = \App\User::doesntHave('posts')->with('posts')->get();
  // $users[0]->posts()->create([
  // 	"title" => "Post 1 Test"
  // ]);
  // $users[2]->posts()->create([
  // 	"title" => "Post 2 Test"
  // ]);
  return view('users.index', compact('users'));
});
Route::get('/posts', function () {
	// \App\Post::create([
	// 	'user_id' => 1,
	// 	'title' => 'Post title 1'
	// ]);
	// $posts = \App\Post::get();
  // \App\Tag::create([
  //   'name' => 'Lavarel'
  // ]);
  // \App\Tag::create([
  //   'name' => 'PHP'
  // ]);
  // \App\Tag::create([
  //   'name' => 'Javascript'
  // ]);
  // \App\Tag::create([
  //   'name' => 'VueJs'
  // ]);
  // $tag = \App\Tag::first();
  // $post = \App\Post::first();
  $post = \App\Post::with('tags')->first();
  // $post->tags()->attach($tag);
  // $post->tags()->attach([1,2,3,4]); // $post->tags()->sync([1,2,3,4]);
  // $post->tags()->detach([1]);
  $posts = \App\Post::with(['user','tags'])->get();
	return view('posts.index',compact('posts'));
});
Route::get('/tags', function () {
  $tags = \App\Tag::with("posts")->get();
  return view('tags.index',compact('tags'));
});

Last updated