|
|||||||
New to SitePoint Forums? Register here for free!
|
![]() |
|
|
Thread Tools | Display Modes |
|
|
#1 |
|
SitePoint Guru
![]() ![]() ![]() ![]() ![]() Join Date: Nov 2002
Posts: 845
|
Object composition by Proxy
Standard PHP has a mechanism for specifying a reference to an object and a method to call it:
PHP Code:
PHP Code:
This could be used to transparently compose objects: PHP Code:
SomeClass makes a normal method call. The call_user_object_array business is encapsulated in the ProxyReference class. My question is, Is it possible to do this in PHP 4? If not, how close can you get? One use I see for this is in creating a GenericDecorator class. This might only be possible in PHP 5. The advantage of a GenericDecorator (performance considerations aside for a moment) is that you could decorate any object without having to declare its entire interface. Only the part you wished to decorate. Thus, when you changed the object being decorated, you might not necessarily have to change the decorator classes. A good dependency limiter, resulting is less code for the same thing. The use that I am interested in is creating on demand references in PHP 4. I want to minimize the effort involved with invoking an on-demand reference by encapsulating the call as much as possible. In other words, I should not have to copy/paste/modify a block of code like the implementation of the __call method in the ProxyReference object for every method invocation on the object in the RarelyCalledMethod invocation. The context is creating objects that persist across several HTTP requests. I would like to construct the object as if it were going to persist across several requests. This object is composed of several other objects. Only a small subset of the objects in the assembly will actually be called on each HTTP requests. Over the course of the sequence of requests, most of the objects will be called. Since the object assembly can't persist across requests, I want to limit the cost of re-instantiating it each time, by not actually instantiating the portions of the assembly which are not not used. Yet, I want my construction code to be unaware of which portions of the assembly will or won't be used during each request. (The same construction code should get executed for each request.) I am not sure if I have been very clear about what I am looking for, but I was hoping for some ideas. |
|
|
|
|
|
#2 | |
|
SitePoint Member
Join Date: Dec 2003
Location: ---
Posts: 22
|
Hi!
Quote:
This is not good for you? Felho |
|
|
|
|
|
|
#3 |
|
SitePoint Guru
![]() ![]() ![]() ![]() ![]() Join Date: Sep 2003
Location: Wixom, Michigan
Posts: 619
|
If you dont want to use the overloading extension, lastcraft posted this possible implementation for Decorators in PHP4, not too long ago:
http://www.sitepoint.com/forums/show...ight=decorator |
|
|
|
|
|
#4 |
|
SitePoint Wizard
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Nov 2000
Location: Switzerland
Posts: 2,906
|
Think I can see what you're trying to do and very powerful it would be if it can be done - suddenly it's worth persisting large numbers of objects.
Off the top of my head, one way to do it (and perhaps the only way) is to generate proxy classes (active generation) although a factory will be needed to get references to them. Something like; PHP Code:
PHP Code:
One issue might be whether the proxy RarelyUsedMethod should return a reference or copy of the result it gets from calling the real RarelyUsedMethod. For that I don't know. |
|
|
|
|
|
#5 | |
|
SitePoint Victim
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Apr 2003
Location: London
Posts: 2,265
|
Hi...
Quote:
PHP Code:
PHP Code:
yours, Marcus |
|
|
|
|
|
|
#6 | |
|
eschew sesquipedalians
![]() Join Date: Jun 2003
Location: Iowa, USA
Posts: 3,764
|
Quote:
PHP Code:
|
|
|
|
|
|
|
#7 |
|
SitePoint Wizard
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Nov 2000
Location: Switzerland
Posts: 2,906
|
Think the problem there is the "overload extension" only became a default part of PHP with 4.3.0 (I think).
Also there was a weird bug with __call() - if you declare it, suddenly your own class methods cease to be able to return values. For example; PHP Code:
|
|
|
|
|
|
#8 |
|
SitePoint Wizard
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Nov 2000
Location: Switzerland
Posts: 2,906
|
Before I lose the link, there's a nice article here: An introduction to object prevalence, and Prevayler. Only vaguely related, as implementing it in PHP would probably only be worthwhile if you're using Shared memory.
|
|
|
|
|
|
#9 |
|
SitePoint Guru
![]() ![]() ![]() ![]() ![]() Join Date: Nov 2002
Posts: 845
|
Well, after some thought, I realized another way to express what I am looking to do. I want to be able to reference a class and have that reference include the information for finding that class. (similar to autoload) This is like in Java where a class name in com.x.x.x.classname format combined with a class path is sufficient for loading that class.
I need to have a solution that works in PHP 4.1 or better. Here is what I have so far: PHP Code:
PHP Code:
The advantage of this method is that I can pass an object or a PHP 4.3+ LazyProxy, or a simple classname, or a classname with a file specification. The disadvantage is that the ResolveReference helper function has to be called on any variable holding a reference before that reference can be used. I love to find a better way to do this. Next up, I would like to expand the concept of the reference to include parameters to the constructor. The problem I have is that there is no call_user_function_array equivalent that can create an object. Unless I am missing something. Here is what I want to do. (Not sure which syntax is best, yet) PHP Code:
|
|
|
|
|
|
#10 |
|
SitePoint Wizard
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Nov 2000
Location: Switzerland
Posts: 2,906
|
On the second problem; passing a variable number of arguments to a constructor, here's a tip off from the PHP manual under eval();
PHP Code:
[/php] |
|
|
|
|
|
#11 | |
|
SitePoint Victim
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Apr 2003
Location: London
Posts: 2,265
|
Hi...
Quote:
.Jeff, can you express what you want as a test case? It sounds like a fun problem, but I am not exactly sure I understand everything. yours, Marcus |
|
|
|
|
|
|
#12 |
|
SitePoint Guru
![]() ![]() ![]() ![]() ![]() Join Date: Nov 2002
Posts: 845
|
I am prejudiced against eval.
Here is my Test case for the ResolveReference Function: PHP Code:
PHP Code:
|
|
|
|
|
|
#13 |
|
SitePoint Zealot
![]() ![]() Join Date: Feb 2003
Location: Virginia
Posts: 143
|
Ok. As promised, Ghost.
PHP Code:
The neat thing about this "proxy"/"factory" pattern I call Ghost is that it can be very flexable. The class objects that were passed in can be lazy loaded or added as objects. One could also add observers and decorators just as easily! This class might proove to be a great test root as well since Secret has no idea its being shadowed - though I would suggest adding a few safe guards in case the output is error code or not of same type as expected to be output. I would also suggest adding an interface to the Filters.. Ok, you could see that one right? Anyhow, its strange I got this idea/concept while reading this post. I read up on Slots and Signals , AOP and AspectJ - took a nap woke up a few hours later with the idea you now see before you. So, does this solution seem to help or did I just make yet another wheel? Cheers, Res |
|
|
|
|
|
#14 | |
|
SitePoint Zealot
![]() ![]() Join Date: Feb 2003
Location: Virginia
Posts: 143
|
Here's the output...
Quote:
|
|
|
|
|
|
|
#15 |
|
SitePoint Guru
![]() ![]() ![]() ![]() ![]() Join Date: Nov 2002
Posts: 845
|
Upon further testing, I've run into an unfortunate snag.
![]() Earlier I had a list of alternative ways to call my RegisterReference function: PHP Code:
PHP Code:
It seems that I am forced to choose between taking a constant and loosing the ability to pass an already instantiated object (or Proxy Object) OR taking only an object and loosing the simplicity of being able to pass in a class name as a string. (which has some backward compatibillity issues for my purposes.) Here is an example of how I wanted to use this capability in WACT: PHP Code:
PHP Code:
![]() |
|
|
|
|
|
#17 |
|
Non-Member
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Jan 2004
Location: Planet Earth
Posts: 1,807
|
Do you mean the following, where by PHP throws up an error ?
PHP Code:
Thanks. |
|
|
|
|
|
#18 | |
|
eschew sesquipedalians
![]() Join Date: Jun 2003
Location: Iowa, USA
Posts: 3,764
|
Quote:
PHP Code:
HTH |
|
|
|
|
|
|
#19 |
|
SitePoint Guru
![]() ![]() ![]() ![]() ![]() Join Date: Nov 2002
Posts: 845
|
Thanks for finding that, sweatje. The envelope technique has eased my mind a bit about removing the reference from the parameter. There is no perfect solution in PHP 4, but at this this should be forward compatible with PHP 5.
I ran across this related blog entry today and now I wish I had used the same title for this thread: Lazy Evaluation and Object Composition |
|
|
|
|
|
#20 |
|
Non-Member
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Jan 2004
Location: Planet Earth
Posts: 1,807
|
So it works then ? That is really cool - Okay for me to use the function SweatJe - Sure to find a use for it
![]() |
|
|
|
|
|
#21 | |
|
eschew sesquipedalians
![]() Join Date: Jun 2003
Location: Iowa, USA
Posts: 3,764
|
Quote:
Code:
* @author Jason E. Sweat ![]() |
|
|
|
|
|
|
#22 |
|
Non-Member
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Jan 2004
Location: Planet Earth
Posts: 1,807
|
No problem
![]() |
|
|
|
![]() |
| Bookmarks |
«
Previous Thread
|
Next Thread
»
| Thread Tools | |
| Display Modes | |
|
|
|
All times are GMT -7. The time now is 17:21.






.




Linear Mode
