The SitePoint Forums have moved.

You can now find them here.
This forum is now closed to new posts, but you can browse existing content.
You can find out more information about the move and how to open a new account (if necessary) here.
If you get stuck you can get support by emailing forums@sitepoint.com

If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

How to pass around User object

It's about access control: domain object wants to know about current user in order to decide if it may execute some action on behalf of this user or should it deny that action. Or it may just choose slightly different action depending on user.

One possibility would be to give user to domain object constructor. But in some environments user may change during domain object lifetime.

Other possibility would be that domain object require user as method parameter when it needs it. This seems clumsy.

Yet another possibility would be to store user as a global object (or set up a possibility to get it as a singleton). Yes, globals are evil, but doesn't this count as a special case?

Anyway, it would be great if someone told how he/she has solved or would solve similar problem.

Now, anywhere in the class, $this->data is actually bound to the php superglobal array _SESSION at the index defined by USER_SESSION_KEY and therefore anything you tuck into the associative array (like the currently authenticated user, or that users permissions) will be accessible to _ANY_ instance of User that you create.

This was a technique I developed prior to using Test Driven Development

Jason, unless I'm mistaken, what Aivar is looking for is for a way to take that "User" object you showed us, which would probably contain other auth checks (IE: isUserAdmin, isUserManager...) and then make use of it from the domain object, which could be some other object (IE: newsModel - to indulge the eternal example )

Personally, since you are dealing with Authorization/Authentication, I think that a singleton / registry / service approach would be the cleanest. Your model code might look like:

By having a sort of "services manager" or application server, if you will, this can act as the auth object factory, and thus allow your domain objects to acquire auth information from any number of auth validation classes.

The service layer approach is much cleaner from an OOP perspecive . Everyone should have been on the lookout when I mentioned "stealth global" While it is functional, and takes advantage of some nice PHP features, it is a bit of a pain to test.

That being said, if you wanted to use the concept further, you might have some methods like:

My feeling is that the problem should be broken down a bit more. One of the user's properties is atht it is an "entity". That is, it has a unique identity and so you cannot freely copy it when passing it around. If all you want is a bunch of permissions passed around then do this...

PHP Code:

$permissions = $user->getPermissions;

The $permissions object is a constant value object. You can copy it around at will. This should make your problem much less tangled.

I have said a few times that I think a 'User' class is a bad idea, probably to the point of annoying everbody in site , but I think that this illustrates the point again. You have a session (which clearly is an application scope single entity) and a login (a persistent domain entity) which comes from the authenticator (a stateless factory domain service). The Login can ask the Authorisor (a stateless domain service) for a PermissionSet (a domain value object) for the application to read. It sounds more compicated, but it is actually simpler. The classes are far smaller, more cohesive and far less entangled.

Basically entities are complicated things. You have to persist them, prevent them being copied, synchronise them and back them up. Value objects are simpler (copyable) lightweight objects and usually constant once created. Services are stateless, they are just code. If you can make the entities as small as possible and push excess information into other places, it should get easier to handle.

The way you describe it is almost exactly how we currently approach the problem of security at my work. On the other hand, the way I propose above is more of a "ideal situation" scenario, and I wish I had the time to code it like that. In a perfect world that we might never, ever live to see, cross-cutting concerns such as this one are handled in a "aspect oriented" fashion. PHP doesn't have any AOP capabilities, so the closest we can get is the decorator pattern. Ideally, a model factory could return either the "naked" model, dumb to any cross-cutting aspects such as authorization, or a "decorated" one depending on requirements (in this case, one that knows when to request authorization checks). The problem is that, AFAIK, the decorator can only be implemented in PHP via inheritance, and for an unknown number of domain objects (N) you would need at least N decorator classes. That does not appeal to me, I want to code my domain model class once and only once, all other functionality that is common should be inherited.

Does anyone have any suggestions in how to approach this? (assuming I just made any kind of intelligible sense )

I do believe that a User class is valid, for User related stuff, like email etc, but I do feel that Permissions do belong to another class, most like authorisation, as it's authorising whether or not the user is allowed to do something.

Jason, I like your approach, and unless lastcraft shows us some of his magic (which he has certainlydone before ), it's likely the only way to implement this decorator in particular. The only complaint that I have about it is that as the interface of the base class changes (AbstractFoo), then you will have to manually change the corresponding methods in the decorator as well. I wish there was a way around this, it sounds like PHP 5 _call() is exactly what is needed in this case, isnt it? Man, I can't wait to start using the new PHP5 features... my head says "wait until its stable", but my heart longs for it more than is healthy....

Methinks people's confidence in me is about to take a bit of a pasting . What follows is anything but magic. It is brute force eval() and doesn't entirely work anyway.

The idea is that decorators can be generated from the reflection API. This is rather limited in PHP4 and I don't yet have a working PHP5 box so I am rather restricted here. As a result parameters are not passed by reference without some extra work.

The idea is that you only have to override the methods you want to change, the other methods are chained automatically by the do-nothing generated decorator. You have to also explicitely chain those where you must pass references, but for simple classes it could ease the drudge.

To fix the reference issue in the generator, the only thing needed is the parameter count of the method. In PHP4 this means creating some kind of reflection API by parsing the PHP through the tokeniser. If the code is generated from some kind of make file, this might not be so bad.

I got more confidence for setting up User as a global. (Anyway, what the heck, I'm using global database connection so I'm already "at the slippery road to hell" as someone once said, nothing to lose anymore)

There were arguments against putting Permissions into User. I somewhat agree with that. I intend my Users to have a "role" attribute (or maybe list of roles) and each domain object decides what to permit for a role.

There were arguments against putting Permissions into User. I somewhat agree with that. I intend my Users to have a "role" attribute (or maybe list of roles) and each domain object decides what to permit for a role.

Marcus, that is definitely a very interesting approach I hadn't though of. While not the cleanest way to do it, I think I might take it home tonight and try it for myself when I have a bit more time, I have a few modifications in mind .. should be interesting

I also want to try Jason's approach, some of these examples are hard for me to wrap my head around unless I implement them in a live server.

Kudos to both of you for what you bring to these boards every single day! I feel fortunate that you are sharing it with all of us