4
\$\begingroup\$

I've recently started using PHP OOP, and I'm now working on an application where different company representatives can create job offers that candidates can look at.

I have a variety of objects for most entities such as Company, Candidate, Offer.

The problem that I have is that these objects all need to be stored in a database, and I need methods to retrieve the information, create the objects and return them. Since it does not make sense - at least to me with my limited experience in OOP - for an object to have access to the database and be able to fetch itself, I'm using a Database class for each of my main objects that are stored in the database : CompanyDatabase, CandidateDatabase, OfferDatabase.

Each of the aforementionned classes have static methods that retrieve one or multiple "objects" from the database - this is a three-step process, they fetch the data, create the objects and return them.

Here's an example of such a xDatabase class (where x is the name of the class)

class CompanyDatabase{

    public static function getFromID($id)
    {
         $company = Database::query("SELECT * FROM companies WHERE id = ?", [$id]);
         return new Company($company->id, $company->name);
    }

    public static function save($company)
    {
        Database::update("UPDATE compagnies SET name = ? WHERE id = ?", [$company->name, $company-id]);
    }
}

And the Company class in this case :

class Company{

   public $id;
   public $name;

   public function __construct($id, $name)
   {
       $this->id = $id;
       $this->name = $name;
   }
}

I've excluded some code, like the validation to check wether or not data was fetched from the database, because I felt it wasn't relevant to my concerns here.

Is this the proper way of doing it? I end up with two seperate classes for just about every object type that I have, and I'm wondering if I'm doing something wrong and should rather keep everything in one class.

\$\endgroup\$
  • \$\begingroup\$ Welcome to Code Review! I would probably have left whatever was excluded in there, but that's just me preferring the more fleshed-up questions that leave plenty of room for many answers to address many issues/concerns. I hope you get good reviews! \$\endgroup\$ – Mathieu Guindon Jul 14 '15 at 3:17
  • \$\begingroup\$ Why aren't you using any framework? Personally I had use: Doctrine and idiorm. Should check any ORM actually. \$\endgroup\$ – gonzalon Jul 14 '15 at 5:43
  • \$\begingroup\$ @gonzalon I'm using SLIM which is a mini-framework, using it for the MVC implementation. I'll look into using a full-stack framework, but I still want to know how it's done without any framework just to know. \$\endgroup\$ – Drown Jul 14 '15 at 12:37
  • \$\begingroup\$ @Drown I used myself SLIM whit idiorm =) \$\endgroup\$ – gonzalon Jul 15 '15 at 2:34
1
\$\begingroup\$

Using DAOs

The problem that I have is that these objects all need to be stored in a database, and I need methods to retrieve the information, create the objects and return them. Since it does not make sense - at least to me with my limited experience in OOP - for an object to have access to the database and be able to fetch itself, I'm using a Database class for each of my main objects that are stored in the database : CompanyDatabase, CandidateDatabase, OfferDatabase.

You are right that it would not make sense for an object to have access to the database and fetch itself, and you have more or less the right approach. The classes that perform the database operations are commonly called "DAO" -- data access object. (I recommend to rename those classes to CompanyDao, CandidateDao, OfferDao.)

It's not common to make the data accessor methods static. If you use DAO instances instead of static method references, then you get a very flexible design where you could change the backend of your operations by simply passing a DAO instance that implements the same interface, but instead of a database, it transfers data from a web service, or a csv file, or via radio transmissions from the moon.

Class design

Avoid public fields in classes, like $id and $name in Company. Fields are an implementation detail of a class, and should not be easily manipulable from outside, but strictly through dedicated accessor methods.

Working with SQL

Avoid SELECT *. It's recommended to name the columns you need explicitly, for two reasons:

  1. Prevent wasted bandwidth between your program and database fetching unnecessary columns
  2. Make sure you receive the columns in the right order, regardless of their ordering in the table

The SELECT query is from a table called companies, but the UPDATE query is into a table called compagnies. I suspect one of them is a typo. In any case, some frameworks recommend naming tables with singular words, for example in this case I'd go for "company" instead.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.