I am trying to execute a MySQL Stored Procedure using PDO connection, i tried almost everything but not able to execute it.
The SP will only insert and update. Following is the codes I tried till now.
$config = require('protected/config/main.php');
try
{
$db_adat = new PDO($config['components']['db']['connectionString'], $config['components'] ['db']['username'], $config['components']['db']['password']);
$result= $db_adat->prepare('CALL pdv()');
$a = $result->execute();
$a->fetchAll(PDO::FETCH_ASSOC);
I tried with only fetch(), with only fetchAll(), fetchObject(), with fetch(PDO::FETCH_ASSOC), with fetchAll(\PDO::FETCH_ASSOC), but I always get following error
Fatal error: Call to a member function fetchAll() on a non-object in D:\ADAT_System\www\test\protected\controllers\ExportPDVController.php on line 35
I also tried using query() instead of execute(), but that doesn't work either.
I also tried adding a (select * ) statement in SP and tried with all above "fetch" options, but got same error.
The SP takes 7 minutes to complete, but all gave error immediately, so I am guessing it never ran the SP.
I tried as following too
$result= $this->$db_adat->prepare("CALL pdv()");
$result->execute();
but the I got following error:
Object of class PDO could not be converted to string
I am not passing any parameters in SP, just a simple call. Please let me know if any more information is required.
This part of your code is wrong
$result= $db_adat->prepare('CALL pdv()');
$a = $result->execute();
$a->fetchAll(PDO::FETCH_ASSOC);
Because execute() returns a boolean upon success or failure.
You cannot use that to fetch.here is the proper way with appropriate variable names:
$stmt= $db_adat->prepare('CALL pdv()');
$success = $stmt->execute();
if($success){
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
}else{
echo 'failed to run sp';
}
<?php
if(isset($_POST) && !empty($_POST)){
$SearchPO = (($_POST)['SearchPO']);
}
$stmt = $pdo->prepare("CALL spPO(?)");
$stmt->bindParam(1, $SearchPO, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT|PDO::ATTR_EMULATE_PREPARES, 4000);
$stmt->execute();
do {
$result = $stmt->fetchAll();
} while ($stmt->nextRowset() && $stmt->columnCount());
?>
You must use the nextRowset() function because the next record is 'empty' without it. Source
Related
I have been trying to convert a old mysql too pdo as I am trying to learn how pdo works, I have been working on this one file for hours now busting my head and can not figure out what is wrong, and I'm sure its a lot.
try{
$check_user_data = $dbh->query("SELECT * FROM members WHERE username = '$username'");
$stmt = $dbh->prepare($check_user_data);
$stmt->execute();
$result->bind_result($username);
$data_exists = ($check_user_data->fetchColumn() > 0) ? true : false;
if($data_exists = false){
$final_report.="This username does not exist..";
}else{
$get_user_data = $stmt->fetch(PDO::FETCH_ASSOC);
if($get_user_data['password'] == $password){
$start_idsess = $_SESSION['username'] = "".$get_user_data['username']."";
$start_passsess = $_SESSION['password'] = "".$get_user_data['password']."";
$final_report.="You are about to be logged in, please wait a few moments.. <meta http-equiv='Refresh' content='2; URL=members.php'/>";
}
}
foreach ($dbh->query($sql) as $row){
}
$dbh = null;
}
catch(PDOException $e){
echo $e->getMessage();
}
Also getting a fatal
Fatal error: Call to a member function execute() on a non-object
Not sure if the fatal is related to the warning or not.
First, change these two lines:
$check_user_data = $dbh->query("SELECT * FROM members WHERE username = '$username'");
$stmt = $dbh->prepare($check_user_data);
to:
$stmt = $dbh->prepare("SELECT * FROM members WHERE username = :username");
$stmt->bindParam(':username', $username);
This makes use of the parameter feature of prepared statements, which prevents SQL injection.
Next, PDO doesn't have a bind_result method, that's part of MySQLI. To get the results, you should do:
$get_user_data = $stmt->fetch(PDO::FETCH_ASSOC);
$data_exists = ($get_user_data !== false);
You should then remove the call to $stmt->fetch in the else block, because it will try to get the next row of results.
The fatal is definitely related to the warning; you are passing the results of $dbh->query() (which is a PDOStatementObject) into $dbh->prepare, causing $dbh->prepare to return something which is not an object.
Just move the SQL into the $dbh->prepare call and get rid of the $dbh->query() entirely.
For people who might come over here my problem was a bit different i was trying to enable a filter on doctrine/symfony project and accidentally made a mistake on the following line :
$filter->setParameter($name, $someObject);
and when i called the function getParameter($name) in addFilterConstraint function i got the same error
Warning: PDO::prepare() expects parameter 1 to be string, object given
And later on i found the mistake. the fix would be to replace the setParameter second input from $someObject to $someString something like this:
$filter->setParameter($name, 'some string which is the real value you want to get later');
I'm trying to implement pagination using PHP. I found that calling exec to the connected database prevents the further query calls from working.
The piece of code at hand:
<?php
// Pagination logic
//Here we count the number of results
$query = "SELECT COUNT(*) as num FROM gig";
$total_pages = $db->exec($query);
$total_pages = $total_pages[num];
?>
After it if I try to use a query such as:
<?php>
foreach ($db->query("SELECT sname, start, venue FROM gig WHERE start = '0000-00-00 00:00:00'") as $a) {
$row="<tr><td>$a[sname]</td><td>To be announced</td><td>$a[venue]</td></tr>\n";
print $row;
}
?>
it returns
Warning: Invalid argument supplied for foreach()
As soon as the first code block is removed, the query works fine. When I check the value of $total_pages, it's 0, so something must be going wrong along the way. As far as I know, I use it in the same way as the query(which works on its own), so is there any reason why it doesn't work?
The PDO is initialized in the following way:
try {
$db = new PDO("mysql:dbname=$db_name;host=$db_server", $db_user, $db_pw);
} catch (PDOException $e) {
die('Connection failed: ' . $e->getMessage());
}
session_start();
From Manual
PDO::exec() does not return results from a SELECT statement. For a
SELECT statement that you only need to issue once during your program,
consider issuing PDO::query(). For a statement that you need to issue
multiple times, prepare a PDOStatement object with PDO::prepare() and
issue the statement with PDOStatement::execute().
Used a function of the STATEMENT object had after using querying to count the rows instead of exec:
$dbq = $db->query("SELECT * FROM gig");
$rows = $dbq->rowCount();
About the latter code block not working because of the exec failing - it seems to just be the way php queries work, if one fails, all fail. The foreach() error is for the object it's provided is not an array, for it failed.
Below is some poorly written and heavily misunderstood PHP code with no error checking. To be honest, I'm struggling a little getting my head around the maze of PHP->MySQLi functions! Could someone please provide an example of how one would use prepared statements to collect results in an associative array whilst also getting a row count from $stmt? The code below is what I'm playing around with. I think the bit that's throwing me off is using $stmt values after store_result and then trying to collect an assoc array, and I'm not too sure why...
$mysqli = mysqli_connect($config['host'], $config['user'], $config['pass'], $config['db']);
$stmt = $mysqli->prepare("SELECT * FROM licences WHERE generated = ?");
$stmt->bind_param('i', $core['id']);
$result = $stmt->execute();
$stmt->store_result();
if ($stmt->num_rows >= "1") {
while($data = $result->fetch_assoc()){
//Loop through results here $data[]
}
}else{
echo "0 records found";
}
I feel a little cheeky just asking for code, but its a working demonstration of my circumstances that I feel I need to finally understand what's actually going on. Thanks a million!
I searched for a long time but never found documentation needed to respond correctly, but I did my research.
$stmt->get_result() replace $stmt->store_result() for this purpose.
So, If we see
$stmt_result = $stmt->get_result();
var_dump($stmt_result);
we get
object(mysqli_result)[3]
public 'current_field' => int 0
public 'field_count' => int 10
public 'lengths' => null
public 'num_rows' => int 8 #That we need!
public 'type' => int 0
Therefore I propose the following generic solution. (I include the bug report I use)
#Prepare stmt or reports errors
($stmt = $mysqli->prepare($query)) or trigger_error($mysqli->error, E_USER_ERROR);
#Execute stmt or reports errors
$stmt->execute() or trigger_error($stmt->error, E_USER_ERROR);
#Save data or reports errors
($stmt_result = $stmt->get_result()) or trigger_error($stmt->error, E_USER_ERROR);
#Check if are rows in query
if ($stmt_result->num_rows>0) {
# Save in $row_data[] all columns of query
while($row_data = $stmt_result->fetch_assoc()) {
# Action to do
echo $row_data['my_db_column_name_or_ALIAS'];
}
} else {
# No data actions
echo 'No data here :(';
}
$stmt->close();
$result = $stmt->execute(); /* function returns a bool value */
reference : http://php.net/manual/en/mysqli-stmt.execute.php
so its just sufficient to write $stmt->execute(); for the query execution.
The basic idea is to follow the following sequence :
1. make a connection. (now while using sqli or PDO method you make connection and connect with database in a single step)
2. prepare the query template
3. bind the the parameters with the variable
4. (set the values for the variable if not set or if you wish to change the values) and then Execute your query.
5. Now fetch your data and do your work.
6. Close the connection.
/*STEP 1*/
$mysqli = mysqli_connect($servername,$usrname,$pswd,$dbname);
/*STEP 2*/
$stmt = $mysqli->prepare("SELECT * FROM licences WHERE generated = ?");
/*Prepares the SQL query, and returns a statement handle to be used for further operations on the statement.*/
//mysqli_prepare() returns a statement object(of class mysqli_stmt) or FALSE if an error occurred.
/* STEP 3*/
$stmt->bind_param('i', $core['id']);//Binds variables to a prepared statement as parameters
/* STEP 4*/
$result = $stmt->execute();//Executes a prepared Query
/* IF you wish to count the no. of rows only then you will require the following 2 lines */
$stmt->store_result();//Transfers a result set from a prepared statement
$count=$stmt->num_rows;
/*STEP 5*/
//The best way is to bind result, its easy and sleek
while($data = $stmt->fetch()) //use fetch() fetch_assoc() is not a member of mysqli_stmt class
{ //DO what you wish
//$data is an array, one can access the contents like $data['attributeName']
}
One must call mysqli_stmt_store_result() for (SELECT, SHOW, DESCRIBE, EXPLAIN), if one wants to buffer the complete result set by the client, so that the subsequent mysqli_stmt_fetch() call returns buffered data.
It is unnecessary to call mysqli_stmt_store_result() for other queries, but if you do, it will not harm or cause any notable performance in all cases.
--reference: php.net/manual/en/mysqli-stmt.store-result.php
and http://www.w3schools.com/php/php_mysql_prepared_statements.asp
One must look up the above reference who are facing issue regarding this,
My answer may not be perfect, people are welcome to improve my answer...
If you would like to collect mysqli results into an associative array in PHP you can use fetch_all() method. Of course before you try to fetch the rows, you need to get the result with get_result(). execute() does not return any useful values.
For example:
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli($config['host'], $config['user'], $config['pass'], $config['db']);
$mysqli->set_charset('utf8mb4'); // Don't forget to set the charset!
$stmt = $mysqli->prepare("SELECT * FROM licences WHERE generated = ?");
$stmt->bind_param('i', $core['id']);
$stmt->execute(); // This doesn't return any useful value
$result = $stmt->get_result();
$data = $result->fetch_all(MYSQLI_ASSOC);
if ($data) {
foreach ($data as $row) {
//Loop through results here
}
} else {
echo "0 records found";
}
I am not sure why would you need num_rows, you can always use the array itself to check if there are any rows. An empty array is false-ish in PHP.
Your problem here is that to do a fetch->assoc(), you need to get first a result set from a prepared statement using:
http://php.net/manual/en/mysqli-stmt.get-result.php
And guess what: this function only works if you are using MySQL native driver, or "mysqlnd". If you are not using it, you'll get the "Fatal error" message.
You can try this using the mysqli_stmt function get_result() which you can use to fetch an associated array. Note get_result returns an object of type mysqli_result.
$stmt->execute();
$result = $stmt->get_result(); //$result is of type mysqli_result
$num_rows = $result->num_rows; //count number of rows in the result
// the '=' in the if statement is intentional, it will return true on success or false if it fails.
if ($result_array = $result->fetch_assoc(MYSQLI_ASSOC)) {
//loop through the result_array fetching rows.
// $ rows is an array populated with all the rows with an associative array with column names as the key
for($j=0;$j<$num_rows;$j++)
$rows[$j]=$result->fetch_row();
var_dump($rows);
}
else{
echo 'Failed to retrieve rows';
}
I used PDO hundreds of times but now I'm very frustrated - everything seems ok for me, I must be missing something... I use PGSql and PDO. Passing query to PgAdmin 3 and running it - no problem! But calling it from PDO is a different story.
My code:
(...checking if $name is null and so on...)
$query = "SELECT
*
FROM
out.city
WHERE
city_name ILIKE ?";
$stmt = $this->db->prepare($query);
try{
$res = $stmt->execute(array("'".$name."'"));
$ret = $res->fetchAll(PDO::FETCH_ASSOC);
(... rest of try-catch block...)
Problem is that $res returns boolean (true) instead of object. It results in error:
PHP Fatal error: Call to a member function fetchAll() on a non-object
I've tried few methods of how to put $name inside query - using question mark, bind or just joining the strings (I know, bad way). None of them work.
Should be prepare handle (object) only, replace $res-> with $stmt->,
$stmt->fetchAll(PDO::FETCH_ASSOC);
When querying using mysqli_stmt::prepare() and execute(), it will not return the result set. But we need to access using the mysqli_stmt:fetch() on the stmt object. There is one function in the php manual called mysqli_stmt::get_result() that will return the result set into a variable we define, but when I use it, it gives me undefined method error. The manual say it is probably in SVC which I am not sure what.
The codes:
$conn = new mysqli(DB_HOST,DB_USERNAME,DB_PASSWORD, DB_NAME);
$stmt = $conn->stmt_init();
$stmt->prepare("select * from users where u_id = ? ");
$stmt->bind_param('s', $param);
$stmt->execute();
Edit :
I know I can use bind_result() and fetch() function to retrieve the record like :
$stmt->bind_result($column1, $column2, $column3);
while ($stmt->fetch()) {
echo "Column 1: $column1\n";
echo "Column 2: $column2\n";
echo "Column 3: $column3\n";
}
But, my objective is to get the result set (the resource type object) after I execute, something like this:
$result = $stmt->execute();
so I can use the normal mysqli::fetch_object on the result set
$conn->fetch_object($result);
Is there any way to achieve this? thanks
Update:
The get_result function is exactly what I need, but it's not working on my PHP
Well, if you do not want to use mysqli_stmt::fetch() but mysqli_result::fetch_*(), I guess it will be a little cumbersome.
http://www.joekolba.com/node/2
Alternatively, use PDO.
I have done it in the following way:
$stmt->prepare("select * from users where u_id = ? ");
$stmt->bind_param('s', $param);
$stmt->execute();
$stmt->bind_result($columns['column_name1'], $columns['column_name2'], $columns['column_name3']);
while ($stmt->fetch()) {
$row = (object) $columns;
}
That comes quite near the FETCH_OBJECT method. You can access all the data of one row via $row->column_name1 etc. Of course you would have to update the associative columns-array, when you alter your table and change names. But it works quite well for me. Didn't want to switch to PDO - considering the fact I switched to MYSQLi just some days ago ;)
To enable the method mysqli_stmt::get_result(), you need to use the mysqlnd (MySQL Native Driver) extension: http://php.net/manual/en/book.mysqlnd.php
For some reason, this concrete method is not implemented with the more usual libmysqlclient. In my debian server (and also on my ubuntu desktop) this amounted to run:
sudo apt-get install php5-mysqlnd
You need to call bind_result to tell mysqli which variables should hold the columns. Then every time you call fetch, those variables will be automatically filled in, and you can access them like normal. See the code below (not sure if it works, ymmv).
$conn = new mysqli(DB_HOST,DB_USERNAME,DB_PASSWORD, DB_NAME);
if($stmt = $conn->prepare('select * from users where u_id = ?'))
{
$stmt->bind_param("s", $param);
$stmt->execute();
$stmt->bind_result($column1, $column2, $column3);
while ($stmt->fetch()) {
echo "Column 1: $column1\n";
echo "Column 2: $column2\n";
echo "Column 3: $column3\n";
}
$stmt->close();
}