Estoy usando el siguiente código y funciona perfectamente. Cámbielo para adaptarlo a sus necesidades.
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;
}
Ejemplo de llamada:
$params = ['2014-01-01','2014-12-31',100];
$results = APIDB::CallRaw('spGetData',$params);
La llamada resultante será:
CALL spGetData(?,?,?)
Si solo hay un conjunto de resultados, se devolverá tal cual. Si hay más, devolverá una matriz de conjuntos de resultados. La clave es usar $pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, true);
. Sin él, un horrible SQLSTATE[HY000]: General error: 2053
se lanzará una excepción.
El bloque try{} catch() se utiliza para eliminar los conjuntos de resultados que no se pueden recuperar. En particular, tengo procedimientos que devuelven dos conjuntos de resultados, uno como resultado de una actualización (u otras instrucciones de ejecución) y el último como datos reales. La excepción lanzada en fetchAll()
con una consulta de ejecución será PDOException
.
Advertencia:la función no está optimizada. Puede reescribirlo con un solo paso a través de los parámetros.