1

I was starting a project today and after designing the database structure and how the data would be stored etc, I started the implementation. I am doing this on php, but the language isn't really relevant here, since my doubts are more architectured related or I guess, since I'm struggling more than I thought by implenting stuff in OOP on PHP. (Recently jumped on php, I've been coding in c++ and java before).

So, I started by creating my "User" class, simple as that, few attributes, and __construct, insert, update and delete methods. Those last 3, queries to the db.

Then this doubt came to my head, and I probably know the answer myself but I just don't find out.

I can now create instances and create new Users: $user = new User("John", 34) but, what if I want to edit the user "Dave"? Or I want to show all users. That method, for example, getAllUsers() which would return all users where would be implemented? Because it doesn't really belong to the class User right? If it did, then how I would instance that method if I don't have any User instance?

I guess, I would need a class Users, or UserCollection which would be a collection of all the users, with the methods ´getCertainUser(id)´ and ´getAllUsers()´ which would return certain User or All of them, now then I would have a User I would be able to edit. That is the way I've did in both Java and C++, since I didn't use a database to store the data, it was stored on a Set/Map or whatever the structure, and then saved on files.

That being said, my questions is, how this problem should be addressed as the way to go, Am I complicating things too much? How this should be solved 'the correct way' in OOP. The times I've handled similar problems I've never used a database, so having a collection of users was the only way to store them, but having the database which stores the users feels redundant to have that collection of users.

Thanks in advance.

4

If you're looking for 'the correct way' to marry Object Oriented code with Relational Database persistence, you're going to be sorely disappointed. There is no single 'correct way', only a range of options.

Some would recommend separating your concerns (as AvetisG has suggested in his answer), by putting business logic in one class and persistence logic in another. An example of this, using the Repository pattern, is given in this SO question/answer.

Others feel perfectly fine combining all of the User-related stuff, including persistence, in the same object. An example of this is the Active Record pattern.

I would suggest you familiarize yourself with these alternatives, and then go with whatever makes the most sense to you. In the end, that'll be the most correct way.

3

The problem should be addressed by separating concerns

Here is what I mean.

The reason why you have a bad feeling about adding the getAllUsers() to the User class is because it is too much responsibility for that class. This could convolute things down the line - especially when trying to test things.

My suggesting would be to rethink the way you are doing it.

Instead of making the User class know about all of those things such as inserting itself, updating itself and maybe returning all of the users - make it instead a DTO object that doesn't know about anything.

Then have a UserManager that takes in that DTO which can insert it into the database, update it, delete it and have a UserReader or UserRetriever (or some other name that gets the point across) that either returns back all users as a list of DTOs or a specific user based on the id.

This way it makes testing easier and makes sense conceptually which is key when - you want others to contribute to the project or just maintain it yourself.

  • was about to upvote until you suggested they implement an anemic domain model by design... – TheCatWhisperer Feb 28 '18 at 14:21
0

Relational databases deal with Sets. If want a flexable and usable OO implementations you classes should also be sets ie. collections.

So you have a class "Users" which is a collection of "User" classes.

You need to support the following methods:--

   Users.loadById(id)   // get one user from db
   Users.loadAll()      // definately not scalable !
   Users.loadWithFilter("sql where clause") 

   Users.first()       // first user in result set
   Users.next()        // next user in result set
   Users.byId(id)      // search for specific user id in current set

   Users.Update(id)    // make changes persistant in db for an indvidual entry
   Users.Delete(id)    // delete individual user from db
   Users.New(User)     // Insert new user into database.

So all you SQL handling is in the Users class, the User class contains just the column values.

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.