Estou usando o seguinte código e funciona perfeitamente. Altere-o para atender às suas necessidades.
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;
}
Exemplo de chamada:
$params = ['2014-01-01','2014-12-31',100];
$results = APIDB::CallRaw('spGetData',$params);
A chamada resultante será:
CALL spGetData(?,?,?)
Se houver apenas um conjunto de resultados, ele será retornado como está. Se houver mais, ele retornará uma matriz de conjuntos de resultados. A chave está usando
$pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, true);
. Sem ele, um horrível SQLSTATE[HY000]: General error: 2053
exceção será lançada. O bloco try{} catch() é usado para eliminar os conjuntos de resultados que não podem ser buscados. Particularmente, tenho procedimentos que retornam dois conjuntos de resultados, um como resultado de uma atualização (ou outras instruções de execução) e o último como os dados reais. A exceção lançada em
fetchAll()
com uma consulta de execução será PDOException
. Atenção:a função não está otimizada. Você pode reescrevê-lo com uma única passagem pelos parâmetros.