1

So I am writing a PHP class at the moment to help make construction of SQL statements easier. I am writing them so that each method returns an instance of the object (return $this) in order to enable method chaining.

Is it possible to test whether a method being called is a part of a method chain and which methods have been executed already in the method chain? For example, in the below code, I would like the 'from' method to test whether it was called as part of a chain with the select() method directly before it.

$object->select('john', 'chris')->from('people');

Thanks in advance!

Ben Wainwright
  • 4,224
  • 1
  • 18
  • 36
  • 3
    Not by default, but you could have implement a list in your object that each method would add itself to and you could review the chain as it's built. – Always Learning May 17 '15 at 16:53
  • 1
    Have a look at [this question](http://stackoverflow.com/questions/2110732/) . You may be able work out what you need using [debug_backtrace](http://php.net/manual/en/function.debug-backtrace.php) – Rhumborl May 17 '15 at 16:59
  • You may implement that, but you should ask yourself if that's really a good idea: normally only the state of the object should matter and not what methods have been called and in which order – Beat May 17 '15 at 17:14
  • It's indeed possible to retrieve de call stack. – dbf May 17 '15 at 17:23

1 Answers1

1

I think it is not necessary to check sequence of called methods. You can create one finally method (for example execute() ), and in it check all attributes you needed for query, if any attribute is missing (for example select) you can set default value for it: if available(for example 'select' => '*').

But in any case if you want to check is some method called before concrete method, you can set private attribute to keep methods requirements. For example:

private $_methodsRequirements = array(
    'from' => array('select'),
    'set' => array('update', 'where'),
    // and all requiriments for each method
)
private $_calledMethods = array();

and create additional method for checking methods "callability":

private function checkCallability($method) {
    $requiredMethods = $this->_methodsRequirements[$method];
    foreach($requiredMethods as $m) {
        if(!in_array($m, $this->_calledMethods)) {
            throw new Exception('You must call method "'.$m.'" before calling method "'.$method.'"!');
        }
    }
    return true;

}

and on begin of each method you must call it:

public function select() {
   $this->checkCallability(__METHOD__);
   // your query generation
   array_push($this->_calledMethods, __METHOD__);
}
Taron Saribekyan
  • 1,360
  • 7
  • 13