You'd probably save yourself a bunch of headache by storing start/end dates on the course itself, and updating those values when lessons are added to or removed from a course.
To get the earliest and latest lesson dates in a course you should be able to do this:
$course_dates = DB::table('lessons')
->where('course_id', '=', $course_id)
->select(DB::raw('min(start_date) as earliest'), DB::raw('max(start_date) as latest'))
->get();
If your start/end dates existed on the course fetching courses for those three states would be much easier...
$released = Course::with('lessons')
->where('start_date', '<=', $today)
->where('end_date', '>', $today)
->get();
$expired = Course::with('lessons')
->where('end_date', '<=', $today)
->get();
$unreleased = Course::with('lessons')
->where('start_date', '>', $today)
->get();