1

I code as a hobby so i do not have a formal education on this topic so please excuse me for this question. I really have done a lot of research on this topic but wasnt able to get a clear answer.

what class structure should i choose for database acess in php?

  1. class DatabaseObject and one child class per table as well as a class DatabaseObjectArray wich extends ArrayObject and allows loading multiple DatabaseObjects at once. (i need to be able to iterate over it with a foreach or similar) DatabaseObject has functions load() and store().

  2. class Database and interface DatabaseObject where each table correlates to one class that implements the inteface. Database can be used to load either one object at a time or multiple ones in an array.

where should the sql be done?

if I choose option one i would have some duplicate code between DatabaseObject and DatabaseObjectArray so would it be better to make use an extended PDO class?

For example I want to have an array called $conditions as well as a addCondition($key, $value, $operator = '=') function so that i can first define the condtions and then load() the data into the object.(the sql query is assembled based on $conditions) Should I define these in DatabaseObject and DatabaseObjectArray independently or in an extension of PDO?

  1. or maybe i should define a trait called DatabaseAccess that would be used either in the table classes or in the two Base classes of option 1.
J. Doe
  • 54
  • 1
  • 8
  • Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, as there are too many ways to achieve this. "Best practice" is also completely contextual and depends on very specific scenarios, codebase, etc. You might be better making a good question on https://codereview.stackexchange.com/ and asking if your approach is good or could perhaps be improved. – James May 19 '18 at 13:39
  • 1
    The question is very opinion based. The problem you'll find with many of these "best practices" questions (besides the really basic ones like if you should hash passwords or not) are that there are really no single correct answer. I suggest you look into how Laravel, Symfony and other frameworks do their DB stuff – JimL May 19 '18 at 13:39
  • 1
    @JimL sending people to learn "best practices" from Laravel is about the same as sending someone to North Korea to learn about democracy. And reading though the DBAL of large frameworks is a thankless task. I have done it - it wasn't fun. – tereško May 19 '18 at 13:53
  • @tereško true, but I strongly believe anyone new to PHP have much to learn to try out at least those two frameworks. I don't agree on everything the Symfony guys are doing, and I'm probably disagreeing with even more things Laravel is doing (especially AR). But exploring the most popular options in the PHP world must surely be good learning for anyone new to the language? I wasn't saying they did everything right (which would be weird as they do pretty much the opposite of eachother). But still sounds like good learning – JimL May 19 '18 at 13:54
  • I wasn't really thinking they would go off reading about the system, my natural learning process is to dive in and try some examples and get a feel for how they work with things. – JimL May 19 '18 at 13:55
  • I guess this is a matter of perspective. I believe that someone need to learn the language and understand OOP, before starting to use frameworks, because otherwise one will gain a lot of bad habits, that will be very hard to break. – tereško May 19 '18 at 13:55

1 Answers1

3

Extending PDO is never the "best practice". Actually it's the exact opposite. And traits are just a code-smell, since they are interpreter-driven copy-paste.

IMHO, the best approach is to separate the business logic and the persistence logic. For example: you have a class that does the user-logic and a separate class that saves or populates the instance of this user class. This pattern is called data mapper.

Basically the setup goes like this:

$user = new Entity\User($id);
$mapper = new Mapper\User($pdo);

$mapper->fetch($user);
if ($user->isBanned() && $user->hasExpiredBan(new DateTimeImmutable)) {
    $user->removeBan();
    $mapper->store($user);
}

In this case the mapper does not extend the PDO, but instead uses it as a dependency. As for how to share the same PDO instance with multiple mappers, you can look up this old post.

And for simple example of how mapper itself can be implemented, you can looks at this example.

tereško
  • 58,060
  • 25
  • 98
  • 150
  • It's not my fault Laravel is as popular as it is. But of respect to not polluting your answer I'll pull the comment – JimL May 19 '18 at 13:50