2

Concise: How I can avoid using static methods in a model?

Loquacious: Suppose I have a user class. Having userID I can get user name by (new user($userID))->getUserName(). Fine, what if I want to lookup a user? (new user())->lookup($uname, $pass). Still fine, but the latter case could be done via a simple static method user::lookup($uname, $pass)!
Some thoughts:

  • It's OK! Use (new object())->method() whenever you want. So should I create a hollow object to call a function?
  • Move this function out of your model. If it needs a DB lookup, where is better than Model context?
  • Define it as a static method. So isn't it lame to have a mixture of public and static methods in a class?

Side note: I've searched this question, no avail!

2 Answers 2

2

Move this function out of your model. If it needs a DB lookup, where is better than Model context?

Yes, indeed, this is the best way to solve the problem.

Currently your User class violates single responsibility principle which basically, says "one task - one class".

Right now your User describes user entity/state and handles persistence (in your case - retrieval from database). See, two things.

I suggest you create another class that is going to handle persistence tasks, like add/update/delete user. The simplest solution is to create a primitive repostitory, like this:

<?php class UserRepository { public function addUser(User $user); public function updateUser(User $user); public function deleteUser(User $user); public function getUserById($id); } 

Then retrieval of user can be done in the following manner:

// get an instance of this repository class $userRepository = new UserRepository; // ask it to find and return user from the database by ID $user = $userRepository->getUserById($_GET['id']); 

Easy to read, easy to handle, right?

This UserRepository class is actually a primitive implementation of Repository Pattern. UserRepository emulates an in-memory collection of all of your users, hiding implementation inside. It hides actual persistence mechanism from you as user: imagine, your coleague would write this class and you're just using its methods, like UserRepository::getById(1) - you don't even know/care if it grabs data from files/db/API. That's neat. )

This particular implementation is described very clearly in Kristopher Wilson's book "The Clean Architecture in PHP", which I highly recommed for you to read: it will take you two-three evenings, and push you to the next level.

You can extend the list of methods, of course, add lookups, etc.

class UserRepository { public function getByCompany(Company $company); public function getByEmail($email); public function countTotal(); } 

In fact, every time you need to grab/add/update user in the database, you should do it via this repository.

I would like to emphasize that this is a simple implementation of the pattern, particularly, if you compare it to what Martin Fowler describes as Repository. However, in most cases it's totally fine.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks @Georgy, Suppose I switch things to the structure you mentioned. WHat about methods like lookup, where I have to place this method?
These methods should also be implemented in your UserRepository. I'll add details to the answer now.
0
  • It's OK! Use (new object())->method() whenever you want. So should I create a hollow object to call a function?

    depends on how much creating an instance will cost

  • Move this function out of your model

    Factory Pattern comes in mind here.

    notes here:

    What happens when $userID in the first call do not exists?

    Isnt your lookup() method not creating 2 instances at one call, first for lookup, second the found one that is returned?

A FactoryPattern for example can have findByID() or findByName() and return an UserObject. And all that should not depend on this syntax at all: (new object())->method(), that is nice, but not always best practise.

6 Comments

I see, but what should I do?
The UserRepository implementaion above is one way, and he has some very good points. Seperate as much as possible. The User Class should in the end nothing more than bunch of setter an getter of properties.
I still want to know should I put this method as static or not? Should I move it out of user class?
Why not let the User class do _construct($id or [$n,$p]); and do the lookup internal on the args that are give? Whatever, i had also questions for you to thing about, your major problem is the structure of your application (that not can only use MVC) and that cant answered here. My short answer woulde be: Do it like you want, all is possible, but not everthing is good.
Are you suggesting to let my user class accept userID or even user name and password?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.