Reputation: 849
I have 3 tables:
users:
id
first_name
last_name
courses:
id
name
student_courses:
id
student_id
course_id
paid
Users keeps track of the users, courses keep track of the courses, and student_courses is the table that shows what students have signed up for which courses. I currently have a "users" class and a "courses" class. My question is: Should I create a StudentCourses class to handle the interactions for the student_courses table?
ie: I need to create a function that gets all courses a user has signed up for, mark them as paid, etc.
Is it best to do:
$student = new User($userId);
$student->getCourses();
$student->markCourseAsPaid($courseId);
OR
$student = new User($userId);
$studentCourses = new StudentCourses($studentId);
$studentCourses->markCourseAsPaid($courseId);
etc.
Upvotes: 3
Views: 466
Reputation: 316959
If you think about your student_courses
and courses
tables in terms of objects, you will notice that the student_courses
is the really interesting table as it contains the individual objects for the student. They are what you want to have your Student object connect to. What you have in courses
now is just the non-changing part of a course, e.g. it's name and description. Hence, your StudentCourse
instances can simply aggregate that. You only need to load that instance once and then share it across StudentCourse
instances:
For Cohesion, your markAsPaid
method should be on the object with the most information required to fulfill it. In other words, it should be on Course
. However, you can add a payForCourse
proxy method on the Student that then calls markAsPaid
on the appropriate Course
. You might want to introduce a Courses
class that acts as a Repository.
Upvotes: 4
Reputation: 4054
I would create a third class for course_student
that would rely on a table
on your database AND a view
for the following reason, separation of concerns.
You view is used for all the select and the table for insert, update and delete.
Your view would be composed of all the relevant fields of both tables (using 2 inner join
) (students and courses) based on the relations in your course_student
table
A row will look like :
student_id, student_first_name, student_last_name, courses_id, courses_name, is_paid
If you want to get all the students taking a course you can have a method named getStudentsByCourse(courseId)
.
If you want to get all the courses of a specific student you can have a method named getStudentCourses(studentId)
.
If you need to register a set of students for a course (or many) you can have a method named setStudentsCourses(studentId, courseId)
(where both parameters can be either integers or array.
Upvotes: 0
Reputation: 10413
I'd not create the separate class. My approach would be to use something like the following:
$student = new User($userId);
$course = new Course($courseId);
$student->markCourseAsPaid($course);
As the student_courses
table is simply just a relationship, there shouldn't be an extra class. An extra class would imply that it's an entity, which it's not, it's a relationship.
My code differs from yours as I'm first fetching the appropriate Course
instance, then passing that instance to the user. In my opinion it's weird to pass just the ID of the course, since then the User
object just receives a number as parameter, which has no meaning at all. We might not have to ID (primary key) of the course, but a secondary key. Then this method becomes useless since it expects the PK, not some SK. Because I choose to fetch the Course
object first we don't have this problem, as the Course object does know how to retrieve the correct course by a secondary key.
Edit: As this is an objectified relationship, there may be some point in using the extra class. But then I'd go with another approach:
$studentCourse = new StudentCourse($studentId, $courseId);
$studentCourse->markPaid();
As both the student ID and course ID make up for the secondary key of the table, they should both be specified in the constructor.
Upvotes: 0
Reputation: 2844
If you're going to extend the application in the future, I'd create separate class for StudentCourse. Now it has only one additional attribute except join attributes (paid), but when you will need to add another attributes you'll going to create this class anyway.
Upvotes: 3
Reputation: 61
Well in this case it looks like either may work.
usually you would make each model/table a class (i.e. a Student, a Course, a User etc.) in an MVC (model-view-controller) paradigm. Then in each class you might have a variable to relate them. I don't see the need for the StudentCourses class even though the table structure shows a relationship there should be no need for another class. The first example looks more object oriented to me. Again you could do it either way but I always opt for more object-oriented code myself.
Upvotes: 0