Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

stef686's avatar

Help refactoring code - Relationship with key value database store

I'm pretty new to Laravel and working on a system with multiple levels of relationships between database tables.

Briefly, I have a situation involving three database tables - Tournaments, which can have multiple Attendees, and each Attendee's details are stored in a "meta" table, which stores data by key - value (such as their name, address, email, telephone etc).

What I need to do is for a tournament, display a list of attendees using values from the meta table for each one.

Here's where I'm at so far, I have this working, but I want to refactor the code to be more reusable and efficient, plus as I'm new to Laravel I'd like to learn more too.

database tables

Schema::create('tournaments', function (Blueprint $table) {
    $table->increments('id');
    $table->timestamps();
    $table->string('name');
});

Schema::create('attendees', function (Blueprint $table) {
    $table->increments('id');
    $table->timestamps();
    $table->integer('tournament_id')->unsigned();
    $table->index('tournament_id');
});

Schema::create('attendees_meta', function (Blueprint $table) {
    $table->increments('id');
    $table->string('key', 50);
    $table->text('value');
    $table->integer('attendee_id')->unsigned();
    $table->index('key');
    $table->index('attendee_id');
});

There are more fields to the above tables which aren't relevant here. Next my Models:

Tournament Model

namespace App;

use Illuminate\Database\Eloquent\Model;

class Tournament extends Model
{

    /**
     * The attendees relationship
     */
    public function attendees()
    {
        return $this->hasMany('App\Attendees');
    }

}
Attendees Model

namespace App;

use Illuminate\Database\Eloquent\Model;

class Attendees extends Model
{

    /**
     * The tournament relationship
     */
    public function tournament() {
        return $this->belongsTo('App\Tournament');
    }

}
AttendeesMeta Model

namespace App;

use Illuminate\Database\Eloquent\Model;

class AttendeesMeta extends Model
{

    /**
     * The table
     *
     * @var string
     */
    protected $table = 'attendees_meta';

}

I know there should be a one to many relationship between the Attendees and AttendeesMeta, but I couldn't get this to work with that relationship in place.

In my controller I have this:


public function dashboard(Tournament $tournament) {

$data['tournament'] = $tournament;

$attendees = Attendees::where('tournament_id', $tournament->id)->get()->toArray();

foreach ( $attendees AS $attendee ) {
    $attendee['meta'] = AttendeesMeta::where('attendee_id', $attendee['id'])->get()->keyBy('key')->toArray();
    $data['attendees'][] = $attendee;
}
        
return view('manager.dashboard', $data);

}

This allows me in my view to do the following:


@foreach ( $attendees AS $attendee )
{{ $attendee['meta']['name']['value'] }}
{{ $attendee['meta']['email']['value'] }}
@endforeach

I'm sure there's a better way to produce these results and construct these relationships?

0 likes
3 replies
MuhammadTauqeer's avatar

First thing, you should use relations to retrieve records like

$attendees = $tournament->attendees;

Secondly,

You should use eloquent's with function to eager load attendeesMeta while getting attendess records. This way you can get rid of foreach loop.

Just have a look at the documentation, it's very well documented (https://laravel.com/docs/5.0/eloquent#eager-loading).

stef686's avatar

@MuhammadTauqeer Yes that is true, I should be using the relationship to load the attendees.

However, with the attendeesMeta, because I have the keys in the database table, my example code was the only way I could figure out how to get a situation where I could use $attendee['meta']['name']['value']. If I were to simply eager load the attendees via a relationship, I would not be able to reference the name for example.

In an ideal world, I'd like to have a situation where in my controller I can get the tournament, and in my template loop through $tournament->attendees displaying $attendee->meta->name.

jbowman99's avatar

@stef686

in your controller have you tried to fetch

$attendees = Attendees::where('tournament_id', $tournament->id)->with('meta')->get()

if your relationships are correct this should return the entire related model and you would be able to return data from the related model.

for example:

i have a customer model in which has related contacts, i can fetch them

$customer = Customer::where('vdid', $vdid)->with('contacts')->first();

then foreach

@foreach($customer->contacts as $contact)
     {!! $contact->name !!}

Please or to participate in this conversation.