Search code examples
phplaraveleloquentone-to-manylaravel-relations

Laravel: Use sync or updateOrCreate for updating parent table and child table?


I have a parent table like this:

clubs

id name budget
1 Arsenal 90
2 Chelsea 150
3 Man City 135
4 Man Utd 140
5 Tottenham 87

And a child table like this

players

id club_id name position
1 3 Grealish LM
2 3 Sterling LW
3 3 Haaland ST
4 1 Dybala ST
5 1 Casemiro DM
6 4 Fred DM
7 2 Mbappe ST
8 2 Hazard LW
9 4 Varane DM

The club_id is the foreign key that refer to the clubs table id column

Club Model

public function players()
{
    return $this->hasMany('App\Models\Player', 'club_id', 'id');
}

Player Model

public function club()
{
    return $this->belongsTo('App\Models\Club', 'club_id', 'id');
}

I have an array input and logic to create a club and player like this:

// the array create input will contain the club and all the players that is related to the club
$createInput = array(
  'title' => 'Liverpool',
  'budget' => '70'
  'players' => [
      [ 
         'name' => 'Handerson',
         'Position' => 'CM'
      ],
      [ 
         'name' => 'Milner',
         'Position' => 'LW'
      ]
   ]
);

$club = new Club;
$club->name = $createInput['name];
$club->budget = $createInput['name];
$club->save();
foreach($createInput['players'] as $playerInput){
  $player = new Player;
  $player->name = $playerInput['name'];
  $player->position = $playerInput['position'];
  $player->save();
}]

and I have an array input and logic to update club and player like this:

// the array update input will contain the club and all the players that are related to the club

$updateInput = array(
  'id'.  => 1,
  'budget' => '50',
  'players' => [
      [ 
         'id' => '4',
         'name' => 'Dybala',
         'Position' => 'ST'
      ],
      [ 
         'name' => 'Sane',
         'Position' => 'LW'
      ],
      [ 
         'name' => 'De Ligt',
         'Position' => 'DF'
      ]
   ]
);

$club = Club::find($updateInput['id']);
if(isset($updateInput['name'])) $club->name = $updateInput['name'];
if(isset($updateInput['budget'])) $club->budget = $updateInput['budget'];
$club->save();

$existingIds = [];
foreach($updateInput['players'] as $playerInput){
  if(isset($playerInput['id'])) $player = Player::find($playerInput['id']);
  else $player = new Player;
  if(isset($updateInput['name'])) $player->name = $playerInput['name'];
  if(isset($updateInput['position'])) $player->name = $playerInput['position'];
  $player->save();
  $existingIds[] = $player->id;
}

//if the player id is not in the input data then delete it 

DB::table('players')->whereNotIn('id', $existingIds)->where('club_id', $club->id)->delete();

I'm planning to simplify my code by using the sync and createorupdate method, but i'm not sure which one is more suitable for inserting/updating/deleting related players data which are connected to the clubs table?


Solution

  • You have a defined relationship then why not used that:

    When you are creating a new records:

    $club = new Club;
    $club->name = $createInput['name];
    $club->budget = $createInput['name];
    $club->save();
    
    // club_id automatic attach with players
    $club->players()->createMany( $createInput['players'] );
    

    While updating records with relationship:

    $club = Club::find($updateInput['id']);
    if(isset($updateInput['name'])) $club->name = $updateInput['name'];
    if(isset($updateInput['budget'])) $club->budget = $updateInput['budget'];
    $club->save();
    
    foreach($updateInput['players'] as $playerInput){
        $playerData = $club->players()->updateOrCreate(
            ['id' => $playerInput['id']],
            ['name' => $playerInput['name'], 'position' => $playerInput['position']]
        );
    }
    

    When you needed deleting records with parent relationship:

    $club = Club::find( $id_of_club );
    $club->players()->delete();