We notice more and more use-cases for our QuickAdminPanel, and here’s a new demo-project we created to manage a school timetable. It doesn’t necessarily have to be school, it can be applied to any organization with a weekly timetable schedule.


How Does It Look/Work?

At the bottom of the article, you will have a link to the Github repository, but meanwhile, let’s see the features.

In this system, we have three user roles:

  • Teachers
  • Students
  • Administrators

And when a student logs in, they see their own weekly schedule.

Also, every teacher sees only their own timetable.

This timetable is managed by administrators. They enter the lessons, attaching them to a class and to a teacher.

Every student belongs to one class, which means that the class’s timetable becomes every student’s timetable of that class.

Finally, there’s a function for admin to view the schedule for a certain class.


DB Structure

Here’s our database structure:

Tables on the left come from our Roles/Permissions system in QuickAdminPanel, with three roles seeded into the database. And on the right side, we have lessons and classes, both attached to the users but with a different meaning: a user belongs to a class, and a lesson belongs to a teacher user.


Interesting Code Snippets

I won’t list all the code here, as you will have Github repository at the end of the article, but will mention a few things.

Eloquent Query: Local Scopes

We are showing the same calendar, but filtering depending on the parameters – logged in user and GET request query.

Instead of doing that in Controller, we create a Local Scope in the app/Lesson.php model:

class Lesson extends Model
{
    // ...

    public function scopeCalendarByRoleOrClassId($query)
    {
        return $query->when(!request()->input('class_id'), function ($query) {
                $query->when(auth()->user()->is_teacher, function ($query) {
                    $query->where('teacher_id', auth()->user()->id);
                })
                ->when(auth()->user()->is_student, function ($query) {
                    $query->where('class_id', auth()->user()->class_id ?? '0');
                });
            })
            ->when(request()->input('class_id'), function ($query) {
                $query->where('class_id', request()->input('class_id'));
            });
    }
}

And then in the CalendarController, we have this short sentence:

$lessons = Lesson::with('class', 'teacher')
    ->calendarByRoleOrClassId()
    ->get();

Eloquent Accessors

You probably noticed checks like auth()->user()->is_teacher in the code above. These are not real database fields, they are actually attributes inside of app/User.php model:

class User extends Authenticatable
{
    // ...

    public function getIsAdminAttribute()
    {
        return $this->roles()->where('id', 1)->exists();
    }

    public function getIsTeacherAttribute()
    {
        return $this->roles()->where('id', 3)->exists();
    }

    public function getIsStudentAttribute()
    {
        return $this->roles()->where('id', 4)->exists();
    }

}

Constant for Weekdays

This is a debatable decision, cause we could have used Carbon/PHP functions, we be decided to separate weekdays into a constant inside of app/User.php:

const WEEK_DAYS = [
    '1' => 'Monday',
    '2' => 'Tuesday',
    '3' => 'Wednesday',
    '4' => 'Thursday',
    '5' => 'Friday',
    '6' => 'Saturday',
    '7' => 'Sunday',
];

And then, whenever we need them as an array, we do this:

Controller:

$weekDays = Lesson::WEEK_DAYS;
return view('admin.calendar', compact('weekDays'));

Blade:

@foreach($weekDays as $index => $day)
  ...
@endforeach

No Calendar Plugin

Lastly, you will notice that we don’t actually use any library for viewing the calendar, like FullCalendar.

At first, we wanted to use something like AgendaWeek, but then realized that for this project we don’t really need any calendar, a simple HTML table would be totally enough.


Final Repository

As promised, here’s the link for you to download the project, play around and customize: LaravelDaily/Laravel-School-Timetable-Calendar