0

I'm thinking about creating a class that uses method chaining. What I'm trying to achieve is the type the output of methods, based if the methods are chained or not.

Example 1:

$var = $instance->user($id);

Returns an array with the necessary information.

Example 2:

$var = $instance->user($id)->action($arg);

I want the chained method in front of user() to just pass the argument $id to the next method and for it not to output anything. Then the method action() grabs the $id and return what's asked.

How can I achieve this?

The reason I want don't want to make user() return its normal result code is because I intend to use this in an API wrapper. Returning the "normal" user() will cost me an additional X-Rate-Limit call. If I could spare this call, and just pass the parameter $id to the second method, that would be the ideal.

5
  • And your question would be? Commented Mar 19, 2015 at 10:28
  • @Rizier123 The obvious. How can I achieve this? Commented Mar 19, 2015 at 10:31
  • @halfer Does that answer does what I need? I saw that one before, but got confused. Commented Mar 19, 2015 at 10:33
  • @halfer As far as I know that one returns its original function. Since I intend to make HTTP requests on some of the methods, I want to spare server work on that. I just want to make the method know that it will be chained, so it could just pass its arguments instead of processing its original code. Commented Mar 19, 2015 at 10:38
  • Clarified for what and why I need this. Commented Mar 19, 2015 at 10:58

2 Answers 2

1

Your current plan is for each of your methods to perform an expensive HTTP call, but you are aware of the potential for significant delay to mount up if several methods are chained.

A good solution for this is to use chained methods to set the parameters and then to run an execute method at the end. So, you might modify your examples thus:

$var = $instance->user($id)->execute(); $var = $instance->user($id)->action($arg)->execute(); 

You'd have user() and action() returning $this (as well as changing the instance's state in some way) and then execute() would run the HTTP call in one go. This makes all calls prior to the last one very inexpensive indeed.

The return value could be $this, although a terminator method of this kind might just return a boolean success value. Your examples imply that a value is expected - having that relate to the last method prior to the execute() would probably work too.

Sign up to request clarification or add additional context in comments.

5 Comments

That's mostly what I want. But is there a way to do this without the execute()? I mean, is there a way to let action() know that it is the last method in the chain and it kind of already returns the executed code?
@oscarmarcelo: it might be if you use Reflection, but I would say that's very hacky, and it isn't really much more effort to type a terminator method. This design pattern is quite common - see Propel's Query system - the find* methods are the terminator.
@oscarmarcelo: somewhat related, same answer I think!
In other words, there isn't a way to reliably tell that a method is the final one in the chain. Unless an output requires a fixed number of methods (like the second example you gave, which have precisely 3, red->blue->green) I can't make the instance to predict when an output is intended and the only option I have is to use a final method, like execute().
@oscar: as I say, there might be a way to do that, but the way in which it may be possible is so hacky I recommend you don't do it. In other words, I am not aware of an elegant way to do it, and I don't think it's worth the effort anyway.
0

Instead of returning an array, user() should return a User object.

This way, $var = $instance->user($id); will return the infos you need (because all the infos will be in the User object) and $var = $instance->user($id)->action($arg); will call action() on the User object (this way, you can easiely access the id of the user).

No more need to differentiate how user() has been called. ;)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.