I am very new to PHP and only have a class from a year ago where I touched MySQL.
I am trying to add a check in some existing code to query a db table for a value, and if that value is = to 1, change a variable in the code. Seems simple enough but it's not working out. I am getting 0 results from my query, even though the query works as expected in Sequel Pro.
I am modeling my syntax after the existing query even though I don't fully understand the prepare and execute functions, because I don't want to create a new db connection to make it easier on myself. I'll give the snippets that matter, I think.
My question: Why is this not returning results, when it works fine in the database directly? The query should return 2 results, in the form of Integers, which I want to compare to another integer, $friend_uid.
$dbObj = new sdb("mysql:host=".DB_HOST.";dbname=".DB_NAME, DB_USERNAME, DB_PASSWORD);
$dbObj->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$newStatus = 'REQUEST_PENDING';
$botquery = "SELECT `KAP_USER_MAIN.UID` FROM `KAP_USER_MAIN` WHERE `KAP_USER_MAIN.IS_BOT` = 1";
$botstatement = $dbObj->prepare($botquery, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$botstatement->execute();
$posts[]= "sql error " . mysql_error();
if(!$botstatement){
$posts[] = "failed bot query: " . mysql_error();
}
$num_rows = mysql_num_rows($botstatement);
if ($num_rows == false) {
$num_rows = 0;
}
$posts[] = "$num_rows rows";
while($row = mysql_fetch_array($botstatement)) {
if($row[0]['UID'] == $friend_uid){
$newStatus = 'FRIENDS';
}
}
$statement->execute(array(':uid'=>$uid,':friend_uid'=>$friend_uid,':status'=>$newStatus));
Here is an example of a query from the existing code that works just fine, which I am modeling after:
$query = "SELECT kits.TOTAL_UNIT,kum.ENERGY,kum.NAME,kum.LEVEL FROM KAP_USER_MAIN kum,KNP_INVENTORY_TRANSACTION_SUMMARY kits WHERE kits.UID = :uid AND kits.INV_ID = '10004' and kum.UID = :uid";
$statement = $dbObj->prepare($query, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$statement->execute(array(':uid'=>$uid));
$res = $statement->fetchAll(PDO::FETCH_ASSOC);
$sender_name = $res[0]['NAME'];
DON'T MIX PDO AND MYSQL FUNCTIONS
Looking more closely at the code, it looks like you are mixing PDO and mysql functions.
That's not valid. Don't mix calls to the two separate interface libraries.
The mysql_fetch_array function cannot be used to fetch from a PDO statement. Use the appropriate PDO fetch functions/methods.
There are three separate and distinct MySQL interface libraries in PHP.
There's the older (and now deprecated) mysql interface, all the functions from that interface start with mysql_.
There's the improved mysqli interface. The procedural style functions all begin with mysqli_.
And thirdly, there's the more database independent PDO interface.
Do not mix calls of these three separate interface libraries, because mixing calls won't work.
It looks like you're getting a connection with PDO, preparing a statement with PDO... but you are calling the msyql_error, mysql_num_rows and mysql_fetch_array functions. Replace those calls to the mysql_ functions with the appropriate PDO functions.
DOT CHARACTER IN COLUMN NAME?
It's very strange to include a dot character in a column name. (It's not invalid to do that, but something like that wouldn't fly in our shop.)
SELECT `KAP_USER_MAIN.UID` FROM `KAP_USER_MAIN` WHERE `KAP_USER_MAIN.IS_BOT` = 1
^ ^
But I'm suspicious that the column names are actually UID and IS_BOT, and that what you intended was:
SELECT `KAP_USER_MAIN`.`UID` FROM `KAP_USER_MAIN` WHERE `KAP_USER_MAIN`.`IS_BOT` = 1
^ ^ ^ ^
Each identifier (the column name and the table name) can be escaped separately. The dot character between the table name and the column name should not be escaped, because that's part of the SQL text, not part of the identifier.
We typically use a short table alias in our queries, so a typical query would look like this:
SELECT m.UID FROM `KAP_USER_MAIN` m WHERE m.IS_BOT` = 1
Or, for a query equivalent to the original query (with the dot character as part of the column name), like this:
SELECT m.`KAP_USER_MAIN.UID` FROM `KAP_USER_MAIN` m WHERE m.`KAP_USER_MAIN.IS_BOT` = 1
(That's not invalid, to include a dot character in a column name, but it is an unusual pattern, one that we don't see very often. I think that's because that pattern leads to more potential problems than whatever problem it was intended to solve.)
If the query works the way it is in your code, then that dot character must be part of the column name.
Related
EDIT: PDO appears to have an issue with the French character in the column name Unité. Is there a solution to this, or do I need to rename the column in the database?
SELECT statements work with PDO, but the INSERT statement does not.
Connection string:
$dbCon = new PDO("mysql:host=".$host.";dbname=".$dbName.";charset=utf8", $username, $password);
Working SELECT statement:
$sql = 'SELECT * FROM availability WHERE event_id=:postID';
$stmt = $dbCon->prepare($sql);
$stmt->execute(array(':postID'=>$postID));
$result = $stmt->fetchAll();
Non-functioning INSERT statement:
$sql = 'INSERT INTO `availability` (`event_id`,`Nom`,`Address`,`Address2`,`Tel1`,`Tel2`,`Tel3`,`Classement`,`Soleil`,`Unité`,`Dispo`,`Ville`,`Type`,`URL`,`Jour1`,`Jour2`,`Jour3`,`Jour4`,`Jour5`,`Jour6`,`Jour7`,`Jour8`,`Jour9`,`Jour10`,`Jour11`,`Jour12`,`Jour13`,`Jour14`,`Jour15`,`visible`) (SELECT :postID,`Nom`,`Address`,`Address2`,`Tel1`,`Tel2`,`Tel3`,`Classement`,`Soleil`,`Unité`,`Dispo`,`Ville`,`Type`,`URL`,`Jour1`,`Jour2`,`Jour3`,`Jour4`,`Jour5`,`Jour6`,`Jour7`,`Jour8`,`Jour9`,`Jour10`,`Jour11`,`Jour12`,`Jour13`,`Jour14`,`Jour15`,`visible` FROM `default_hotels`)';
$stmt = $dbCon->prepare($sql);
$stmt->execute(array(':postID'=>$postID));
$result = $stmt->fetchAll();
Another working SELECT statement:
$sql = 'SELECT post_title FROM wp_posts WHERE id=:postID';
$stmt = $dbCon->prepare($sql);
$stmt->execute(array(':postID'=>$postID));
$records = $stmt->fetchAll();
All of the statements appear in this order in my script. The variables are re-used and not cleared.
The SQL INSERT statement that I provided works when submitted through phpmyadmin but not PDO.
The PDO charset parameter in the connection string started being supported in PHP 5.3.6. Before that it did nothing. So the problem is that the connection to your database is not actually run in utf8, but likely latin1. Hence the encoding of the column name in PHP and in MySQL doesn't match, hence MySQL misunderstands the column name, hence can't find the column you ask for.
See https://stackoverflow.com/a/279279/476 for alternative ways to specify the connection encoding, upgrade your version of PHP, or use ASCII-only for column names (that's a good idea anyway, specifically because it makes compatibility issues like this much less of a problem).
I have a MySQL Database Table containing products and prices.
Though an html form I got the product name in a certain php file.
For the operation in this file I want to do I also need the corresponding price.
To me, the following looks clear enough to do it:
$price = mysql_query("SELECT price FROM products WHERE product = '$product'");
However, its echo returns:
Resource id #5
instead a value like like:
59.95
There seem to be other options like
mysqli_fetch_assoc
mysqli_fetch_array
But I can't get them to output anything meaningful and I don't know which one to use.
Thanks in advance.
You will need to fetch data from your database
$price = mysql_query("SELECT price FROM products WHERE product = '$product'");
$result = mysql_fetch_array($price);
Now you can print it with
echo $result['price'];
As side note I would advise you to switch to either PDO or mysqli since mysql_* api are deprecated and soon will be no longer mantained
If you read the manual at PHP.net (link), it will show you exactly what to do.
In short, you perform the query using mysql_query (as you did), which returns a Result-Resource. To actually get the results, you need to perform either mysql_fetch_array, mysql_fetch_assoc or mysql_fetch_object on the result resource. Like so:
$res = mysql_query("SELECT something FROM somewhere"); // perform the query on the server
$result = mysql_fetch_array($res); // retrieve the result from the server and put it into the variable $result
echo $result['something']; // will print out the result you retrieved
Please be aware though that you should not use the mysql extension anymore; it has been officially deprecated. Instead you should use either PDO or MySQLi.
So a better way to perform the same process, but using for example the MySQLi extension would be:
$db = new mysqli($host, $username, $password, $database_name); // connect to the DB
$query = $db->prepare("SELECT price FROM items WHERE itemId=?"); // prepate a query
$query->bind_param('i', $productId); // binding parameters via a safer way than via direct insertion into the query. 'i' tells mysql that it should expect an integer.
$query->execute(); // actually perform the query
$result = $query->get_result(); // retrieve the result so it can be used inside PHP
$r = $result->fetch_array(MYSQLI_ASSOC); // bind the data from the first result row to $r
echo $r['price']; // will return the price
The reason this is better is because it uses Prepared Statements. This is a safer way because it makes SQL injection attacks impossible. Imagine someone being a malicious user and providing $itemId = "0; DROP TABLE items;". Using your original approach, this would cause your entire table to be deleted! Using the prepared queries in MySQLi, it will return an error stating that $itemId is not an integer and as such will not destroy your script.
I notice that these two ways of structuring a query with PHP PDO, both return the same data.
//prepare with $dbh->prepare
$w_ft = "36";
$sth = $dbh->prepare("SELECT * FROM main_products_common_dimensions WHERE w_ft = :w_ft");
$sth->bindParam(':w_ft', $theId, PDO::PARAM_INT);
$sth->execute();
$result = $sth->fetchAll(); //PHP array of data
//prepare with pg_prepare()
$result = pg_prepare($con, "my_query", 'SELECT * FROM main_products_common_dimensions WHERE w_ft = $1');
$result = pg_execute($con, "my_query", array("48")); //A query result resource on success or FALSE on failure.
while ($row = pg_fetch_assoc($result)){
echo $row['w_ft'] . "<BR>";
}
I read at http://php.net/manual/en/function.pg-execute.php that the second way returns "A query result resource on success or FALSE on failure." So I tried to iterate through it with pg_fetch_assoc(). It works, but is that not deprecated along with the rest of the pg_sql functions? Should I be using something in the PDO to look at the results of the query?
For this reason, I'm inclined to use the first method while using PDO. Is this the norm?
My question is how to submit multiple values to either method. Neither method works when I try to submit an array to the prepared statement
$w_ft = array("48", "36");
$result = pg_execute($con, "my_query", array("48", "36"));
I thought that I was able to submit multiple values to the query in this way. How can I do this?
Thank you
Looks like you're taking execute array wrong.
It takes values not for the consequent executions but for one execution only.
So, number of values should be equal to number of placeholders.
So it goes
$sql = 'SELECT * FROM table WHERE w_ft = $1 OR w_ft = $2 OR w_ft = $3'
for your array("48", "36", "12")
I am not a PG user though, so, I can confuse some syntax.
PDO is an agnostic database access API for PHP. This means, whatever your database is, you will be able to use the same objects and methods to query it and fetch results. PDO was the first step toward database abstraction layers in PHP.
The pg_* API is, afaik, not going to be deprecated and is dedicated to Postgres. It also contains functions that were not implemented in PDO (like binary escaping or event notifier functions amongst others).
The choice between PDO and dedicated library is often hidden by the choice of the Model Manager you use in your controllers code. Either it can be Object Relational Mapper over an abstraction layer like ORMs (Doctrine, Propel and many others) or it can be an Object Model Manager (OMM) dedicated to Postgresql like Pomm.
In both ways, you do not need to prepare statements, manage the columns types nor results cursors (btw, using PDO::fetch_all() will dump all results in memory), the database layer handles that for you. Your above query would be written like:
// Using Pomm
// SELECT * FROM main_products_common_dimensions WHERE w_ft = ?
// Returns a MainProductsCommonDimensions instance
$object = $connection
->getMapFor('\Database\Schema\MainProductsCommonDimensions')
->findWhere('w_ft = ?', array(48))
->current(); // fetch only the first result.
Note that both ORMs and OMMs do propose handy query builder:
$where = \Pomm\Query\Where::createWhere('w_ft = ?', array(48))
->orWhere('w_ft = ?', array(12))
->orWhere('w_ft = ?', array(66));
// which is pretty much the same as
$where = \Pomm\Query\Where::createIn('w_ft', array(48, 12, 66));
// SELECT * FROM main_products_common_dimensions WHERE w_ft IN (?, ?, ?);
$collection = $connection
->getMapFor('\Database\Schema\MainProductsCommonDimensions')
->findWhere($where); // Return an Iterable cursor over results
// display 48, 12 and 66 fetching one result at the time in memory:
foreach($collection as $object)
{
printf("W_FT = '%d'.\n", $object['w_ft']);
}
Using those layers above PDO offers numerous advantages, the main one is to focus more on what you want instead of dealing with weird APIs (yes PDO is weird as almost any lib in PHP). Furthermore, since PDO is just an access layer it will return results as arrays of strings (binary or not). Boolean in Postgres are 't' and 'f' and thus will need to be converted to PHP proper Boolean (sic) type to be used. ORMs and OMMs do propose such translation mechanisms and Pomm as being dedicated to Postgres also support Arrays, HStore, LTree, geometric and composite types conversions and more.
I'm converting all my sites code from using mysql_* functions to PDO. The PHP documentation on PDO is not clear for my needs. It gives you the functions to use, but does not go into detail to explain them in different scenarios.
Basically, I have a mysql fulltext search:
$sql = "SELECT ... FROM search_table WHERE MATCH(some_field) AGAINST ('{$searchFor}*' IN BOOLEAN MODE)";
The actual statements much longer, but this is what it basically does.
My question is, how would I incorporate this into PDO?
I know you're not meant to use quotes around the place-marker, so do you leave them out in the AGAINST() function? Do I include them? If I leave them out, what happens to the wildcard symbol etc?
$sql = $this->db->prepare("SELECT ... FROM search_table WHERE MATCH(some_field) AGAINST(:searchText IN BOOLEAN MODE");
$sql->bindValue(':searchText', $searchFor . '*');
This is unfortunately a weird exception to the use of query parameters (edit: but apparently not in the most recent point-release of each MySQL branch, see below).
The pattern in AGAINST() must be a constant string, not a query parameter. Unlike other constant strings in SQL queries, you cannot use a query parameter here, simply because of a limitation in MySQL.
To interpolate search patterns into queries safely, use the PDO::quote() function. Note that PDO's quote() function already adds the quote delimiters (unlike mysql_real_escape_string()).
$quoted_search_text = $this->db->quote('+word +word');
$sql = $this->db->prepare("SELECT ... FROM search_table
WHERE MATCH(some_field) AGAINST($quoted_search_text IN BOOLEAN MODE");
Re comment from #YourCommonSense:
You're right, I just tested this on MySQL 5.5.31, 5.1.68, and 5.0.96 (MySQL Sandbox is a wonderful tool), and it seems that these versions do accept query parameters in the AGAINST() clause of a dynamic SQL query.
I still have a recollection of a conflict existing in the past. Maybe it has been corrected in the most recent point-release of each branch. For example, I find these related bugs:
Using a stored procedure parameter in the AGAINST() clause always returns the same result: http://bugs.mysql.com/bug.php?id=3734
Crash or strange results with prepared statement, MATCH and FULLTEXT: http://bugs.mysql.com/bug.php?id=14496
$sql = "SELECT * FROM tablename WHERE MATCH (fieldname) AGAINST (:searchstr IN BOOLEAN MODE) LIMIT {$per_page} OFFSET {$pg_offset}";
try {
$database->prepare($sql);
$database->bindParam(':searchstr', $search);
$database->execute();
$result_array = $database->fetch_array($sql);
} catch (Exception $e) {
echo $e->getMessage();
}
my goal here is to be able to get a variable (with php) and use it in a prepared statement (with mysqli), and then fetch_assoc. For some reason this code will not work (no errors). I've rtm and I haven't found anything combining fetch_assoc with prepared statements, so I'm not sure if it's even possible. Any help to get this working is appreciated, here's my code currently.
$where = $_GET['section'];
$mysqli = mysqli_connect("localhost", "root", "","test");
if($stmt = mysqli_prepare($mysqli,"SELECT title, img, active, price FROM ? ORDER by ID limit 5 ")){
mysqli_stmt_bind_param($stmt, 's', $where);
mysqli_stmt_execute($mysqli);
mysqli_stmt_fetch($mysqli);
while($row = mysqli_fetch_assoc($stmt)){
if($row['active']=="yes"){
echo 'the rest of my stuff goes here';
From the PHP website page for mysqli->prepare (with emphasis added to the most relevant part):
Note:
The markers are legal only in certain places in SQL statements. For
example, they are allowed in the VALUES() list of an INSERT statement
(to specify column values for a row), or in a comparison with a column
in a WHERE clause to specify a comparison value.
However, they are not allowed for identifiers (such as table or column
names), in the select list that names the columns to be returned by a
SELECT statement), or to specify both operands of a binary operator
such as the = equal sign. The latter restriction is necessary because
it would be impossible to determine the parameter type. In general,
parameters are legal only in Data Manipulation Language (DML)
statements, and not in Data Definition Language (DDL) statements.
Assuming you can get past that problem, your use of mysqli is a little confused. You correctly bind your parameters and execute, but you've mixed up two different ways of getting at your results. Either
Use mysqli_stmt_get_result to fetch the result set and then use mysqli_fetch_assoc on that, or
Bind your results with mysqli_stmt_bind_result, and then use mysqli_stmt_fetch to fetch the next set of results into your bound variables. (Usually you'd iterate over the results using something like while(mysqli_stmt_fetch($stmt)){ //do stuff here }
Another way style, we can write it below:
$mysqli=new mysqli("host","user","pass","db");
$stmt = $mysqli->prepare($query);
$stmt->bind_param('s', $variable);
$stmt->execute();
$result = $stmt->get_result();
while($row = $result->fetch_assoc()){
....
}