OOP design issue

I am relatively new using OOP in PHP. This helped a lot in organizing and maintaining my code, but I would like to improve the design of my classes and use OOP as efficiently as I can. I read The Gang of Four Design Drawings, but I still need help. After creating a few small applications, here is one thing that I keep working on.

Let's say I'm creating an application that tracks school enrollment information.

The way I am now approaching this is to have a class called student and methods inside this class for CRUD for a single student record. It seems logical that I would have a constructor method for this class that took student_id as an argument, so I could reference it from the inside of the object for all these different CRUD operations.

But then, as the application continues to be created, I come across situations where I need to run queries that several students return. For example, something like get_all_students_from_grade($grade) , get_dropdown_of_all_students() , etc. These methods are not applicable to only one student, so it seems strange that I will use them as methods in my student class, since I created an instance of an object with one student_id . Obviously, I can make it work this way, but it looks like I'm "doing it wrong." What is the best way to approach this?

+6
oop php
source share
8 answers

Separate the student class (domain class) from operations on it (business logic or data access, as appropriate), for example:

  • student - the domain object contains only data
  • student_service or student_dao (data access object) - performs operations

This is sometimes considered encapsulation violation, but it is acceptable good practice.

Here is more information on this. This gives more disadvantages in terms of OOP than encapsulation breaks. Therefore, although this is apparently an acceptable practice, it is not entirely OOP.

+4
source share

Break it into two classes:

  • student
  • student_repository

Your student class knows nothing about how it is stored relationally.

 $students = student_repository.get_all_students_from_grade($grade) 
+4
source share

I do not pretend to know the "best" way, but it can help to approach the problem in different ways. Instead of a single class representing a single student, you could make the class a representation of the data interface between your application and the database.

This class will know how to get a bunch (possibly one) of student lines from db, cache them in a local array, allow the application to view cached records, allow changes to cached records, and when this is done write the cached changes back to db (by generating SQL to account for changes).

Thus, you avoid running a separate SQL query for each change (you are still working with a set of rows) and at the same time offer access to individual objects (by maintaining the index at the current location in the cache, and allowing this "pointer" to be advanced application, as it calls the methods of your class)

+1
source share

There is always a starting point. In your case, it will be WHAT you get students (for example, school, class, etc.).

 $class = new Model_Class; $students = $class->students; foreach($students as $student) { print $student->name. ' is in class '. $class->name; } 
+1
source share

I ran into the same problem, I assume you are using MySQL? this is one of the common OOP design issues, since SQL tends to smooth everything.

I solved this by doing the following

1.) create a class that has three instance forms,

where is he new

 $myStudent = new $Student(); 

another where you know the id but need ids data

 $myStudent = new $Student($student_id); 

and another where you already have data in an associative array

 $data = array('id'=13,'name' => 'studentname', 'major' => 'compsci'); $myStudent = new $Student($data['id'], $data); 

This allows you to create a factory class that can run a query from mysql, retrieve an associative data array, and then create student instances from this array data without getting into the database for each student instance.

here is the constructor for this class:

 public function __construct($id=FALSE, $data=FALSE) { if(!$id) $this->is_new = true; else if($id && !$data) $this->get_data_from_db($id); else if($id && $data) $this->set_data($data); } 
+1
source share

You can go with the factory method and factory to decide what the new student ID should be.

Of course, this factory would have to read the database to find out where to start indexing (depending on the number of students in your database), and you will need to decide what to do with remote students (if possible).

As for the methods you described, I donโ€™t understand why you should include them in your class of students. You could, but it should be a static method, not a member method.

0
source share

As Neal said in his comment (not sure why we didnโ€™t give him an answer), you should probably have Course and School classes. You may have special methods related to the school (getting all students in a given class with a given number of days, etc.) in School and course-specific methods (all students in a class with a specific class, etc.) In a Course class .

You are right in thinking that in standard CRUD you do not want to give a class representing an individual (i.e., Student class) to load multiple values โ€‹โ€‹of yourself. On the other hand, if you intend to use the more ActiveRecord style of loading data (this is what Ruby is on Rails), you will actually make the static methods of Student loader static methods of the Student class. It depends on how you want to style it, which partly depends on how complex your data model is.

0
source share

You must do their class methods on Student.

-one
source share

All Articles