Using php version 5.5.7, I was looking at the mysqli examples for php prepared statements: MySQLi QuickStart Prepared Statements
Under example #5 they use a method call:
$stmt = $mysqli->prepare("SELECT id, label FROM test WHERE id = 1");
$stmt->execute();
$res = $stmt->get_result();
$row = $res->fetch_assoc();
However, I cannot seem to call get_result in my own environment. Netbeans also does not show an autocomplete for this. Is this an actual method that I am missing, or do the examples have incorrect method names in them?
Note this line on the PHP page for get_result():
Available only with mysqlnd.
To use this you'd have to compile PHP with mysqlnd included, or include it some other way. You might find support limited on hosted systems, so you might do better to ignore it.
Related
The question is a fairly open one. I've been using Stored Procs with MS SQLServer for some time with classic ASP and ASP.net and love them, lots.
I have a small hobby project I'm working on and for various reasons have gone the LAMP route. Any hints/tricks/traps or good starting points to get into using stored procedures with MySQL and PHP5? My version of MySQL supports Stored Procedures.
#michal kralik - unfortunately there's a bug with the MySQL C API that PDO uses which means that running your code as above with some versions of MySQL results in the error:
"Syntax error or access violation: 1414 OUT or INOUT argument $parameter_number for routine $procedure_name is not a variable or NEW pseudo-variable".
You can see the bug report on bugs.mysql.com. It's been fixed for version 5.5.3+ & 6.0.8+.
To workaround the issue, you would need to separate in & out parameters, and use user variables to store the result like this:
$stmt = $dbh->prepare("CALL sp_takes_string_returns_string(:in_string, #out_string)");
$stmt->bindParam(':in_string', 'hello');
// call the stored procedure
$stmt->execute();
// fetch the output
$outputArray = $this->dbh->query("select #out_string")->fetch(PDO::FETCH_ASSOC);
print "procedure returned " . $outputArray['#out_string'] . "\n";
Forget about mysqli, it's much harder to use than PDO and should have been already removed. It is true that it introduced huge improvements over mysql, but to achieve the same effect in mysqli sometimes requires enormous effort over PDO i.e. associative fetchAll.
Instead, take a look at PDO, specifically
prepared statements and stored procedures.
$stmt = $dbh->prepare("CALL sp_takes_string_returns_string(?)");
$value = 'hello';
$stmt->bindParam(1, $value, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 4000);
// call the stored procedure
$stmt->execute();
print "procedure returned $value\n";
It isn't actually mandatory to use mysqli or PDO to call stored procedures in MySQL 5. You can call them just fine with the old mysql_ functions. The only thing you can't do is return multiple result sets.
I've found that returning multiple result sets is somewhat error prone anyway; it does work in some cases but only if the application remembers to consume them all, otherwise the connection is left in a broken state.
You'll need to use MySQLI (MySQL Improved Extension) to call stored procedures. Here's how you would call an SP:
$mysqli = new MySQLI(user,pass,db);
$result = $mysqli->query("CALL sp_mysp()");
When using SPs you'll need close first resultset or you'll receive an error. Here's some more information :
http://blog.rvdavid.net/using-stored-procedures-mysqli-in-php-5/
(broken link)
Alternatively, you can use Prepared Statements, which I find very straight-forward:
$stmt = $mysqli->prepare("SELECT Phone FROM MyTable WHERE Name=?");
$stmt->bind_param("s", $myName);
$stmt->execute();
MySQLI Documentation: http://no.php.net/manual/en/book.mysqli.php
I have been using ADODB, which is a great thing for abstracting actual commands to make it portable between different SQL Servers (ie mysql to mssql). However, Stored procedures do not appear to be directly supported. What this means, is that I have run a SQL query as if it is a normal one, but to "call" the SP.
An example query:
$query = "Call HeatMatchInsert('$mMatch', '$mOpponent', '$mDate', $mPlayers, $mRound, '$mMap', '$mServer', '$mPassword', '$mGame', $mSeason, $mMatchType)";
This isn't accounting for returned data,which is important. I'm guessing that this would be done by setting a #Var , that you can select yourself as the return #Variable .
To be Abstract though, although making a first php stored procedure based web app was very difficult to work around (mssql is very well documented, this is not), It's great after its done - changes are very easy to make due to the seperation.
I want to optimize this section of code a bit to use an array such as $_SESSION['user']= $arr;.
// Store user db info in session for use
$stmt = $mysqli->prepare("SELECT id,user,pass,email,timezone,lastIP,currIP,dtLastLogin,dtCurrLogin FROM test_users WHERE user = ?");
// bind params
$stmt->bind_param('s', $user);
// execute prepared statement
$stmt->execute();
// Bind result variables
$stmt->bind_result($_SESSION['id'], $_SESSION['user'], $_SESSION['pass'], $_SESSION['email'], $_SESSION['timezone'], $_SESSION['lastIP'], $_SESSION['currIP'], $_SESSION['dtLastLogin'], $_SESSION['dtCurrLogin']);
// fetch values
$stmt->fetch();
// close statement
$stmt->close();
I tried using :
$rs = $stmt->get_result();
$arr = $rs->fetch_all(MYSQLI_ASSOC);
// close statement
$stmt->close();
//store array into session
$_SESSION['user']= $arr;
but I received a Call to undefined method mysqli_stmt::get_result(). I have php 5.3.8 and MySQL 5.1.70-cll running.
mysqli_stmt::get_result is only available if you are running the MySQL native driver (mysqlnd).
This is documented in the manual page for the method.
To clarify:
There are three ways of accessing a MySQL database from PHP: the ancient mysql functions, the modern mysqli functions/class, and the PDO mysql extension.
All three of these interact with the database in the same way, using the library called libmysqlclient. Properly speaking, this is not part of PHP. It is a C library, which PHP uses.
In PHP 5.3, however, the mysqlnd driver was introduced. This is a native part of PHP (that's what the n stands for). In 5.3, it needs to be installed deliberately. From 5.4, it is the default way to access MySQL.
So to get it working, either install PHP 5.4 or compile PHP 5.3 with the options given in the installation page for mysqlnd.
In the meantime, your method is probably the best to get the data. The only other way would be to use PDO instead, which might offer a nicer syntax. This, for instance, would be possible:
$stmt = $dbh->prepare("SELECT id,user,pass,email,timezone,lastIP,currIP,dtLastLogin,dtCurrLogin FROM test_users WHERE user = :user");
$stmt->bindParam(':user', $user);
$stmt->execute();
$_SESSION['user'] = $stmt->fetch(PDO::FETCH_ASSOC);
The php manual seems to be a little light regarding the mysqli extension and I am not finding any information poking with Google.
When I create a mysqli prepared statement, should the order of calls be
mysqli::prepare()
mysqli::stmt::bind_param()
mysqli::stmt::execute()
mysqli::stmt::store_result()
mysqli::stmt::bind_result()
or
mysqli::prepare()
mysqli::stmt::bind_param()
mysqli::stmt::execute()
mysqli::stmt::bind_result()
mysqli::stmt::store_result()
Furthermore, if I then want to change the parameters and reexecute the statement, should I use
mysqli::free_result()
mysqli::stmt::execute()
mysqli::stmt::store_result()
mysqli::bind_result()
or can I simply use execute() again and then use free_result() once I am finished using the statement?
It is not PHP manual but mysqli extension itself being unclear and ambiguous.
However, to clear your confusion
You can call store_result() anywhere you wish between prepare() and fetch(). As a matter of fact, bind_result() is just a supplementary function for fetch().
In PHP you rarely need to free anything in general, and especially in cases like this, when result going to be overwritten in the next call. So - yes, you can simply call execute() again (with bind_param() first).
Also note that some installations will let you call get_result which makes all that process with fetching variables at least sensible. But is isn't always available
Also note that neither bind_param() nor bind_result() will let you easily bind an arbitrary number of variables, which will make code even more bloated.
So, looking at all that mess I'd still suggest you to use either PDO or manually implemented placeholders, like safeMysql does.
here is an example that works:
$query="SELECT service_ip,service_port FROM users WHERE username=? and password=?";
$conn=connection();
$stmt = $conn->prepare($query);
$stmt->bind_param('ss', $user,$pass);
$ans=$stmt->execute();
$service_ip=false;
$service_port=false;
$stmt->bind_result($service_ip,$service_port);
$stmt->fetch();
mysqli_free_result($ans);
$stmt->close();
$conn -> close();
Here is proper code:
$query="SELECT service_ip,service_port FROM users WHERE username=? and password=?";
$stmt = $conn->prepare($query);
$stmt->execute(array($user,$pass));
$data = $stmt->fetch()/fetchAll()/fetchColumn();
// whoops! that's all
// ...in case you want to execute again
$stmt->execute(array($user2,$pass2));
$data = $stmt->fetch()/fetchAll()/fetchColumn();
// and again...
$stmt->execute(array($user3,$pass3));
$data = $stmt->fetch()/fetchAll()/fetchColumn();
Note that you already have all required data. Feel the power of PDO
I simply want to execute a MySQL stored procedure. But I want to use the parameter parsing technique for all the usual reasons. So I've taken the example from the php manual here and now have this:
$stmt = $dbh->prepare("CALL update_bug_status(?,?)");
$stmt->bindParam(1, $bug_id);
$stmt->bindParam(2, $bug_status);
$stmt->execute();
The missing piece of the puzzle is the $dbh variable, which the manual seems to forget to mention!
I thought for $dbh I could use an ODBC connection variable like this:
$connection_string = "DRIVER={MySQL ODBC 5.1 Driver};Server=10.32.27.6;Database=bugs";
$dbh=odbc_connect($connection_string,'root','xxxxxx');
But this doesn't work because 'odbc_connect' simply returns an id number.
I've seen other examples that seem to make use of mysql specific functions. But I don't have these functions available so I want an answer that uses standard ODBC functions if possible.
You are using a PDO method on an ODBC connection (see the menu on the left to see which portion of the manual you are in), and you should use odbc_prepare and odbc_execute (either that, or rather then doing an odbc_connect use the PDO driver).
The question is a fairly open one. I've been using Stored Procs with MS SQLServer for some time with classic ASP and ASP.net and love them, lots.
I have a small hobby project I'm working on and for various reasons have gone the LAMP route. Any hints/tricks/traps or good starting points to get into using stored procedures with MySQL and PHP5? My version of MySQL supports Stored Procedures.
#michal kralik - unfortunately there's a bug with the MySQL C API that PDO uses which means that running your code as above with some versions of MySQL results in the error:
"Syntax error or access violation: 1414 OUT or INOUT argument $parameter_number for routine $procedure_name is not a variable or NEW pseudo-variable".
You can see the bug report on bugs.mysql.com. It's been fixed for version 5.5.3+ & 6.0.8+.
To workaround the issue, you would need to separate in & out parameters, and use user variables to store the result like this:
$stmt = $dbh->prepare("CALL sp_takes_string_returns_string(:in_string, #out_string)");
$stmt->bindParam(':in_string', 'hello');
// call the stored procedure
$stmt->execute();
// fetch the output
$outputArray = $this->dbh->query("select #out_string")->fetch(PDO::FETCH_ASSOC);
print "procedure returned " . $outputArray['#out_string'] . "\n";
Forget about mysqli, it's much harder to use than PDO and should have been already removed. It is true that it introduced huge improvements over mysql, but to achieve the same effect in mysqli sometimes requires enormous effort over PDO i.e. associative fetchAll.
Instead, take a look at PDO, specifically
prepared statements and stored procedures.
$stmt = $dbh->prepare("CALL sp_takes_string_returns_string(?)");
$value = 'hello';
$stmt->bindParam(1, $value, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 4000);
// call the stored procedure
$stmt->execute();
print "procedure returned $value\n";
It isn't actually mandatory to use mysqli or PDO to call stored procedures in MySQL 5. You can call them just fine with the old mysql_ functions. The only thing you can't do is return multiple result sets.
I've found that returning multiple result sets is somewhat error prone anyway; it does work in some cases but only if the application remembers to consume them all, otherwise the connection is left in a broken state.
You'll need to use MySQLI (MySQL Improved Extension) to call stored procedures. Here's how you would call an SP:
$mysqli = new MySQLI(user,pass,db);
$result = $mysqli->query("CALL sp_mysp()");
When using SPs you'll need close first resultset or you'll receive an error. Here's some more information :
http://blog.rvdavid.net/using-stored-procedures-mysqli-in-php-5/
(broken link)
Alternatively, you can use Prepared Statements, which I find very straight-forward:
$stmt = $mysqli->prepare("SELECT Phone FROM MyTable WHERE Name=?");
$stmt->bind_param("s", $myName);
$stmt->execute();
MySQLI Documentation: http://no.php.net/manual/en/book.mysqli.php
I have been using ADODB, which is a great thing for abstracting actual commands to make it portable between different SQL Servers (ie mysql to mssql). However, Stored procedures do not appear to be directly supported. What this means, is that I have run a SQL query as if it is a normal one, but to "call" the SP.
An example query:
$query = "Call HeatMatchInsert('$mMatch', '$mOpponent', '$mDate', $mPlayers, $mRound, '$mMap', '$mServer', '$mPassword', '$mGame', $mSeason, $mMatchType)";
This isn't accounting for returned data,which is important. I'm guessing that this would be done by setting a #Var , that you can select yourself as the return #Variable .
To be Abstract though, although making a first php stored procedure based web app was very difficult to work around (mssql is very well documented, this is not), It's great after its done - changes are very easy to make due to the seperation.