0

I have 2 classes: User and Router

In my script, class User is instantiated first to set user data, then class Router is instantiated to set page data.

$user = new User();
$router = new Router();

Inside one of Router's methods, I need to invoke $user->getSuperPrivileges(). This function queries the DB and sets extra parameters in the $user object, then returns them.

I could pass $user as a parameter of Router($user) and save it as a property in the construct function, but I believe this would only create a clone of the real object. Problem with this is that the values set by $this->user->getSuperPrivileges() would only be accessible by the clone, and not in the global script by the real object. In other words, I would need to invoke the getSuperPrivileges() method once again in the real object to set these properties again, which is counterproductive.

What is the best way to achieve what I want (access the real object $user and its methods from inside $router, without having to create a clone passed as a function parameter)?

3
  • use the $user only in router - which means that you will always call $user via $router->user Commented Feb 9, 2015 at 16:15
  • but I believe this would only create a clone of the real object no, that would not. It is the same object everywhere Commented Feb 9, 2015 at 19:05
  • 1
    Just wanted to add that it sounds fishy that the router needs to know about a user. It sounds like that logic might need to be in another class, depending on what you're doing. Commented Feb 9, 2015 at 19:43

3 Answers 3

1

As pointed out below by @hek2mgl, in php5 every object variable is a reference. The __construct magic method would not work at all prior to that anyway so we can assume that OPs example should work regardless.

http://3v4l.org/6dKL0

The following lines are really pointless given the above example.


have you tried passing the $user object as a reference?

class Router{
  function __contruct(&$user){
    $this->user=$user;
  }
}

new Router($user);

in that case how about a singleton?

function user(&$userO){
  static $user;
  if(!is_array($user)) $user=array();
  if(is_object($userO)) $user[$userO->uid]=$userO;
  if(is_string($userO)) return $user[$userO];
}
class Router{
  function __construct($user){
    $this->uid=$user->uid;
  }
  function __get($k){if($k=='user') return user($this->uid);}
}

To explain a little more, the user function stored the user objects, keyed by a unique identifier in a static array, the __get magic method allows you to intercept calls to the user property on the router object and return the statically saved object from the singleton function.

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

6 Comments

This is what I'm doing right now, but it creates a clone of the $user object, and when I invoke getSuperPrivileges() from $this->user->getSuperPrivileges(), it only sets the new properties to the cloned object, not to the real one. So when I try to access these properties from the real object afterwards, I get an error and need to invoke once again the method...
What is the benefit of passing an object by reference?
Theoretically passing it by reference allows you to edit the object itself rather than just a clone of it
the link that @joey provided is actually a true singleton example, I opt for a wrapper function to handle it because I frequently need to load multiple objects (users) in a single load and it allows me to maintain separate objects. I may be mistaken, but in my experience settings something static in a class actually makes it static for the class and every instantiation of that class rather than on a particular object.
@Trey Every object variable in PHP5 is a reference - not a clone. Check this example: 3v4l.org/K8Rci
|
0

You can create the $user object and inject it into $router object using constructor injection. But what you are doing should be just fine. You should be able to use that object for whatever you need within your router class. Especially if the database maintains the privilege state.

If you must use only one instance of the class check out the section on Singleton patterns at: http://www.phptherightway.com/pages/Design-Patterns.html and you can get an idea of how to achieve this.

Comments

0

I'd try and apply the Dependency Injection pattern. The point is that methods should be passed all they need to operate.

Meaning the method in your router which operates on a user should be passed said user.

class Router {
  method privilegiateUser(User $user) { 
    // notice the typehint
    // php will enforce that your method receives a User
    $user->getSuperPrivileges();
  }
}

I'd disapprove passing the User to your Router's __construct() if it's to be used only once and not with each script run. Think about it that way:

Is a User a property of a Router in the same way than a Name is a property of a User?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.