has-one-through & has-many-through Laravel Eloquent Relationships (phần 1)

Ví dụ 1: Tạo dữ liệu projects, users, tasks

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]);
  $post  = \App\Post::first();
  $posts = \App\Post::with(['user', 'tags'])->get();
  // $post->tags()->sync([
  //   2 => [
  //     'status' => 'approved',
  //   ],
  // ]);
  // dd($post->tags->first()->pivot->status);
  // Post::delete();
  return view('posts.index', compact('posts'));
});
Route::get('/tags', function () {
  $tags = \App\Tag::with("posts")->get();
  return view('tags.index', compact('tags'));
});
Route::get('/projects', function () {
  // $project = \App\Project::create([
  //   'title' => 'Project B',
  // ]);
  // $user1 = \App\User::create([
  //   'name'       => 'User 1',
  //   'email'      => 'user1@gmail.com',
  //   'password'   => Hash::make('password'),
  //   'project_id' => $project->id,
  // ]);
  // $user2 = \App\User::create([
  //   'name'       => 'User 2',
  //   'email'      => 'user2@gmail.com',
  //   'password'   => Hash::make('password'),
  //   'project_id' => $project->id,
  // ]);
  // $task1 = \App\Task::create([
  //   'title'   => 'Task 1 for project 1 by user 1',
  //   'user_id' => $user1->id,
  // ]);
  // $task2 = \App\Task::create([
  //   'title'   => 'Task 2 for project 1 by user 1',
  //   'user_id' => $user1->id,
  // ]);
  // $task3 = \App\Task::create([
  //   'title'   => 'Task 3 for project 1 by user 2',
  //   'user_id' => $user2->id,
  // ]);
  // $project = \App\Project::create([
  //   'title' => 'Project B',
  // ]);
  // $user1 = \App\User::create([
  //   'name'       => 'User 3',
  //   'email'      => 'user3@gmail.com',
  //   'password'   => Hash::make('password'),
  //   'project_id' => $project->id,
  // ]);
  // $user2 = \App\User::create([
  //   'name'       => 'User 4',
  //   'email'      => 'user4@gmail.com',
  //   'password'   => Hash::make('password'),
  //   'project_id' => $project->id,
  // ]);
  // $user5 = \App\User::create([
  //   'name'       => 'User 5',
  //   'email'      => 'user5@gmail.com',
  //   'password'   => Hash::make('password'),
  //   'project_id' => $project->id,
  // ]);
  // $task1 = \App\Task::create([
  //   'title'   => 'Task 4 for project 2 by user 3',
  //   'user_id' => $user1->id,
  // ]);
  // $task2 = \App\Task::create([
  //   'title'   => 'Task 4 for project 2 by user 3',
  //   'user_id' => $user1->id,
  // ]);
  // $task3 = \App\Task::create([
  //   'title'   => 'Task 5 for project 2 by user 4',
  //   'user_id' => $user2->id,
  // ]);
  // $task6 = \App\Task::create([
  //   'title'   => 'Task 6 for project 2 by user 5',
  //   'user_id' => $user5->id,
  // ]);
  $project = \App\Project::find(1);
  return $project->users[0];
});

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

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Project extends Model {
  protected $guarded = [];
  public function users() {
    return $this->hasMany(User::class);
  }
  public function tasks() {
  	return $this->hasMany(Task::class);
  	// return $this->hasManyThrough(Task::class,User::class);
  }
}

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

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Task extends Model {
	protected $guarded = [];
  public function user () {
  	return $this->belongsTo(User::class);
  }
}

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

<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable {
  use Notifiable;
  /**
   * The attributes that are mass assignable.
   *
   * @var array
   */
  protected $fillable = [
    'name', 'email', 'password','project_id'
  ];
  /**
   * The attributes that should be hidden for arrays.
   *
   * @var array
   */
  protected $hidden = [
    'password', 'remember_token',
  ];
  /**
   * The attributes that should be cast to native types.
   *
   * @var array
   */
  protected $casts = [
    'email_verified_at' => 'datetime',
  ];
  public function address() {
    return $this->hasOne(Address::class);
  }
  public function addresses() {
    return $this->hasMany(Address::class); 
  }
  public function posts() {
    return $this->hasMany(Post::class); 
  }
  public function tasks() {
    return $this->hasMany(Task::class);
  }
}

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

$project = \App\Project::find(1);
return $project->users[0];
$project = \App\Project::find(1);
return $project->users[0]->tasks;

Ví dụ 2: Vấn đề được đặt ra là để lấy dữ liệu từ project đến tasks ta phải sử dụng như sau

$project = \App\Project::find(1);
return $project->users[0]->tasks;

Nhưng bây giờ ta muốn lấy trực tiếp??

$project = \App\Project::find(1);
return $project->tasks;

Như vậy trong C:\xampp\htdocs\hanam.com\app\Project.php

Ta thay

hasMany thành hasManyThrough
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Project extends Model {
  protected $guarded = [];
  public function users() {
    return $this->hasMany(User::class);
  }
  public function tasks() {
  	// return $this->hasMany(Task::class);
  	return $this->hasManyThrough(Task::class,User::class);
  }
}

Last updated