2

I'm trying to implement dynamic proxies in PHP and I'm running into a problem of implementing interfaces.

My current approach to building a dynamic proxy is by having a class which uses the __call magic method. The issue is that this class implements no interface and/or extends no other class. So if I have a method which accepts only objects of a certain type through PHP type hints, I cannot pass an object of my dynamic proxy type.

One case I'm currently dealing with is a LazyLoader class, which checks the method being called to see if it should perform the loading procedure. My data source method for loading a user, instead of returning a User object, returns a LazyLoader object, which will load the user's friend list lazily. Many other data source methods will do similar things. The issue is that, there, I return a LazyLoader object and not a User object. So whenever I use a data source object to load a User object, I'll get back a LazyLoader object, which I can't pass to methods/functions which take a type hinted User parameter.

Any way to dynamically make a LazyLoader object "be a" User?

Edit: I could make several kinds of lazy loaders which extend the right class. For example, I could have a UserLazyLoader, a FinanceSheetLazyLoader and so forth. This is a possibility, but I'd like to see if I could solve this issue in a more generic way first.

5
  • 2
    Using magic methods means you have a broken architecture, if it's a business logic
    – Yang
    Aug 4, 2014 at 11:16
  • @bad_boy The LazyLoader has the magic method. It (the class) contains no business logic. It only knows how to do lazy loading. The issue is that the way LazyLoader works is by "impersonating" a (for example) User object, but I can't (because of type hinting) use it where a User object is required. Aug 4, 2014 at 14:45
  • Why you can't type hint an interface instead of a class? So that you can pass any class that implements UserInterace
    – Yang
    Aug 4, 2014 at 15:13
  • @bad_boy I could do that, yes, but then my LazyLoader would have to implement a BUNCH of interfaces (as many as there are domain types for which I want to apply lazy loading), which is also not possible given I'm using __call magic method. My current approach is having several LazyLoader classes for each domain type (UserLazyLoader, and the like), which extend the domain types, and add lazy loading capabilities. However, there is a lot of boiler plate in doing that. Aug 4, 2014 at 16:08
  • 1
    IFAIK this can only be done by code generation. Generating the proxy class source files and import them into your application.
    – Bart
    Aug 5, 2014 at 11:26

1 Answer 1

1

Make a LazyLoader interface, subclass the class you want to proxy, and implement the LazyLoader interface. Reimplement all of the parent class' public methods to forward to the lazy-loaded real-instance.

Since the proxy is a subclass of the thing you are proxying, types will remain satisfied, it can be used as the thing it's proxying.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.