Използвам следния код и работи безупречно. Променете го, за да отговаря на вашите нужди.
public static function CallRaw($procName, $parameters = null, $isExecute = false)
{
$syntax = '';
for ($i = 0; $i < count($parameters); $i++) {
$syntax .= (!empty($syntax) ? ',' : '') . '?';
}
$syntax = 'CALL ' . $procName . '(' . $syntax . ');';
$pdo = DB::connection()->getPdo();
$pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, true);
$stmt = $pdo->prepare($syntax,[\PDO::ATTR_CURSOR=>\PDO::CURSOR_SCROLL]);
for ($i = 0; $i < count($parameters); $i++) {
$stmt->bindValue((1 + $i), $parameters[$i]);
}
$exec = $stmt->execute();
if (!$exec) return $pdo->errorInfo();
if ($isExecute) return $exec;
$results = [];
do {
try {
$results[] = $stmt->fetchAll(\PDO::FETCH_OBJ);
} catch (\Exception $ex) {
}
} while ($stmt->nextRowset());
if (1 === count($results)) return $results[0];
return $results;
}
Примерно обаждане:
$params = ['2014-01-01','2014-12-31',100];
$results = APIDB::CallRaw('spGetData',$params);
Полученото повикване ще бъде:
CALL spGetData(?,?,?)
Ако има само един набор от резултати, той ще бъде върнат такъв, какъвто е. Ако има повече, той ще върне масив от набори от резултати. Ключът използва $pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, true);
. Без него, ужасен SQLSTATE[HY000]: General error: 2053
ще бъде изведено изключение.
Блокът try{} catch() се използва за премахване на наборите от резултати, които не могат да бъдат извлечени. По-специално, имам процедури, които връщат два набора от резултати, единият в резултат на актуализация (или други оператори за изпълнение) и последният като реални данни. Изключението, хвърлено на fetchAll()
със заявка за изпълнение ще бъде PDOException
.
Предупреждение:функцията не е оптимизирана. Можете да го пренапишете с едно преминаване през параметрите.