bindParam or binValue will not work - pdo

Hi It seems that both bindParam or bindValue methods will not work.
Please advise. I tried to bind the $dbname to dbtest. It does not seem to work!
bindParam
$dbname = "test1";
$stmt=$dbh->prepare('use :dbtest');
$stmt->bindParam(':dbtest', $dbname, PDO::PARAM_STR);
$firephp->fb($stmt);
try
{ $stmt->execute();
$stmt=$dbh->prepare('select database()');
$stmt->execute();
$count = $stmt->fetch(PDO::FETCH_ASSOC);
$firephp->warn("Attempting to use selected database is successful.");
}
bindValue
$dbname = "test1";
$stmt=$dbh->prepare('use :dbtest');
$stmt->bindValue(':dbtest', $dbname, PDO::PARAM_STR);
$firephp->fb($stmt);
try
{ $stmt->execute();
$stmt=$dbh->prepare('select database()');
$stmt->execute();
$count = $stmt->fetch(PDO::FETCH_ASSOC);
$firephp->warn("Attempting to use selected database is successful.");
$firephp->fb($count);
}
What could be the problem?

First, native prepared statements won't work for identifiers
Second, there is no point in having dynamically bound databases. They are supposed to be constant.
So, select your database in DSN and then use bindValue to bind values in the query.

Related

number of bound variables does not match number of tokens

I am facing "number of bound variables does not match number of tokens" exception while trying to use multiple condition in where clause using PDO.
code:
$servername = "localhost";
$username = "xxxx";
$password = "xxxxx";
$dbname = "yyyy";
$searchParam = $_POST['typeahead'];
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $conn->prepare("SELECT * FROM trucks WHERE plate_number LIKE :plateNumber OR company_name LIKE: companyName");
$stmt->bindValue(':plateNumber', '%'.$searchParam.'%', PDO::PARAM_INT);
$stmt->bindValue(':companyName', '%'.$searchParam.'%', PDO::PARAM_INT);
I am trying to search depending on either plate_number or company_name. For the same reason I am binding the two place holders(variables). the code works while I use only 1 variable but not two. how to bind two variables?
You can use
$stmt->bindValue(array(':plateNumber', '%'.$searchParam.'%', PDO::PARAM_INT,':companyName', '%'.$searchParam.'%', PDO::PARAM_INT));

Truncate all tables before running seed files with Phinx

So, I have been creating migrations using Phinx. I want to be able to truncate all the tables(148 tables) before running the seed files. I am thinking about just creating a seed file that will be ran first and then it will truncate all the tables. The catch is that I don't want to have to ever change this file if we add more tables. How would I go about doing this. Maybe doing a Show tables and then looping through them, but not exactly sure how to do that. Any help would be great! This is what I have so far.
<?php
use Phinx\Seed\AbstractSeed;
class BonusRuleTypesSeeder extends AbstractSeed
{
public function run()
{
$this->execute('SET foreign_key_checks=0');
// some code here
$this->execute('SET foreign_key_checks=1');
}
}
If you have a migrations table, then this will truncate that table as well. This would work.
$this->execute('SET foreign_key_checks=0');
foreach($tables as $table){
$table = $table["Tables_in_".$database];
if ($table != $config->getProperty(['phinx', 'default_migration_table'])){
$sql = "TRUNCATE TABLE ".$table;
$this->execute($sql);
}
}
Here is the answer
$config = new Config(__DIR__.'/../../config/default.ini',true);
$host = $config->getProperty(['db', 'host']);
$database = $config->getProperty(['db', 'name']);
$username = $config->getProperty(['db', 'username']);
$password = $config->getProperty(['db', 'password']);
$mysqli = new mysqli($host, $username, $password, $database);
$query = "Show tables";
$tables = $mysqli->query($query);
$tables->fetch_all();
$mysqli->close();
$this->execute('SET foreign_key_checks=0');
foreach($tables as $table){
$table = $table["Tables_in_".$database];
$sql = "TRUNCATE TABLE ".$table;
$this->execute($sql);
}
$this->execute('SET foreign_key_checks=1');

Switching from mysql_ to PDO

After a lot of recommendation from others I have decided to make the switch from mysql_ to PDO. I started looking at PDO literally around 15 minutes ago and I'm stuck trying to convert this line of code into PDO format.
function verify_user($username, $recover_password) {
return (mysql_result(mysql_query("SELECT COUNT(`user_id`) FROM `users` WHERE `username` = '$username' AND `password_recovery` = '$recover_password'"), 0) == 1) ? true : false;
}
I have looked at a couple of tutorials and as far as I can work out I can do the actual query with this code:
$verify_user = "SELECT COUNT(`user_id`) FROM `users` WHERE `username` = '$username' AND `password_recovery` = '$recover_password'";
$result = $con->prepare($verify_user);
$result->execute();
The problem I am having is the second part of the line of code - the mysql_result. Now that the query has run I have no idea how to return true or false using PDO. I'd appreciate any help. Thanks!
Updated:
$result = $con->prepare("SELECT COUNT(`user_id`) FROM `users` WHERE `username` = :username AND `password_recovery` = :recover_password");
$result->bindParam(':username', $username, PDO::PARAM_STR);
$result->bindParam(':password_recovery', $recover_password, PDO::PARAM_STR);
$result->execute();
From reading that page you provided it would be:
$result = $con->prepare("SELECT COUNT(`user_id`) FROM `users` WHERE `username` = :username AND `password_recovery` = :recover_password");
$result->bindParam(':username', $username, PDO::PARAM_STR);
$result->bindParam(':password_recovery', $recover_password, PDO::PARAM_STR);
$result->execute();
return ($con->fetch($result) == 1) ? true : false;
I'm probably miles out but I appreciate the help you've given me :) I'll do a couple more searches.
I would write the function this way:
function verify_user($username, $recover_password) {
$sql = "SELECT COUNT(`user_id`) AS count FROM `users`
WHERE `username` = ? AND `password_recovery` = ?";
$stmt = $con->prepare($sql);
$stmt->execute(array($username, $recover_password));
while ($row = $stmt->fetch()) { } /* should be exactly one row anyway */
return $row["count"] == 1;
}
There's no need to use bind_param(), since you can just pass values in an array argument to execute(). And there's no need to specify the parameter type (that's actually ignored, at least in the MySQL PDO driver).
Also be careful to do error-checking. The prepare() and execute() functions return false on error. Many things can cause an error. You could misspell a column name. Your database connection may lack the right database privileges. Someone could drop the table.
FWIW, proper error-checking is important when using the mysql_* and mysqli_* API's too, but it seems that few people do it right.
In the above code, I don't show checking the return values because I've made an assumption that we've enabled exceptions when we created the PDO connection.
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
That relieves us of having to write code to check the return values every time, but it means that an error will cause our application to go "white-screen". It's best practice to handle the exceptions in the caller function, and display some friendly error screen.

Bindparam and Like condition when querying

I have this function that should just look in the database for a name similars to an user input. However I can't use Like with the param :uname.
Everyone I look in the web they suggest me to do something like this
$username = "$%username%";
However the query doesn't return any result.
I know the database is properly made because if I ask this, it returns the proper answer
SELECT * FROM $schema.pessoa WHERE nome LIKE %Mike%
However in my code $username contains "Mike" and yet it doesn't return anything, I assumed %username hadn't be properly made however if I make an echo of it, it indeed contains the string I want- "Mike".
So the problem seems to be in the way I am questioning it with the parameter but I have no idea
function SearchUser($username) {
global $dbh, $schema;
try {
$username = "$%username%";
$stmt = $dbh->prepare("SELECT * FROM $schema.pessoa WHERE nome LIKE :uname");
$stmt->bindParam(':uname', $username);
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if(empty($result))
{echo 'empty';}
return $result;
}
catch(PDOException $e) {
$_SESSION["s_errors"]["generic"][] = "ERRO[32]: ".$e->getMessage();
header("Location: list.php");
die;
}
It does look right to me,
I could only suggest you try it this way and see if that makes any difference
$username = 'Mike';
$stmt->bindValue(":uname", "%".$username."%");
Edit.
Looking at it again, this doesn't look right to me..
$username = '$%username%';
Shouldn't it be
$username = '%'.$username.'%';

SQL optimisation

I want to optimize some of the SQL and just need an opinion on whether I should do it or leave it as is and why I should do it. SQL queries are executed via PHP & Java, I will show an example in PHP which will give an idea of what Im doing.
Main concerns are:
-Maintainability.
-Ease of altering tables without messing with all the legacy code
-Speed of SQL (is it a concern???)
-Readability
Example of what I have right now:
I take a LONG array from a customer (cant make it smaller unfortunately) and update the existing values with the new values provided by a customer in the following way:
$i = 0;
foreach($values as $value)
{
$sql = "UPDATE $someTable SET someItem$i = '$value' WHERE username='$username'";
mysql_query($sql, $con);
$i+=1;
}
Its easy to see from the above example that if the array of values is long, than I execute a lot of SQL statements.
Should I instead do something like:
$i = 0;
$j = count($values);
$sql = "UPDATE $someTable SET ";
foreach($values as $value)
{
if($i < $j) //append values to the sql string up to the last item
{
$sql .= "someItem$i = '$value', ";
}
$i+=1;
}
$sql .= "someItem$i = '$value' WHERE username='$username'"; //add the last item and finish the statement
mysql_query($sql, $con); //execute query once
OR which way should it be done / should I bother making these changes? (there a lot of the type and they all have 100+ items)
Thanks in advance.
The only way you'll get a definitive answer is to run both of these methods and profile it to see how long they take. With that said, I'm confident that running one UPDATE statement with a hundred name value pairs will be faster than running 100 UPDATE statements.
Don't run 100 seperate UPDATE statements!
Use a MySQL wrapper class which, when given an array of name => value pairs will return an SQL UPDATE statement. Its really simple. I'm just looking for the one we use now...
We use something like this (registration required) but adapted a little more to suit our needs. Really basic but very very handy.
For instance, the Update method is just this
/**
* Generate SQL Update Query
* #param string $table Target table name
* #param array $data SQL Data (ColumnName => ColumnValue)
* #param string $cond SQL Condition
* #return string
**/
function update($table,$data,$cond='')
{
$sql = "UPDATE $table SET ";
if (is_string($data)) {
$sql .= $data;
} else {
foreach ($data as $k => $v) {
$sql .= "`" . $k . "`" . " = " . SQL::quote($v) . ",";
}
$sql = SQL::trim($sql , ',');
}
if ($cond != '') $sql .= " WHERE $cond";
$sql .= ";";
return $sql;
}
If you can't change the code, make sure it is enclosed in transaction (if the storage engine is InnoDB) so no non-unique indexes will be updated before commiting transaction (this will speed up the write) and the new row won't be flushed to disk.
If this is MyISAM table, use UPDATE LOW_PRIORTY or lock table before the loop and unlock after read.
Of course, I'm sure you have index on the username column, but just to mention it - you need such index.