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

Ev-genius's avatar

How to get just the data i need for a template?

Hello!

I have three table and one linking table

programs table

id | name
1  | for mass
2  | for strength
exercises table

id | name
1  | arms-exercise-1
2  | arms-exercise-2
3  | arms-exercise-3
4  | arms-exercise-4
5  | legs-exercise-1
6  | legs-exercise-2
7  | legs-exercise-3
8  | legs-exercise-4
timetables

id | week | day_of_week 
1  | odd  | 1
2  | odd  | 2
3  | odd  | 3
4  | odd  | 4
5  | odd  | 5
6  | odd  | 6
7  | odd  | 7
8  | even | 1
9  | even | 2
10 | even | 3
11 | even | 4
12 | even | 5
13 | even | 6
14 | even | 7
exercise_program_timetable linking table

id | program_id | exercise_id | timetable_id
1  |         1→ | 1→          | 1→
2  |         1→ | 2→          | 2→
3  |         1→ | 1→          | 3→
4  |         1→ | 3→          | 4→
6  |         1→ | 1→          | 5→
7  |         1→ | 4→          | 6→
8  |         1→ | 5→          | 7→

And relationships in models

class Program extends Model
{

    public function Exercises()
    {
        return $this->belongsToMany(Exercise::class, 'exercise_program_timetable');
    }

    public function Timetables()
    {
        return $this->belongsToMany(Timetable::class, 'exercise_program_timetable');
    }
}
class Exercise extends Model
{    

    public function Programs()
    {
        return $this->belongsToMany(Program::class, 'exercise_program_timetable');
    }

    public function Timetables()
    {
        return $this->belongsToMany(Timetable::class, 'exercise_program_timetable');
    }

}
class Timetable extends Model
{

    public function Programs()
    {
        return $this->belongsToMany(Program::class, 'exercise_program_timetable');
    }

    public function Exercises()
    {
        return $this->belongsToMany(Exercise::class, 'exercise_program_timetable');
    }

}

My questions:

Firstly, without specifying the linking table

... ::class, 'exercise_program_timetable');

Laravel says I can't find the table... Is this how it should be?

I need to show a schedule of program "for mass" , for example from today and 10 days in advance, based on table "timetables"

in controller

public function show(Program $program)
{
	$program->load('exercise.timetabless')->get();
        return response()->view('programs.show', ['program' => $program]);
}

and trash in view ))

<h4>{{ $program->name }}</h4>

<h5>Odd week</h5>

@for ($i = 1; $i <= 7; $i++)
<ul>
	<li><h6>Day of week: {{ $i }}</h6>
		<ul>
			@foreach ($program->menus as $menu)
				@if ( $menu->week === 'odd' && $menu->day_of_week === $i )
					@foreach ($menu->dishes as $dish)
						<li>{{ $dish->name }}</li>
					@endforeach
				@endif
			@endforeach
		</ul>
	</li>
</ul>
@endfor

Firstly, exercises for the day are shown several times (according to the number of entries in the linking table) Well, and secondly, is it basically wrong?

How can I get only the data I need so that the logic is in the model and so that such a list can be built

Name of program
	Odd week
		Day_of_week(1)
			Exercise_1
			...
			Exercise_N

		Day_of_week(2)
			Exercise_1
			...
			Exercise_N
...
...
...
		Day_of_week(7)
			Exercise_1
			...
			Exercise_N
0 likes
5 replies
automica's avatar

@ev-genius you'll need to specify table name as your belongsToMany is expecting 'exercise_program' as a table name.

  • following Laravel convention, also make sure your method names are camelCased starting lowercase.

eg exercises() & timetables().

  • in your blade you're looping through $program->menus. Wheres that defined, or is that some example you are trying to modify?

  • how do you know whether it is an odd or an even week? where is that defined?

you'll be able to get a list of timetables for 'mass' with the following:

//get the program
$program = Program::where('name','mass')->first();

// get the timetables for this program and group by week.
$timetables = $program->timetables()->groupBy('week');
Ev-genius's avatar

@automica what to do to expect table name "exercise_program_timetable"? I have three models, between which all have a many-to-many relationship How to set relations between three or more tables? Tried change models method names to camelCase... not working

yes, wrong code part, it's from example... can't edit post

correct code

<h4>{{ $program->name }}</h4>

<h5>Odd week</h5>

@for ($i = 1; $i <= 7; $i++)
<ul>
   <li><h6>Day of week: {{ $i }}</h6>
      <ul>
         @foreach ($program->timetables as $timetable)
            @if ( $timetable->week === 'odd' && $timetable->day_of_week === $i )
               @foreach ($menu->exercises as $exercise)
                  @if ($loop->first)
                  <li>{{ $exercise->name }}</li>
                  @endif
               @endforeach
            @endif
         @endforeach
      </ul>
   </li>
</ul>
@endfor

the timetable is compiled for an even and an odd week, and then shown to the user depending on which week is now - even or odd

now odd or even week defined hard in template

week === 'odd'

in future of course it will need to be determined depending on the date on which we show the schedule it doesn't matter yet

how to remove all logic from the template? or is it okay to do this?

automica's avatar

@ev-genius Laravel can't guess when you have a 3 column join table so that's why you are specifying table name. That's fine though.

For your other model relationships, you'll also want to specific the foreign keys

from the docs: https://laravel.com/docs/8.x/eloquent-relationships#many-to-many

class User extends Model
{
    /**
     * The roles that belong to the user.
     */
    public function roles()
    {
        return $this->belongsToMany('App\Models\Role');
    }
}

To determine the table name of the relationship's joining table, Eloquent will join the two related model names in alphabetical order. However, you are free to override this convention. You may do so by passing a second argument to the belongsToMany method:

return $this->belongsToMany('App\Models\Role', 'role_user');

In addition to customizing the name of the joining table, you may also customize the column names of the keys on the table by passing additional arguments to the belongsToMany method. The third argument is the foreign key name of the model on which you are defining the relationship, while the fourth argument is the foreign key name of the model that you are joining to:

return $this->belongsToMany('App\Models\Role', 'role_user', 'user_id', 'role_id');

in your case (if I've got these correct :P )

    class Program extends Model
    {

        public function exercises()
        {
            return $this->belongsToMany(Exercise::class, 'exercise_program_timetable', 'program_id', 'exercise_id');
        }

        public function timetables()
        {
            return $this->belongsToMany(Timetable::class, 'exercise_program_timetable', 'program_id', 'timetable_id');
        }
    }
class Exercise extends Model
{

    public function programs()
    {
        return $this->belongsToMany(Program::class, 'exercise_program_timetable', 'exercise_id', 'program_id');
    }

    public function timetables()
    {
        return $this->belongsToMany(Timetable::class, 'exercise_program_timetable', 'exercise_id', 'timetable_id');
    }

}
class Timetable extends Model
{

    public function programs()
    {
        return $this->belongsToMany(Program::class, 'exercise_program_timetable', 'timetable_id', 'program_id');
    }

    public function exercises()
    {
        return $this->belongsToMany(Exercise::class, 'exercise_program_timetable', 'timetable_id', 'exercise_id');
    }

}
Ev-genius's avatar

@automica thank you for the explanation! Relationship setup is clear!

But I cannot figure out how I can configure the controller to get data for this view.

to put it simply, I need something like this

<h1>
SELECT * from Programs where id=1 // program "for mass" in table, mysite.com/programs/1
</h1>

<h2>Odd week</h2> // defined hard in template while

for ($i = 1; $i <= 7; $i++) // from monday to sunday
<ul>

   <li><h3>Day of week: {{ $i }}</h3> // header for Monday/Thuesday/.../Sunday
      <ul>
         <li>
            SELECT the exercises that are contained in program id=1, on an odd week, on $i day
	    // list of exercises for $i day (Monday/Thuesday/.../Sunday) for odd week
         </li>                  
      </ul>

   </li>
</ul>

How much of the logic should be in the model and how much in the view?

automica's avatar

@ev-genius if you are only looking to display 1 week at a time, you should filter on the week column before passing your blade and that will make your for each simpler

Your query will also be quicker as you are using all the results you are getting.

You should endeavor to keep as much as the logic in the model as you can, as that will make your blades simpler.

you could be looking at a blade as simple as this:

<div class="program">
    <h4>{{ $program->name }}</h4>

    <ul>
        @foreach($program->timetables as $timetable)
            <li>
                <h6>{{ $timetable->day_of_week }}}</h6>
                <ol>
                    @foreach ($timetable->exercises as $exercise)

                        <li>{{ $exercise->name }}</li>

                    @endforeach
                </ol>
            </li>
        @endforeach
    </ul>
</div>

Please or to participate in this conversation.