A variable seems to be uninitialized - php

I am calling a stored procedure from PHP and it is supposed to give me a date.
global $dbh;
$stmt = $dbh->prepare("CALL date_sp(?)");
$stmt->bindParam($employee_id, $return_value, PDO::PARAM_STR, 4000);
// Call the stored procedure
$stmt->execute();
I keep getting an error that variable $return_value (in the third line) is not initialized.

Be careful here. bindParam is used only for input parameters. Return values are handled with a different method. You should be doing:
$stmt = $dbh->prepare("CALL date_sp(:employee_id)");
$stmt->bindParam('employee_id', $employee_id, PDO::PARAM_STR, 4000);
// call the stored procedure
$stmt->execute();
Whenever writing code of this sort, be sure to check the API reference very carefully. There's often some subtle things you have to get perfectly right or nothing will work.
If you want to bind result values you can use bindColumn but it's often easier to just fetch it as an array and deal with it directly.

You don't actually need a named placed holder. Using the ? you would just do the following.
global $dbh;
$stmt = $dbh->prepare("CALL date_sp(?)");
$stmt->bindParam(1, $employee_id, PDO::PARAM_STR, 4000);
// call the stored procedure
$stmt->execute();
To actually fetch the result you would do something like:
$result = $stmt->fetch()

Related

Why isn't affected_rows working in this PHP Mysqli code?

I have a mysqli database object $DataBase and the following code works as intended:
$stmt = $DataBase->stmt_init();
$stmt->prepare("UPDATE `optshop_stock` SET quantity_b = ? WHERE product_id = ?;");
$stmt->bind_param('ii', $qty, $sku);
$stmt->execute();
$stmt->close();
But when I add:
echo $stmt->affected_rows;
between $stmt->execute() and $stmt->close() no value is echoed, not even a zero if nothing happened. Am I using this statement in a correct manner?
( I followed this http://php.net/manual/en/mysqli-stmt.affected-rows.php example)
The property can be retrieved at database level (reference here):
echo $DataBase->affected_rows;
I think you should try to add $stmt->store_result() after $stmt->execute(), otherwise you can't get right results when use $stmt->affected_rows

Difference between passing the data type and executing an array without them

I just want to know if these 2 sets of code are doing the same thing or not, if not what's the difference?
$connect= new CONNECT();
$sql = ("query here");
$stmt = $connect->runQuery($sql);
$stmt->bindParam(':sample', $_POST['sample'], PDO::PARAM_STR);
$stmt->bindParam(':sample2', $_POST['sample2'], PDO::PARAM_STR);
$stmt->bindParam(':sample3', $_POST['sample3'], PDO::PARAM_STR);
$stmt->execute();
=======================AND========================
$connect= new CONNECT();
$sql = ("query here");
$stmt = $connect->runQuery($sql);
$stmt->execute(Array(
':sample1' => $_POST['sample'],
':sample2' => $_POST['sample2'],
':sample3' => $_POST['sample3']
));
FYI, both work perfectly, just wanting to know if I'm getting the full security benefit using either one. Thanks.
By passing the parameters along with the $stmt->execute() method, all values in the array with be passed, as PDO::PARAM_STR to the statement with the $stmt->bindParam() function.
And with the $stmt->bindParam() function, you can define the data type passed along, using the PDO::PARAM_*
Read more about PDO::PARAM_

PDO bindParam not working in foreach

I am using PDO for an application but getting a problem for PDO bindParam(). I have an array and I want to use the values of array for PDO bindParam() using for loop or foreach() but an unexpected result is getting by foreach(). When I used bindParam() in for loop, it worked fine. What I tried was
$con = $this->connection();
$stmt = $con->prepare($sql);
for($i = 0; $i < count($params); $i++){
$stmt->bindParam($i + 1, $params[$i], PDO::PARAM_STR, 10);
}
$stmt->execute();
$result = $stmt->fetchAll();//$result is OK
But when I used bindParam() in foreach() then I got an empty array() as result. Below the codes
$con = $this->connection();
$stmt = $con->prepare($sql);
foreach($params as $key=>$val){ //Here
$stmt->bindParam($key + 1, $val, PDO::PARAM_STR, 10);
}
$stmt->execute();
$result = $stmt->fetchAll(); //$result is an empty array
I'm wondering why this happened. I can't find out the reason. Any information will be appreciated.
EDIT : I solved my problem using bindValue() instead.
use bindValue() instead of bindParam(). bindParam() binds to a reference, so when you execute the query all the parameters use the last value of $val.
If you already have the items in an array, there's no reason to call $stmt->bindParam in a loop; just do:
$con = $this->connection();
$stmt = $con->prepare($sql);
$stmt->execute($params);
$result = $stmt->fetchAll();
Per the PHP documentation:
Execute the prepared statement. If the prepared statement included
parameter markers, you must either:
call PDOStatement::bindParam() to bind PHP variables to the parameter
markers: bound variables pass their value as input and receive the
output value, if any, of their associated parameter markers
or pass an array of input-only parameter values

When using PDO::bindParam my query returns no results

I am doing the following query. If i put the numbers straight into the query the query returns lots of results... Now if I use the bindParam to pass the values there are no results.
I've tested whether or not the passed values have values and the echo shows that they do... so I have no idea why this is happening
Could anyone tell me what am i doing wrong?
public function searchWithPagination( $startPage = 0, $numberResultsPerPage = 10 ) {
$q = $this->db->prepare( 'SELECT * FROM ecm LIMIT :startpage, :numberresultsperpage' );
$q->bindParam(':startpage', $startPage);
$q->bindParam(':numberresultsperpage', $numberResultsPerPage);
$q->execute();
echo $numberResultsPerPage . $startPage ;
$f = $q->fetchAll();
var_dump($f);
}
EDIT: tried PDO::PARAM_INT still doesnt work
Try using bindValue instead of bindParam. In the user submitted notes in the PHP manual (php.net/manual/en/pdostatement.bindvalue.php) there is a note about bindParam passing by reference, whereas bindValue doesn't.
The limit parameters has to be bound as integers, the default binding is string.
$q->bindParam(':startpage', $startPage, PDO::PARAM_INT);
$q->bindParam(':numberresultsperpage', $numberResultsPerPage, PDO::PARAM_INT);
As it is stated in another question/answer:
How to apply bindValue method in LIMIT clause?
You need to bind the params explicitly as INT's, also you should cast them as integers.
$q->bindParam(':numberresultsperpage', (int)$numberResultsPerPage, PDO::PARAM_INT);
The problem is with your question.
In the code that actually runs, you are binding constant values
$q->bindParam(':startpage', 0);
$q->bindParam(':numberresultsperpage', 10);
which causes the error you mention:
Cannot pass parameter 2 by reference
But in the code you posted here you are binding variables
$q->bindParam(':startpage', $startPage);
$q->bindParam(':numberresultsperpage', $numberResultsPerPage);
which works all right, if fed with PDO::PARAM_INT or if emulation code is turned off.

Fatal error: Call to a member function close() on a non-object. MySQLi issue

I have been getting the following error when I uploaded to a live server. It works OK on localhost which I thought was strange.
Fatal error: Call to a member function close() on a non-object....
The line it refers to
$stmt->close();
The connection to the DB
$connection=new mysqli($MYSQL_HOST,$MYSQL_USER,$MYSQL_PASS,$DB)or die(mysqli_error($connection));
The class itself.
function getTimes(){ //this method just pulls the results of the query and returns them as an array
global $connection;
$route = $this->route;
$station = $this->station;
$day = $this->day;
// create a prepared statement
if ($stmt = $connection->prepare("select time from timetable where route=? and day=? and station=?")) {
$stmt->bind_param("sss", $route, $day, $station); // bind parameters for markers
$stmt->execute(); //execute query
$stmt->bind_result($col1); //bind result variables
while ($stmt->fetch()){
$results[]=$col1;
}
}
$stmt->close();//close statement
return $results;
}
You should put $stmt into you if clause. There is a possiblity that if (false) and still get to your $stmt->close();
Your problem was that the $stmt object was instantiated as part of an if condition test. In the cases it failed, i.e. when it returns false, you were still trying to call ->close() on it anyway. I moved the method call within the if block.
Now you need to add an else clause to handle the fact that your script couldn't prepare the statement and given you say this works locally but not on your live server, I suggest there is some configuration difference causing a problem here. You need to turn on error handling with display_errors('1') and error_reporting(E_ALL). Don't forget to turn these off before letting the world at your new script. :)
function getTimes(){ //this method just pulls the results of the query and returns them as an array
global $connection;
$route = $this->route;
$station = $this->station;
$day = $this->day;
// create a prepared statement
if ($stmt = $connection->prepare("select time from timetable where route=? and day=? and station=?")) {
$stmt->bind_param("sss", $route, $day, $station); // bind parameters for markers
$stmt->execute(); //execute query
$stmt->bind_result($col1); //bind result variables
while ($stmt->fetch()){
$results[]=$col1;
}
$stmt->close();//close statement
}
return $results;
}
Move the close() call into your if statement, so that it will only be called if a $stmt was successfully created.
// create a prepared statement
if ($stmt = $connection->prepare("select time from timetable where route=? and day=? and station=?")) {
$stmt->bind_param("sss", $route, $day, $station); // bind parameters for markers
$stmt->execute(); //execute query
$stmt->bind_result($col1); //bind result variables
while ($stmt->fetch()){
$results[]=$col1;
}
$stmt->close();//close statement
}
I suspect on your local machine you don't have errors turned on, but on the server you upload to, errors are on.
The root issue to address here is the fact that prepare() is failing. The problem there most likely is the database on the server is missing the timetable table or that table is missing one or more fields route, day or station. As said by cbuckley, check $connection->error for the full error message.
When you uploaded to the server, did you remember to also make any database structure changes on the server?

Categories