debugEnabled){ $this->storeDebug(); } if($this->stacking){ return new PDOStatementWrapper($statement, $this); }else{ $st = parent::prepare($statement, $options); if($st === false){ throw new \PDOException("There is an error in your SQL statement"); } return $st; } } /** * @throws \ReflectionException * * @return void */ private function storeDebug(){ //get all the debug info about the repo $prepareStack = debug_backtrace(0,3)[1]; $stack = debug_backtrace(0,3)[2]; //create the reflection object $f = new \ReflectionMethod($stack["class"],$stack["function"]); //get only the repo name $className = explode("\\",$stack["class"]); $className = $className[count($className)-1]; $result = []; //if we are flushing a stack, just count the number of request stacked if($stack["function"] == "executeStack"){ $result["StackedRequest"] = true; $result["numberOfStackedRequest"] = substr_count($prepareStack["args"][0],";"); //if we are not stacking, log the repo call }else if(!$this->stacking){ //store results $result["repoName"] = $className; $result["methodName"] = $stack["function"]; $result["args"] = []; foreach ($f->getParameters() as $key => $param) { $result["args"][$param->name] = $stack["args"][$key]; } //else we are stacking a request, we should not log it }else{ return; } $this->debug[] = $result; } /** * @return array */ public function getDebug() : array{ return $this->debug; } /** * Enable request stacking */ public function enableStacking(){ $this->stacking = true; } /** * @return bool */ public function isDebugEnabled() : bool{ return $this->debugEnabled; } /** * @param PDOStatementWrapper $st */ public function stackStatement(PDOStatementWrapper $st){ array_push($this->statements,$st); } /** * Enable repo debug */ public function enableDebug(){ $this->debugEnabled = true; } /** * disable repo debug */ public function disableDebug(){ $this->debugEnabled = false; } /** Execute the stored request stack * @return bool */ public function executeStack(){ //init the statements and the generator of number $finalStatement = ''; $finalExecute = []; $i = 0; //for each request stacked foreach ($this->statements as $request){ $statement = $request->getStatement(); // we have to modify the parameters index at the same time that we modify the request, so we use static class attribute $tempParametes = $request->getParameters(); //find the given pattern in the request, then call our function and replace the matched string by the return value of our function $finalStatement .= rtrim(preg_replace_callback("/(:[a-z_\-0-9]*)/is",function($matches) use (&$i,&$tempParametes){ //copy the parameter with the modified index $tempParametes[":$i"] = $tempParametes[$matches[0]]; //delete the old index unset($tempParametes[$matches[0]]); //return the modified string for replacement return ":".$i++; },$statement),';').';'; $finalExecute += $tempParametes; } //disable stacking $this->stacking = false; //enable prepare emulation (native prepare do not accept stacked requests parent::setAttribute(\PDO::ATTR_EMULATE_PREPARES, true); $this->beginTransaction(); $req = $this->prepare($finalStatement); $success = $req->execute($finalExecute); //as we execute multiple query that we don't fetch, we have to close the cursor if we want to do other requests later $req->closeCursor(); $this->commit(); //using beginTransaction/commit disable the autocommit, we re-activate it $this->setAttribute(\PDO::ATTR_AUTOCOMMIT,1); parent::setAttribute(\PDO::ATTR_EMULATE_PREPARES, false); return $success; } }