iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 9
1
Software Development

30天完成家庭任務平台系列 第 9

30天完成家庭任務平台:第九天

  • 分享至 

  • xImage
  •  

接下來要講的是Eloquent的Has One Through/Has Many Through的關係,這兩個關係相對來說少用,但是在三個Model的狀況時,兩個不連結的Model可以透過中間Model而連結起來,提供便利的效果。

我們用官方文件(Laravel 8)提供的例子來試做Has One Through/Has Many Through的關係:

  1. Has One Through:Mechanic擁有一個Car,Car擁有一個Owner
    • 資料表
          class CreateMechanicsTable extends Migration
  {
     /**
      * Run the migrations.
      *
      * @return void
      */
     public function up()
     {
         Schema::create('mechanics', function (Blueprint $table) {
             $table->id();
             $table->string('name');
             $table->timestamps();
         });
     }
           class CreateCarsTable extends Migration
   {
      /**
       * Run the migrations.
       *
       * @return void
       */
      public function up()
      {

          Schema::create('cars', function (Blueprint $table) {
              $table->id();
         $table->foreignId('mechanic_id')->constrained('mechanics')->onDelete('cascade');
              $table->string('model');
              $table->timestamps();
          });
      }
            class CreateOwnersTable extends Migration
    {
       /**
        * Run the migrations.
        *
        * @return void
        */
       public function up()
       {
           Schema::create('owners', function (Blueprint $table) {
               $table->id();
               $table->string('name');
               $table->foreignId('car_id')->constrained('cars')->onDelete('cascade');
               $table->timestamps();
           });
       }
  • Model
         class Mechanic extends Model
   {
      use HasFactory;
      public function car()
      {
          return $this->hasOne('App\Models\Car');
      }
      public function carOwner()
      {
          return $this->hasOneThrough('App\Models\Owner', 'App\Models\Car');
      }
   }
         class Car extends Model
   {
      use HasFactory;
      public function owner()
      { 
          return $this->hasOne('App\Models\Owner');
      }

      public function mechanic()
      {
          return $this->belongsTo('App\Models\Mechanic');
      }
   }
         class Owner extends Model
   {
      use HasFactory;
      public function car()
      {
          return $this->belongsTo('App\Models\Car');
      }
   }
  • 使用php artisan test 測試:結果通過
         class HaveThroughTest extends TestCase
   {
      use RefreshDatabase;
      /**
       * A basic feature test example.
       *
       * @test
       */
      public function mechanic_have_one_owner_through_car()
      {
          $car = Car::factory()->hasOwner(1)->create();
          $mechanic = $car->mechanic;
          $owner = $car->owner;
          $this->assertTrue($owner->is($mechanic->carOwner));
      }
   ...
   }
  1. Has Many Through:Country擁有很多Visitor,Visitor擁有很多Post
    • 資料表
         class CreateCountriesTable extends Migration
   {
      /**
       * Run the migrations.
       *
       * @return void
       */
      public function up()
      {
          Schema::create('countries', function (Blueprint $table) {
              $table->id();
              $table->string('name');
              $table->timestamps();
          });
      }
       class CreateVisitorsTable extends Migration
  {
     /**
      * Run the migrations.
      *
      * @return void
      */
     public function up()
     {
         Schema::create('visitors', function (Blueprint $table) {
             $table->id();
             $table->foreignId('country_id')->constrained()->onDelete('cascade');
             $table->string('name');
             $table->timestamps();
         });
     }
        class CreatePostsTable extends Migration
  {
     /**
      * Run the migrations.
      *
      * @return void
      */
     public function up()
     {
         Schema::create('posts', function (Blueprint $table) {
             $table->id();
             $table->foreignId('visitor_id')->constrained()->onDelete('cascade');
             $table->string('title');
             $table->timestamps();
         });
     }
  • Model
        class Country extends Model
  {
     use HasFactory;
     public function visitors()
     {
         return $this->hasMany('App\Models\Visitor');
     }

     public function posts()
     {
         return $this->hasManyThrough('App\Models\Post','App\Models\Visitor');
     }
  }
        class Visitor extends Model
  {
     use HasFactory;
     public function country()
     {
         return $this->belongsTo('App\Models\Country');
     }
     public function posts()
     {
         return $this->hasMany('App\Models\Post');
     }
  }
        class Post extends Model
  {
     use HasFactory;
     public function visitor()
     {
         return $this->belongsTo('App\Models\Visitor');
     }

  }
  • 使用php artisan test 測試:結果通過了
        class HaveThroughTest extends TestCase
  {
  ...
  public function country_has_many_postst_hrough_visitors()
     {
         $country = Country::factory()->hasVisitors(4)->create();
         $visitors = $country->visitors;
         foreach($visitors as $visitor){
             Post::factory()->count(2)->create(['visitor_id'=>$visitor->id]);
         }
         $this->assertCount(8,$country->posts);
     }
  }

上一篇
30天完成家庭任務平台:第八天
下一篇
30天完成家庭任務平台:第十天
系列文
30天完成家庭任務平台30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言