3

For example lets say I have a set of classes and methods to do so:

$obj->method1()->method2();

Is there anyway for method1() to know with in itself that its the first method being called or for method2 to know that its the last?

Some more details
I just want to be able to build a set of these calls so that it either returns an instance of itself if the call to the method isnt at the end of the chain or return something different if its at the end.

For example

$obj->method1()->method2(); #Here method 2 will return lets say a string.
$obj->method1()->method2()->method3(); #Since method2 isnt at the end of the chain, it should return an instance of itself (or another object) here so that the chain could continue.

EDIT: anyone whoz trying to do this - it is a bad design pattern.

This does seem to be a duplicate. Refer to this question for more answers.

Community
  • 1
  • 1
shxfee
  • 5,188
  • 6
  • 31
  • 29
  • You could write some special objects to make this possible; but without explicitly coding it yourself, there isn't. Usually this sort of pattern (where method1() returns $this so you can chain event calls) is used for things where methods wouldn't need to know the order they're called in. What problem are you trying to solve? – andrewffff Feb 21 '10 at 19:09
  • 2
    Why would it care? The purpose of `method1` is to return some object; what the caller does with that object is none of `method1`'s concern. If you are even asking the question, reconsider your design. – Thomas Feb 21 '10 at 19:09
  • exact duplicate: http://stackoverflow.com/questions/1934247/javascript-detect-end-of-chained-functions – just somebody Feb 21 '10 at 19:25
  • This is not OOP, I guess you might want to try some other programming techniques... there is for example Functional Programming, or you might find it in one of the uncommon, odd, or old languages like Ada. – Omar Al-Ithawi Feb 21 '10 at 19:43

4 Answers4

1

Not out of the box, not even with a Stack trace.

I guess you could put something together using constants or global variables:

Don't try this at home!

$GLOBALS["chain"] = array();
$obj->method1()->method2();    // method1 adds member to $GLOBALS["chain"], 
                               // array_push($GLOBALS["chain"], __FUNCTION__);
                               // method2 does the same...
print_r($GLOBALS["chain"]);

That would give you the full chain - not yet which one is the last one, to do that, you would have to pass a flag to method2().

But it would be horribly hacky and pollute your code.

Is there a specific reason you need this for?

Pekka
  • 442,112
  • 142
  • 972
  • 1,088
0

I don't think this is possible, no -- at least, I've never seen anything about this.

(Out of curiosity : why would you need that ? Maybe it would be possible to use onther solution to solve your actual problem ?)

Pascal MARTIN
  • 395,085
  • 80
  • 655
  • 663
0

The only way this is possible is to let the methods save some global state.

If both methods are in the same class, you could add a variable to the class and let each class set a unique value.

But the question is if this is desirable. This kind of behavior is often not very smart in the long run.

Ikke
  • 99,403
  • 23
  • 97
  • 120
0

All you could do is find out which methods have been called so far, by setting some kind of global state in the class. But you can't find out what methods are being called after a method, and you wouldn't be able to tell the difference between methods in one chain and methods in another:

$obj->m1()->m2();
$obj->m3(); // You would think that m1() and m2() came before this in the same chain

You would need to have a method at the end of each chain to clear the global state in the class.

Since it seems you need to see which method comes next in a chain, this won't work for you.

I would say that this is a really bad design pattern, at least for PHP (and every other language I've worked in). Each method should do one thing only. If you need a method to either return a string or an object depending on what you need it for later, you are doing something wrong.

Granted, I have done something like this before. It was a meta-information class for images submitted by users -- you could set it up like this:

$meta = new ImageMeta();
$meta->first_name("foo")->last_name("bar")->email("baz")->id("guid");

But, if you did this:

$meta->first_name();

it would return a string. The default value for the first parameter was NULL, and if the method got NULL, it returned a string. Otherwise it set (and escaped) an internal value and returned $this.

At first I thought it was kind of cool, but it turned out to be a mistake. I hate using that class now. Just make one method/function do one thing only and you will be much happier.

Carson Myers
  • 37,678
  • 39
  • 126
  • 176