Looking for a simple way of doing the following in Laravel 5.
Imagine these models and interface
A competition will have a many-to-many relationship to is participants, which can be either users or teams. So I need the competition_participant pivot table to have the following columns to define the models
But how do I write a relation on the Competition model, so it knows which model it should fetch from the database, and at the same time return a collection of mixed models or of the Interface type?
You had some confusions about which tables should get which columns.
Your participants table needs to be a table for managing the polymorphic relations of users and teams. It receives a particpatable_id and particpatable_type as well as an id and timestamps() at the very minimum.
Then you need an additional table called competition_participant which will manage the belongs to many between competitions and your polymorphic table participants.
This will allow you to relate your participants to your competitions. This way, you can grab all participants by a competition, call the $participant->participatable attribute on it which would return either an App\User or an App\Team depending on what type the participant is.
This is all tested.
public function up()
{
Schema::create('competitions', function(Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
Schema::create('teams', function(Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
Schema::create('participants', function(Blueprint $table) {
$table->increments('id');
$table->integer('participatable_id');
$table->string('participatable_type');
$table->timestamps();
});
Schema::create('competition_participant', function(Blueprint $table) {
$table->integer('competition_id');
$table->integer('participant_id');
});
}
class Competition extends Model
{
public function participants()
{
return $this->belongsToMany(Participant::class);
}
}
class Participant extends Model
{
public function participatable()
{
return $this->morphTo();
}
public function competitions()
{
return $this->belongsToMany(Competition::class);
}
}
class Team extends Model
{
public function participants()
{
return $this->morphMany(Participant::class, 'participatable');
}
}
class User extends Authenticatable
{
public function participants()
{
return $this->morphMany(Participant::class, 'participatable');
}
}
public function run()
{
$faker = Faker\Factory::create();
// Seed Users Table
DB::table('users')->delete();
$users = [];
for($i = 0; $i < 100; $i++) {
$users[] = [
'name' => $faker->name,
'email' => $faker->email,
'password' => Hash::make($faker->password),
'created_at' => new DateTime,
'updated_at' => new DateTime
];
}
DB::table('users')->insert($users);
// Seed Teams Table
DB::table('teams')->delete();
$teams = [];
for($i = 0; $i < 20; $i++) {
$teams[] = [
'name' => 'Team ' . ucwords($faker->domainWord),
'created_at' => new DateTime,
'updated_at' => new DateTime
];
}
DB::table('teams')->insert($teams);
// Seed Participants Table
DB::table('participants')->delete();
// Insert some of our users as participants
$users = App\User::limit(20)->orderByRaw('rand()')->get();
foreach($users as $user) {
$user->participants()->create([]);
}
// Insert some of the teams as participants
$teams = App\Team::limit(10)->orderByRaw('rand()')->get();
foreach($teams as $team) {
$team->participants()->create([]);
}
// Seed Competitions Table
DB::table('competitions')->delete();
$competitions = [];
for($i = 0; $i < 10; $i++) {
$competitions[] = [
'name' => $faker->company,
'created_at' => new DateTime,
'updated_at' => new DateTime,
];
}
DB::table('competitions')->insert($competitions);
// Seed Competitions Participants Relationships
DB::table('competition_participant')->delete();
// Sign up each participant to 3 random competitions
$participants = App\Participant::all();
$competitions = App\Competition::all();
foreach($participants as $participant) {
$participant->competitions()->sync($competitions->shuffle()->take(3));
}
}
$competition = App\Competition::with('participants')->has('participants')->first();
foreach($competition->participants as $participant) {
echo get_class($participant->participatable); // Will output either App\User or App\Team
echo "<br />";
}
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