I've get this error on the page. What can be the problem.. I've checked tons of thread here with the same problem and can't figured it out.
$ip_address = $_SERVER['REMOTE_ADDR'];
$vote_rank = 0;
$query = $pdo->prepare("SELECT SUM(vote_rank) as vote_rank FROM ipaddress_vote_map WHERE image_id = ? and ip_address = ?");
$query -> bindParam(1, $_GET['image_id'], PDO::PARAM_INT);
$query -> bindParam(1, $ip_address, PDO::PARAM_INT);
$rowsa = $pdo->execute();
$up = "";
$down = "";
if(!empty($rowsa[0]["vote_rank"])) {
$vote_rank = $row[0]["vote_rank"];
if($vote_rank == -1) {
$up = "enabled";
$down = "disabled";
}
if($vote_rank == 1) {
$up = "disabled";
$down = "enabled";
}
}
Prepare returns the object you need to execute so your code should be:
$stmt= $pdo->prepare("SELECT SUM(vote_rank) as vote_rank FROM ipaddress_vote_map WHERE image_id = ? and ip_address = ?");
$stmt-> bindParam(1, $_GET['image_id'], PDO::PARAM_INT);
$stmt-> bindParam(2, $ip_address, PDO::PARAM_INT);
$rowsa = $stmt->execute();
execute is a method of the PDOStatement class (see docs), not of PDO. The return value of PDO::prepare is an instance of PDOStatement, so replace $pdo->execute(); with $query->execute();
The bindParam calls also seem incorrect to me, as the docs say on the first argument ($parameter):
Parameter identifier. For a prepared statement using named placeholders, this will be a parameter name of the form :name. For a prepared statement using question mark placeholders, this will be the 1-indexed position of the parameter.
This means that this:
$query -> bindParam(1, $_GET['image_id'], PDO::PARAM_INT);
$query -> bindParam(1, $ip_address, PDO::PARAM_INT);
Should be:
$query->bindParam(1, $_GET['image_id'], PDO::PARAM_INT);
$query->bindParam(2, $ip_address, PDO::PARAM_INT);
Related
I am working on the below code. How can I export the result of one row in JSON?
I tried this like
$arr = [];
$arr = $stmt->get_result()->fetch();
but I am getting this error:
Uncaught Error: Call to undefined method mysqli_stmt::get_result()
$stmt = $mysqli -> prepare('SELECT id, name, email, phone FROM users WHERE id = ?');
$userId = 1; // or $_GET['userId'];
$stmt -> bind_param('i', $userId);
$stmt -> execute();
$stmt -> store_result();
$stmt -> bind_result($id, $name, $email, $phone);
$stmt -> fetch();
You must be using a very old PHP version, probably PHP 5.3. I strongly recommend to upgrade to a recent version as soon as possible.
Once you have upgraded, you can use the following.
$stmt = $mysqli->prepare('SELECT id, name, email, phone FROM users WHERE id = ?');
$userId = 1; // or $_GET['userId'];
$stmt->bind_param('i', $userId);
$stmt->execute();
$json = json_encode($stmt->get_result()->fetch_assoc());
I found a useful example in the php documentation here: https://www.php.net/manual/en/mysqli-stmt.bind-result.php
Based on that example, here's what I recommend for you:
$results = array();
$stmt = $mysqli -> prepare('SELECT id, name, email, phone FROM users WHERE id = ?');
$userId = 1; // or $_GET['userId'];
$stmt -> bind_param('i', $userId);
$stmt -> execute();
$stmt -> bind_result($id, $name, $email, $phone);
while($stmt->fetch()){
$results[] = array(
"id"=>$id,
"name"=>$name,
"email"=>$email,
"phone"=>$phone
);
}
$stmt->close();
$output = json_encode($results);
Use PDO:
$db = new PDO("mysql:host=$hostname;dbname=$dbname",$username,$password);
$sth = $db->prepare("SELECT id, name, email, phone FROM users WHERE id = ?");
$sth->execute([ $userId ]); // or $_GET['userId'];
$dbUser = $sth->fetch(PDO::FETCH_ASSOC);
echo json_encode($dbUser);
If you project is API use:
header('Access-Control-Allow-Origin: *'); // For CORS
header('Content-Type: application/json');
When I run the PDO script alone it runs just fine But when I run it in a function I get this error Fatal error: Call to a member function prepare() on a non-object. I can not figure out why it is happening.
$pid = 6;
$custid = 1;
$sql = "SELECT COUNT(*) from signings WHERE pid = ? AND custid = ?";
$stmt = $db->prepare($sql);
$stmt->bindParam(1, $pid, PDO::PARAM_INT);
$stmt->bindParam(2, $custid, PDO::PARAM_STR);
$stmt->execute();
$number_of_rows = $stmt->fetchColumn();
echo $number_of_rows;
$pid = 6;
$custid = 1;
function test($custid,$pid){
$sql = "SELECT COUNT(*) from signings WHERE pid = ? AND custid = ?";
$stmt = $db->prepare($sql);
$stmt->bindParam(1, $pid, PDO::PARAM_INT);
$stmt->bindParam(2, $custid, PDO::PARAM_STR);
$stmt->execute();
$number_of_rows = $stmt->fetchColumn();
echo $number_of_rows;
}
echo test($custid,$pid);
The variable $db is not visible inside your function. you need to add
function test($custid,$pid){
global $db;
[...]
}
inside your function or you should pass the db object to your function via parameter:
function test($db, $custid,$pid){
[...]
}
another nice way ist to work with the factory patterns:
create a class db with a static method dbFactory and call it whenever you need to access your db
class db {
public static function dbFactory($host, $dbase, $user, $pass) {
$pdo = new PDO("mysql:host=$host;dbname=$dbase", $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
return $pdo;
}
}
$db = db::dbFactory('localhost','mydbname','myusername','mypassword');
I'm trying to convert mysql_query over to prepared statements, but it's failing silently and I'm not sure where I'm going wrong. Here's my proc.php page for a form:
$db = new PDO('mysql:host=XXX;dbname=XXX;charset=utf8', 'XXX', 'XXX');
if ($_POST['submit']) {
$type = $_POST['type'];
$auth1_lname = trim($_POST['auth1_lname']);
$auth1_fname = trim($_POST['auth1_fname']);
$today = date("Y-m-d");
$stmt = $db->prepare("INSERT INTO table_base ( type , publ_date , auth1_lname , auth1_fname )
VALUES (:type, :today, :auth1_lname , :auth1_fname) ");
$stmt->bindParam(':type', $type);
$stmt->bindParam(':today', $today);
$stmt->bindParam(':auth1_lname', $auth1_lname);
$stmt->bindParam(':auth1_fname', $auth1_fname);
$stmt->execute();
$bid = $db->lastInsertId();
$subj_area = $_POST['subj_area'];
$subject = 'subj_area';
$subjs = '';
$stmt = $db->prepare("INSERT INTO table_meta (bid, key, value) VALUES (:bid, :key, :value)");
$stmt->bindParam(':bid', $bid);
$stmt->bindParam(':key', $subject);
$stmt->bindParam(':value', $subjs, PDO::PARAM_STR);
foreach($subj_area as $subjs) {
$stmt->execute();
}
$geo_area = $_POST['geo_area'];
$geograph = 'geo_area';
$geos = '';
$stmt = $db->prepare("INSERT INTO table_meta (bid, key, value) VALUES (:bid, :key, :value)");
$stmt->bindParam(':bid', $bid);
$stmt->bindParam(':key', $geograph);
$stmt->bindParam(':value', $geos, PDO::PARAM_STR);
foreach($geo_area as $geos) {
$stmt->execute();
}
}
I'm not sure I'm even doing this right.
I see comments elsewhere on SO that your PHP must be this tall to use PDO, but php.net's page on PDO doesn't list PHP requirements. Am I failing b/c my PHP5 host doesn't have the right drivers?
Is there a way to add a die(mysql_error()) so at least it wouldn't be a silent failure?
I'm kind of new with PDO and currently developing the API call that returns search results. How do I set a prepare statement if there are 2 optional parameters for the search query?
$app->get('/get/search', function () {
$sql = 'SELECT * FROM user WHERE name LIKE :name AND city = :city AND gender = :gender';
try {
$stmt = cnn()->prepare($sql);
$stmt->bindParam(':name', '%'.$_GET['name'].'%', PDO::PARAM_STR);
$stmt->bindParam(':city', '%'.$_GET['city'].'%', PDO::PARAM_STR);
$stmt->bindParam(':gender', $_GET['gender'], PDO::PARAM_INT);
$stmt->execute();
if($data = $stmt->fetchAll()) {
echo json_encode($data);
} else {
echo json_encode(array('error' => 'no records found');
}
} catch(PDOException $e) {
echo json_encode(array('error' => $e->getMessage()));
}
}
The issue here, is that both $_GET['city'] and $_GET['gender'] are optional. If I try to run the code above, it will asume that any empty variable should match an empty value in the column as well; in the other hand, if I do something like this:
if($_GET['gender']) $stmt->bindParam(':gender', $_GET['gender'], PDO::PARAM_INT);
...it will return this error: "SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens"
So, what's the solution if I want to keep the prepared sql statement for optional parameters? Thanks!
Update
This is the solution based on the accepted answer and some comments (by deceze and bill-karwin):
if($_GET['name']) $where[] = 'name LIKE :name';
if($_GET['city']) $where[] = 'city LIKE :city';
if(isset($_GET['gender'])) $where[] = 'gender = :gender';
if(count($where)) {
$sql = 'SELECT * FROM user WHERE '.implode(' AND ',$where);
$stmt = cnn()->prepare($sql);
$name = '%'.$_GET['name'].'%';
if($_GET['name']) $stmt->bindValue(':name', '%'.$_GET['name'].'%', PDO::PARAM_STR);
$city = '%'.$_GET['city'].'%';
if($_GET['city']) $stmt->bindParam(':city', $city, PDO::PARAM_STR);
if(isset($_GET['gender'])) $stmt->bindParam(':gender', $_GET['gender'], PDO::PARAM_BOOL);
$stmt->execute();
if($data = $stmt->fetchAll()) {
echo json_encode($data);
}
}
Some good old dynamic SQL query cobbling-together...
$sql = sprintf('SELECT * FROM user WHERE name LIKE :name %s %s',
!empty($_GET['city']) ? 'AND city = :city' : null,
!empty($_GET['gender']) ? 'AND gender = :gender' : null);
...
if (!empty($_GET['city'])) {
$stmt->bindParam(':city', '%'.$_GET['city'].'%', PDO::PARAM_STR);
}
...
You can probably express this nicer and wrap it in helper functions etc. etc, but this is the basic idea.
There is a nice little function which can help: tiniest query builder. No frameworks or ORMs needed to make code look like this:
public function updateUser(int $id, string $email = '', string $password = '', string $name = '') {
$sql = \App\Utils\build_query([
[ 'UPDATE "users"'],
[$email ,'SET', 'email=:email'],
[$password ,',', 'password=:password'],
[$name ,',', 'name=:name'],
[ 'WHERE "id"=:id']
]);
$stmt = $this->db->prepare($sql);
$stmt->bindValue(':id', $id, \PDO::PARAM_INT);
// Optional bindings.
$email && $stmt->bindValue(':email', $email, \PDO::PARAM_STR);
$password && $stmt->bindValue(':password', $password, \PDO::PARAM_STR);
$name && $stmt->bindValue(':name', $name, \PDO::PARAM_STR);
$stmt->execute();
}
Note how neatly query components are created, with support for optional ones of course. The && experssions by bindings simply check whether this parameter is given, and if it is, then appropriate bindValue are called.
I'm working with a sequence of queries created with PDO class, in some case, my queries needs the same parameter.
I've created an array used in a foreach statement which save the data but some variables come from outside, can I use both data in one query?
the example:
// $connection is the PDO object;
// $full_data contains:
// $full_data[$i]["address"]
// $full_data[$i]["phone"]
// $full_data[$i]["email"]
// $full_data[$i]["user_id"]
// $full_data[$i]["surname"] // not used but present
// $full_data[$i]["name"] // not used but present
$sql = "UPDATE users_table SET city = :address, phone = :phone, email = :email, admin_id = :admin_id, admin_name = :admin_name WHERE user_id = :user_id";
$statement = $connection->prepare ($sql);
$statement->bindParam (':admin_id', trim($admin_id), PDO::PARAM_INT);
$statement->bindParam (':admin_name', trim($admin_name), PDO::PARAM_STR);
foreach ($full_data as $value) {
$ok = $statement->execute ($value);
$num = $statement->rowCount ();
}
} catch (PDOException $e) {
return $e->getMessage ();
}
this page return me the error:
SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
what is exactly the problem, on an UPDATE statement the technique works
damn, I've found the problem after hours...
// $connection is the PDO object;
// $full_data contains:
// $full_data[$i]["address"]
// $full_data[$i]["phone"]
// $full_data[$i]["email"]
// $full_data[$i]["user_id"]
// ==> $full_data[$i]["surname"] // not used but present
// ==> $full_data[$i]["name"] // not used but present
the array data not saved in the query ["surname"] and ["name"] generate the error.
It seems like execute (); needs precise array data structure.
I've solved the problem by using this:
$sql = "UPDATE users_table SET city = :address, phone = :phone, email = :email, admin_id = :admin_id, admin_name = :admin_name WHERE user_id = :user_id";
$statement = $connection->prepare ($sql);
// must be removed ==> $statement->bindParam (':admin_id', trim($admin_id), PDO::PARAM_INT);
// must be removed ==> $statement->bindParam (':admin_name', trim($admin_name), PDO::PARAM_STR);
for ($i = 0; $i < count($full_data); $i++) {
$full_data[$i]["admin_name"] = "the admin name";
$full_data[$i]["admin_id"] = "100";
unset ($full_data[$i]["surname"]); // IMPORTANT: must remove the unused vars
unset ($full_data[$i]["name"]); // IMPORTANT: must remove the unused vars
}
foreach ($full_data as $value) {
// bindParam can be avoided, but it's recommended for data type security
$statement->bindParam(':address', trim($value['address']), PDO::PARAM_STR);
$statement->bindParam(':phone', trim($value['phone']), PDO::PARAM_STR);
$statement->bindParam(':email', trim($value['email']), PDO::PARAM_STR);
$statement->bindParam(':admin_id', trim($value['admin_id']), PDO::PARAM_INT);
$statement->bindParam(':admin_name', trim($value['admin_name']), PDO::PARAM_STR);
$ok = $statement->execute ($value);
$num = $statement->rowCount ();
}
} catch (PDOException $e) {
return $e->getMessage ();
}
You need to bind the :address, :phone, and :email parameters.
To elaborate on BD answer you're missing the following lines of code:
$statement->bindParam (':address', trim($address), PDO::PARAM_STR);
$statement->bindParam (':phone', trim($phone), PDO::PARAM_STR);
$statement->bindParam (':email', trim($email), PDO::PARAM_STR);
Plus, something seems to be wrong with your foreach loop, I think this is what you want:
$sql = "UPDATE users_table SET city = :address, phone = :phone, email = :email, admin_id = :admin_id, admin_name = :admin_name";
$statement = $connection->prepare($sql);
$statement->bindParam(':admin_id', trim($admin_id), PDO::PARAM_INT);
$statement->bindParam(':admin_name', trim($admin_name), PDO::PARAM_STR);
foreach ($full_data as $value)
{
$statement->bindParam(':address', trim($value['address']), PDO::PARAM_STR);
$statement->bindParam(':phone', trim($value['phone']), PDO::PARAM_STR);
$statement->bindParam(':email', trim($value['email']), PDO::PARAM_STR);
$ok = $statement->execute();
$num = $statement->rowCount();
}