I am working on a simple ORM solution and have run into a tricky situation. Ideally, I’d like to be able to use methods in both a static context, and object context depending on how it is called. I am not sure if this is possible, but here is what I mean:
Say a User model wants to call where() statically, this currently works fine, for example:
$user = User::where('id = ?', 3);
Now, I also support relationships, for example a user can have messages. When this relationship is established I simply store a blank copy of a message model in the user model and set a foreign key. For example:
$user -> messages = new Message();
$user -> messages -> foreign_key = 'user_id';
Now, ideally, I would like to be able to call:
$user -> messages -> where('unread = ?', 1);
In a non-static context and make use of $this -> foreign_key when in this context so as to only pull messages where the foreign key matches the user’s id. Is this type of context-switching possible in PHP? Any reference to $this from static context throws an error as its a static method and should not rely on $this (for obvious reasons, when being called from a static context, $this won’t exist)
Are there any clever ways around this? I tried overloading the method to have two different prototypes, both with and without the static keyword but this threw a re-declaration error.
After quite a bit of playing around, I have found a way to make this workable without the
Strict Standardserror mentioned by @drew010. I don’t like it, it feels horrible, but it does work so I shall post this anyway.Basically the idea is to make the method you want to be accessible
privateandstatic. You then define the__call()and__callStatic()magic methods, so that they will call the private static method. Now you may think “this doesn’t solve the problem, I’m still stuck in a static context” – which you are but for a minor addition, you can append$thisto the arguments passed to the actual method in__call()and fetch this as the last argument to the method. So instead of referencing$thisin an object context, you reference the third argument to get a reference to your own instance.I’m probably not explaining this very well, just have a look at this code: