1

When using chained functions, is there a way to determine if the current call is the last in the chain?

For example:

$oObject->first()->second()->third();

I want to check in first, second and third if the call is the last in the chain so it saves me to write a result-like function to always add to the chain. In this example the check should result true in third.

Ben Fransen
  • 10,884
  • 18
  • 76
  • 129
  • Do all of your methods return the object itself? Chaining this way would only be possible if they do. As for your question, there's no strightforward way to achieve what you're looking for. Someone might post a workaround of some kind – Ayush Jun 13 '12 at 13:40
  • How could that be possible? when you chain funcion you call the second when the first is de-stacked. How can the second function know if there was a function before it or after it? – artragis Jun 13 '12 at 13:41
  • @Artragis, that's exactly what I want to know ;) – Ben Fransen Jun 13 '12 at 13:44
  • @xbonex; Yes, I've used http://stackoverflow.com/questions/125268/chaining-static-methods-in-php as a reference. My question was simplified, but I'm using it in a static sitation for handling queries, order-by, limits etc. – Ben Fransen Jun 13 '12 at 13:47

3 Answers3

4

No, not in any way that's sane or maintainable.
You'll have to add a done() method or similar.

deceze
  • 510,633
  • 85
  • 743
  • 889
3

As far as i know it's impossible, i'd suggest to use finishing method like this:

$oObject->first()
  ->second()
  ->third()
  ->end(); // like this
SuperDJ
  • 7,488
  • 11
  • 40
  • 74
ioseb
  • 16,625
  • 3
  • 33
  • 29
  • Yeah, that's the result-like function I mentioned ;) Thanks for your reply. Unfortunate to hear it's not possible, maybe the folks at PHP designed something for this purpose ;) – Ben Fransen Jun 13 '12 at 13:46
1

If you want to execute a function on the last chain (without addional exec or done on the chain).

The code below will obtain the full chain from the source code and return the data after the last chain.

<?php

$abc = new Methods;
echo($abc->minus(12)->plus(32)); // output: -12+32
echo(
    $abc->plus(84)
    ->minus(63)
); // output: +84-63

class Methods{
    private $data = '';
    private $chains = false;

    public function minus($val){
        $this->data .= '-'.$val;
        return $this->exec('minus');
    }

    public function plus($val){
        $this->data .= '+'.$val;
        return $this->exec('plus');
    }

    private function exec($from){
        // Check if this is the first chain
        if($this->chains === false){
            $this->getChains();
        }

        // Remove the first chain as it's
        // already being called
        if($this->chains[0] === $from){
            array_shift($this->chains);
        }
        else
            die("Can't parse your chain");

        // Check if this is the last chain
        if(count($this->chains) === 0){
            $copy = $this->data;

            // Clear data
            $this->chains = false;
            $this->data = '';

            return $copy;
        }

        // If not then continue the chain
        return $this;
    }

    private function getChains(){
        $temp = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);

        // Find out who called the function
        for ($i=0; $i < count($temp); $i++) { 
            if($temp[$i]['function'] === 'exec'){
                $temp = $temp[$i + 1];
                break;
            }
        }

        // Prepare variable
        $obtained = '';
        $current = 1;

        // Open that source and find the chain
        $handle = fopen($temp['file'], "r");
        if(!$handle) return false;

        while(($text = fgets($handle)) !== false){
            if($current >= $temp['line']){
                $obtained .= $text;

                // Find break
                if(strrpos($text, ';') !== false)
                    break;
            }
            $current++;
        }

        fclose($handle);
        preg_match_all('/>(\w.*?)\(/', $obtained, $matches);
        $this->chains = $matches[1];
        return true;
    }
}
StefansArya
  • 2,802
  • 3
  • 24
  • 25