Why do I not get a result in the following code and num_rows returns 0?
Here is my code:
function get_user($user_id) {// This function give some data from table user with user_id
try {
$connection = start_service();
$user_id = sanitize_string($user_id);
$stmt = $connection->prepare(
"SELECT user_id, name, lname, gender, password, avatar, bdate, user_group_id, status, signup_date, last_signin
FROM user
WHERE user_id = ?
");
$stmt->bind_param("i", $user_id);
$stmt->execute();
$stmt->bind_result($user_id, $name, $lname, $gender, $password, $avatar, $bdate, $user_group_id, $status, $signup_date, $last_signin);
if($stmt->num_rows){
while($stmt->fetch()) {
array_push($result, array(
"user_id" => $user_id,
"name" => $name,
"lname" => $lname,
"gender" => $gender,
"password" => $password,
"avatar" => $avatar,
"bdate" => $bdate,
"user_group_id" => $user_group_id,
"status" => $status,
"signup_date" => $signup_date,
"last_signin" => $last_signin
));
}
} else {
$result = false;
}
print $stmt->num_rows;
$stmt->close();
end_service();
} catch (exception $e) {
end_service_error();
echo $e->getMessage(), "\n";
throw $e;
}
return $result;
}
Where is the problem and what must I do to fix it?
I think you need to call mysqli_stmt_store_result() before calling mysqli_stmt_num_rows().
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($user_id, $name, $lname, $gender, $password, $avatar, $bdate, $user_group_id, $status, $signup_date, $last_signin);
if($stmt->num_rows){
...
}
Related
I'm having the problem that the query I'm passing through a function is duplicating me the rows. Before, instead of the statement->execute(array()), I had PARAM_STR working for each value. However, it started to give me problems. This is the code that is duplicating me the rows.
static public function mdlIngresarUsuario($datos){
$statement = Conexion::conectar()->prepare("INSERT INTO usuarios (id, nombre, usuario, password, rol, estado) VALUES (null, :nombre, :usuario, :password, :rol, :estado)");
$statement->execute(array(
':nombre' => $datos['nombre'],
':usuario' => $datos['usuario'],
':password' => $datos['password'],
':rol' => $datos['rol'],
':estado' => 0
));
if ($statement->execute()) {
return "ok";
} else {
return "error";
}
}
You're executing the statement twice:
$statement->execute(array(
':nombre' => $datos['nombre'],
':usuario' => $datos['usuario'],
':password' => $datos['password'],
':rol' => $datos['rol'],
':estado' => 0
));
and then in the condition of the if statement:
if ($statement->execute()) {
return "ok";
}
Just log the return of the first "execute", and use that as the condition:
$success = $statement->execute(array(
':nombre' => $datos['nombre'],
':usuario' => $datos['usuario'],
':password' => $datos['password'],
':rol' => $datos['rol'],
':estado' => 0
));
if( $success ) { return "ok"; }
This is happening because you call $statement->execute twice, once where you 'create' it and once in the if statement. You should assign the value of the first execute to a variable and use that variable in the if statement, like:
public static function mdlIngresarUsuario($datos)
{
$statement = Conexion::conectar()->prepare("INSERT INTO usuarios (id, nombre, usuario, password, rol, estado) VALUES (null, :nombre, :usuario, :password, :rol, :estado)");
$result = $statement->execute(array(
':nombre' => $datos['nombre'],
':usuario' => $datos['usuario'],
':password' => $datos['password'],
':rol' => $datos['rol'],
':estado' => 0
));
if ($result) {
return "ok";
} else {
return "error";
}
}
I am using this php code to insert new record in database. The problem is that if ($query) sometimes returns true and when I check the table, there is no new record. Why is it not inserting the record? and why is it returning true when it should return false in case of failing?
public function insertUserMileage($alias, $address, $distance, $city,
$latitude, $longitude, $id) {
$sql = 'INSERT INTO user_mileage (user_id, alias, address, distance,
city, lat, lng) VALUES (:id, :alias, :address, :distance, :city,
:latitude, :longitude)';
$query = $this->conn->prepare($sql);
$query->execute(array(':id' => $id, ':alias' => $alias,
':address' => $address, ':distance' => $distance, ':city' => $city,
':latitude' => $latitude, ':longitude' => $longitude));
if ($query) {
return true; // Insert success
} else {
return false; // Insert fail
}
}
You need to check the return value of execute:
$result = $query->execute(array(':id' => $id, ':alias' => $alias,
':address' => $address, ':distance' => $distance, ':city' => $city,
':latitude' => $latitude, ':longitude' => $longitude));
if ($result) {
return true; // Insert success
} else {
return false; // Insert fail
}
I'm trying to execute two INSERT statements and I need the last inserted id to do so. I've tried $question_id = $dbh->lastInsertId();, but it doesn't work. Now I'm executing an additional SELECT LAST_INSERT_ID() statement, but that doesn't work either. I keep getting this error: SQLSTATE[HY093]: Invalid parameter number: parameter was not defined, which occurs because $question_id is empty because selecting the last insert id doesn't seem to work.
Here's my code:
public function add_question($user_id, $group_id, $title, $caption, $datetime, $status) {
// Add user to database
try {
$dbh = new DBHandler();
$sql =
"INSERT INTO question(
user_id,
group_id,
title,
caption,
created_date_time,
question_status
)
VALUES(
:user_id,
:group_id,
:title,
:caption,
:created_date_time,
:question_status
)";
$stmt = $dbh->get_instance()->prepare($sql);
$stmt->execute(
array(
':user_id' => $user_id,
':group_id' => $group_id,
':title' => $title,
':caption' => $caption,
':created_date_time' => $datetime,
':status' => $status
)
);
//$question_id = $dbh->lastInsertId();
$sql= "SELECT LAST_INSERT_ID() AS question_id";
$stmt = $dbh->get_instance()->prepare($sql);
$stmt->execute();
// Resultset
$result = $stmt->fetchAll();
foreach($result AS $question_id_row) {
$question_id = $question_id_row['question_id'];
}
$sql =
"INSERT INTO notification(
n_question_id,
n_question_user_id,
n_question_group_id,
n_question_title
)
VALUES(
:n_question_id,
:n_question_user_id,
:n_question_group_id,
:n_question_title
)";
$stmt = $dbh->get_instance()->prepare($sql);
$stmt->execute(
array(
':n_question_id' => $question_id,
':n_question_user_id' => $user_id,
':n_question_group_id' => $group_id,
':n_question_title' => $title
)
);
echo 'Question added!';
}
catch(PDOException $e) {
echo $e->getMessage();
}
}
Your query fails with invalid number of parameter and parameter was not defined because you define this parameter
:question_status
but you bind
':status' => $status
change
$stmt->execute(
array(
':user_id' => $user_id,
':group_id' => $group_id,
':title' => $title,
':caption' => $caption,
':created_date_time' => $datetime,
':question_status' => $status //here
)
);
and it will work
If I run my function edit_profile() without any parameter, then empty strings are written in DB. If $input['email'] is empty for example, I'd like UPDATE not to update this column.
I tried to do:
SET email = IF(LENGTH(:email)=0, email, :email),
It didn't work, I'm not sure how to do same as above with PDO.
function edit_profile($input) {
//
$user_id = 1;
//
try {
//
$conn = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME, DB_USERNAME, DB_PASSWORD);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $conn->prepare('UPDATE users SET
email = :email,
password = :password,
name_surname = :name_surname,
age = :age,
sex = :sex,
education = :education,
avatar = :avatar
WHERE id = :id');
$stmt->execute(array(
':id' => $user_id,
':email' => $input['email'],
':password' => $input['password'],
':name_surname' => $input['name_surname'],
':age' => $input['age'],
':sex' => $input['sex'],
':education' => $input['education'],
':avatar' => $input['avatar']
));
echo $stmt->rowCount(); // 1
//
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
//
}
edit_profile();
Try
UPDATE users SET
email = COALESCE(NULLIF(:email, ''),email),
password = :password,
name_surname = :name_surname,
age = :age,
sex = :sex,
education = :education,
avatar = :avatar
WHERE id = :id
I'm basically trying to use COALESCE (http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_coalesce) to use :email only if not null. If it's null, use the old email.
In case :email is empty string and not simply NULL, I've added NULLIF to convert the empty string to NULL ;)
SET email = IF(LENGTH(:email1)=0, email, :email2)
$stmt->execute(array(
':id' => $user_id,
':email1' => $input['email'],
':email2' => $input['email'],
':password' => $input['password'],
':name_surname' => $input['name_surname'],
':age' => $input['age'],
':sex' => $input['sex'],
':education' => $input['education'],
':avatar' => $input['avatar']
));
I'm creating a multi-step form for my users. They will be allowed to update any or all the fields. So, I need to send the values, check if they are set and if so, run an UPDATE. Here is what I have so far:
public function updateUser($firstName, $lastName, $streetAddress, $city, $state, $zip, $emailAddress, $industry, $password, $public = 1,
$phone1, $phone2, $website,){
$updates = array(
'firstName' => $firstName,
'lastName' => $lastName,
'streetAddress' => $streetAddress,
'city' => $city,
'state' => $state,
'zip' => $zip,
'emailAddress' => $emailAddress,
'industry' => $industry,
'password' => $password,
'public' => $public,
'phone1' => $phone1,
'phone2' => $phone2,
'website' => $website,
);
Here is my PDO (well, the beginning attempt)
$sth = $this->dbh->prepare("UPDATE user SET firstName = "); //<---Stuck here
$sth->execute();
$result = $sth->fetchAll(PDO::FETCH_ASSOC);
return $result;
Basically, how can I create the UPDATE statement so it only updates the items in the array that are not NULL?
I thought about running a foreach loop like this:
foreach($updates as $key => $value) {
if($value == NULL) {
unset($updates[$key]);
}
}
but how would I write the prepare statement if I'm unsure of the values?
If I'm going about this completely wrong, please point me in the right direction. Thanks.
First of all, use array_filter to remove all NULL values:
$updates = array_filter($updates, function ($value) {
return null !== $value;
});
Secondly, bind parameters, that makes your live a lot easier:
$query = 'UPDATE table SET';
$values = array();
foreach ($updates as $name => $value) {
$query .= ' '.$name.' = :'.$name.','; // the :$name part is the placeholder, e.g. :zip
$values[':'.$name] = $value; // save the placeholder
}
$query = substr($query, 0, -1).';'; // remove last , and add a ;
$sth = $this->dbh->prepare($query);
$sth->execute($values); // bind placeholder array to the query and execute everything
// ... do something nice :)
The below can be optimized:
$i = 0; $query = array();
foreach($updates as $key => $value) {
if ($value != NULL) {
$query[] = "{$key} = :param_{$i}";
$i++;
}
}
if (! empty($query)) {
$finalQuery = implode(",", $query);
$sth = $this->dbh->prepare('UPDATE user SET ' . $finalQuery);
$i = 0;
foreach($updates as $key => $value) {
if ($value != NULL) {
$sth->bindParam(':param_'.$i, $value, PDO::PARAM_STR);
$i++;
}
}
}