18
votes

I'm recently have learned to use Zend Framework. I did a simple CRUD application. But now I want to use a existing database for a more complex application and I want to know how I call a stored procedure in the Model, how to send parameters, how to read the results and store them in an array in PHP. Please. I appreciate any kind of help :)

4
If you want to use stored procedures within GoDaddy hosting MySQL Database, check if you can back it up together with your database backup. From my experience, they NOT allow to backup stored procedures. It makes unacceptable for me to use them.Yevgeniy Afanasyev

4 Answers

24
votes

It's not too hard. Here's an example of a MySQL stored procedure with an IN parameter, an OUT parameter, and a result set:

CREATE PROCEDURE MyProc(IN i INTEGER, OUT o INTEGER)
BEGIN
  SELECT i+10 INTO o;
  SELECT i, o;
END

You can call this with the query() method, and pass a parameter:

$stmt = $db->query("CALL MyProc(?, @output)", array(25));
print_r( $stmt->fetchAll() );

The trick is that MySQL stored procs might return multiple result sets (if the proc had multiple SELECT queries for instance). So the API must advance through all result sets before you can execute another SQL query. Or else you get the "Commands out of sync" error.

If you use the PDO_MySQL adapter:

while ($stmt->nextRowset()) { }

If you use the MySQLi adapter, you'll find that Zend_Db_Statement_Mysqli doesn't implement nextRowset(), so you have to call the internal mysqli connection object:

while ($db->getConnection()->next_result()) { }

Once you clear the result sets, you can run subsequent SQL queries, for example to fetch the value of the procedure's OUT parameter:

$stmt = $db->query("SELECT @output");
print_r( $stmt->fetchAll() );
1
votes

Great answer from Bill. Just for completeness, if you encounter:

SQLSTATE[HY000]: General error: 2053

When using this method to get a result set from your procedure, check your arguments. I refactored a method and was passing NULLs as arguments to the procedure as the variables I'd used were out of scope. Once I'd fixed this silly mistake the problem went away (to be replaced by another):

SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other 
unbuffered queries are active.  Consider using PDOStatement::fetchAll().

I'm using $stmt->fetchAll() though. I switched to using prepare() and execute() in place of query(). Switching to mysqli from pdo_mysql in my Zend_Db config finally got things working for me. I found this information from the following SO question:

Call Multiple Stored Procedures with the Zend Framework

0
votes
    $db = Zend_Db_Table::getDefaultAdapter();    
    $stmt = $db->query("CALL procedure()");
    $data = $stmt->fetchAll();
0
votes

If someone is looking for ZendFramework 2 \ Zend Expressive using Zend\Db :

There is another way to do this using createStatement() method.

// prepare create statement from adapter
$stmt = $this->getAdapter()->createStatement();

$stmt->prepare('CALL myproc("myVal")');
// execute sql query
$records = $stmt->execute();
// manipulate results
if ($records instanceof ResultInterface && $records->isQueryResult()) {
    $resultSet = new ResultSet;
    $resultSet->initialize($records);
    // return records if found
    if (count($resultSet)) {
       // return array of result set
       return $resultSet->toArray();
    }
   // if no records found
   return array()

}