PHP - (PDO) Execute with binding variables - php

I just started playing around with PDO and I am trying to create a function that will display all the data for a given table name. After reading a few posts here I found a solution that I can get working (shown below with a hard-coded select statement). However, I can't get my execute statements to work when I bind my field names (I get an exception similar to: Undefined index: person_id). I should mention my class extends PDO:
/*********************************************************************
*Function showTable
*Purpose Display all information for a given table.
*Params $sTable -> Table name
********************************************************************/
public function showTable($sTable)
{
$result;
try
{
if(isset($sTable))
{
//create a result in a table format
$result = "<table>";
//$stmt = $this->prepare('DESCRIBE :sTable');
$stmt = $this->prepare('DESCRIBE ' . $sTable);
//$stmt->bindParam(':sTable', $sTable);
$stmt->execute();
//array version of the column names
$aCols = $stmt->fetchAll(PDO::FETCH_COLUMN);
//string version of the column names
$sCols = implode (", ", $aCols);
//$stmt = $this->prepare('SELECT :fields FROM :sTable');
//$stmt = $this->prepare('SELECT :fields FROM person');
$stmt = $this->prepare('SELECT person_id, first_name, last_name FROM person');
//$stmt->execute(array(':fields'=>$sCols, 'stable'=>$sTable));
//$stmt->execute(array(':fields'=>$sCols));
$stmt->execute();
while($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
var_dump($row);
$result = $result . "<tr>";
foreach($aCols as $col)
{
//var_dump($row);
$result = $result . " <td>" . $row[$col]. "</td>";
}
$result = $result . "</tr>";
}
$result = $result . "</table>";
}
return $result;
}
catch(PDOException $e)
{
if($this->bDebug)
{
echo $e->getMessage();
}
}
}
Like I said the hard coded select string works but when i comment out the hard coded and uncomment the execute with a bind it throws exceptions.

You cannot insert identifiers or keywords this way.
PDOStatement::execute() will put the value in escaped form inside single quotes. Your query would look like:
SELECT 'col1, col2' FROM person
What is invalid MySQL syntax.
A valid example:
$stmt = $this->prepare('SELECT col FROM person WHERE name = :name');
$stmt->execute(array(':name' => $name));
It works, because it's a value you insert here; and not an keyword or identifier.

Related

Table will not display

I am having no success linking the upper part of the code containing the prepared statements to the table display. After eradicating several syntax errors, all I am getting now is a single row of numbers starting at 0 and running through to 2713 instead of the database results. The code below is exactly as I am using it except that for this purpose I have removed my personal details from the '$con'
<?php
$con= new PDO('mysql:host=;', "",
"");
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
if (isset($_POST['submit-keyword'])) {
$keyword = '%'.$keyword. '%';
$stmt = $con->prepare("SELECT * FROM Bath_Wells_NBR WHERE Founder LIKE :keyword ORDER BY DATE");
$stmt->bindParam(':keyword',$keyword,PDO::PARAM_STR);
$stmt->execute();
//use fetchAll to get full array of results, or an empty array
$result=$stmt->fetchAll();
if(count($result)>0) {
print "<table>";
//return only the first row (we only need field names)
$row = $result;
print " <tr>";
foreach ($row as $field => $value){
print " <th>$field</th>";
} // end foreach
print " </tr>";
//second query gets the data
$data = $con->prepare("SELECT * FROM Bath_Wells_NBR WHERE Founder LIKE :keyword ORDER BY DATE");
$data->setFetchMode(PDO::FETCH_ASSOC);
foreach($data as $row){
print " <tr>";
foreach ($row as $name=>$value){
print " <td>$value</td>";
} // end field loop
print " </tr>";
} // end record loop
print "</table>";
}
}
?>
\\
your second query not get bind param properly
See Doc
$data = $con->prepare("SELECT * FROM Bath_Wells_NBR WHERE Founder LIKE :keyword ORDER BY DATE");
$data->bindParam(':keyword', $keyword, PDO::PARAM_STR);
$data->setFetchMode(PDO::FETCH_ASSOC);
$rows = $data->execute();

SQL in php, make partial search using LIKE

I am trying to make SQL in php to return all the entries that matches a keyword that is entered by the user (from search bar).
I want to return all the entries that their name "partial" matches with the keyword.
I want at least to match the keyword, if an entry name in database before has space and after maybe another letter/space.
For example I have three entries with names "Milk", "Semi skimmed Milk" and "Full Milk 2". If the keyword is "Milk" or "milk" or "MiLK", I want to get all these three entries.
The only case I am thinking it might be the problem is case sensitive.
I tried with a keyword that exists exactly in database, but my app (on android) stops .
Based on user3783243 answer.
PHP FILE
<?php
$servername = "";
$username = "";
$password = "";
$dbname = "";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT name FROM items WHERE name LIKE CONCAT ('%', ?, '%')";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $keyword);
$res = $stmt->get_result();
while($row = $res->fetch_assoc()) {
echo $row["name"] . ",";
}
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
echo $row["name"] . ",";
}
} else {
echo "0";
}
$conn->close();
?>
Your query should be:
$sql = "SELECT * FROM items WHERE name LIKE CONCAT ('%', ?, '%')";
and then $keyword should be bound with whatever syntax the driver you are using supports.
As is your query would have been:
SELECT * FROM items WHERE name LIKE CONCAT ('%', Milk, '%')
and you wanted Milk to be a string so it needed to be quoted. As is mysql would have thought that was a column.
Alternatively you could do:
$keyword = '%' . $_POST['keyword'] . '%';
$sql = "SELECT * FROM items WHERE name LIKE CONCAT ?";
that is the same and still requires the binding though.
The binding also takes away the SQL injection. See How can I prevent SQL injection in PHP? and/or https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet#Defense_Option_1:_Prepared_Statements_.28with_Parameterized_Queries.29
Per update.. replace:
$keyword =$_POST['keyword'];
$sql = "SELECT * FROM items WHERE name LIKE '%$keyword%)";
$result = $conn->query($sql);
with:
$sql = "SELECT name FROM items WHERE name LIKE CONCAT ('%', ?, '%')";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $keyword);
$stmt->execute();
$res = $stmt->get_result();
if(empty($conn->errno) && !empty($res)) {
while($row = $res->fetch_assoc()) {
echo $row["name"] . ",";
}
} else {
echo '0';
//print_r($conn->errno);
}
$conn->close();
...
also remove
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
echo $row["name"] . ",";
}
} else {
echo "0";
}
$conn->close();
In this case you can convert the input in search bar to either upper or lower case by default then apply query in db like
For Upper case:
$keyword =strtoupper($_POST['keyword']);
$sql = "SELECT * FROM items WHERE upper(name) LIKE '%$keyword%)";
Or for lower case:
$keyword =strtolower($_POST['keyword']);
$sql = "SELECT * FROM items WHERE lower(name) LIKE '%$keyword%)";

SQL Count Not Working From Inside of PHP Code

I have the weirdest issue going on. COUNT() is not working from inside my PHP code, but it is working in the SQL input space in the PHPMyAdmin database. For example if I use the following query:
SELECT COUNT(*) FROM posts WHERE category = "coding"
It will return the correct results from the SQL input in the PHPmyadmin part, but from the PHP code it will always return 1. Here is the code I am using for the PHP:
function numberofposts($category, $connection) {
$query = "SELECT COUNT(*) FROM posts WHERE category = :category";
$params = array(':category' => $category);
try{
$stmt = $connection->prepare($query);
$result = $stmt->execute($params);
}
catch(PDOException $ex){
echo ("Failed to run query: " . $ex->getMessage());
}
return $result;
}
echo "Number of Posts: " . numberofposts("art", $connection);
What it is doing is in the first code at the top it will return the correct results, but in the PHP code it is always returning 1. Is there a problem with me PHP? Please just post if you do not understand what I am asking, or if you would like more information.
You are doing a select and you execute the statement, but you are not fetching the row with the results.
You probably want something like:
function numberofposts($category, $connection) {
$query = "SELECT COUNT(*) as cnt FROM posts WHERE category = :category";
^^^ for easy access
$params = array(':category' => $category);
try{
$stmt = $connection->prepare($query);
$stmt->execute($params);
$row = $stmt->fetch();
}
catch(PDOException $ex){
echo ("Failed to run query: " . $ex->getMessage());
}
return $row['cnt'];
// if you don't alias the column you can do:
// return $row[0];
}

Searching multiple tables

I'm trying to create a search for my site and I'm having lots of trouble doing it. In my movies database I have two tables: movieinfo and movie_genres. Under movieinfo, there is Movie_Name, actor1, actor2, actor3, actor4. Under the movie_genres table, there is Genre_Id. (There are more columns in each of the tables, but I only want to search those columns.)
My current code is:
<?php
if ($_GET) {
$search = $_GET['search'];
$connect = mysql_connect("localhost","root","spencer");
if($connect) {
mysql_select_db("movies", $connect);
$query = "SELECT Movie_Name, actor1, actor1, actor1, actor1, Genre_Id FROM movieinfo, movie_genres WHERE * LIKE '%:search%' OR actor1 LIKE '%:search%' OR actor2 LIKE '%:search%' OR actor3 LIKE '%:search%' OR actor4 LIKE '%:search%' OR Genre_Id = ? ";
$results = mysql_query($query);
while($row = mysql_fetch_array($results)) {
echo $row['Poster'] . "<br/>" . $row['Movie_Name'];
}
} else {
die(mysql_error());
}
}
?>
Everything in movieinfo I'm searching for is VARCHAR, and movie_genres is an INT (incase that makes much of a difference). I think I'm close to what the code should be, but I don't know.
As of right now, I get the following error while trying to search:
Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in C:\xampp\htdocs\movies\get_search.php on line 12
New code:
<?php
// Connection data (server_address, database, name, poassword)
$hostdb = 'localhost';
$namedb = 'movies';
$userdb = 'root';
$passdb = 'spencer';
try {
// Connect and create the PDO object
$conn = new PDO("mysql:host=$hostdb; dbname=$namedb", $userdb, $passdb);
$conn->exec("SET CHARACTER SET utf8"); // Sets encoding UTF-8
}
catch (PDOException $e) {
$v_errormsg = $e->getMessage();
$error_str = <<<END_HTML
<h2> Error connecting to database: Message: $v_errormsg <h2>
END_HTML;
echo $error_str;
die;
}
$sql = <<<END_SQL
SELECT Movie_Name FROM movieinfo WHERE Movie_Name LIKE '%":search"%' ";
END_SQL;
try {
$sth = $conn->prepare($sql);
$sth->execute();
}
catch (PDOException $e) {
$v_errormsg = $e->getMessage();
$error_str = <<<END_HTML
<h2> Error selecting data: Message: $v_errormsg <h2>
END_HTML;
echo $error_str;
die;
}
$num_rows = 0;
while ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
$Movie_Name = $row['Movie_Name'];
}
echo $row['Movie_Name'];
?>
You can't use part of a string as a placeholder; placeholders can only take the place of a single entire value. Use LIKE :search and bind '%' . $search . '%' as the value.
You aren't binding any values. :)
You are getting an invalid query because you're using bind paramter syntax from PDO
start with something very simple like
$search= mysql_escape_string($search);
$query = "SELECT Movie_Name FROM movie_info WHERE name LIKE '%".$search."%';
Once you get that working, move on to the more complex logic...
Better yet, use PDO to do the query:
<?php
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->bindValue(':id', $id, PDO::PARAM_INT);
$stmt->bindValue(':name', $name, PDO::PARAM_STR);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
example from: http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers

How to insert where condition in mysql query

I will pass the query into this function query("SELECT * FROM table_name");
And the function is
public function query($sql) {
$resource = mysql_query($sql, $this->link_web);
if ($resource) {
if (is_resource($resource)) {
$i = 0;
$data = array();
while ($result = mysql_fetch_assoc($resource)) {
$data[$i] = $result;
$i++;
}
mysql_free_result($resource);
$query = new stdClass();
$query->row = isset($data[0]) ? $data[0] : array();
$query->rows = $data;
$query->num_rows = $i;
unset($data);
return $query;
} else {
return true;
}
} else {
trigger_error('Error: ' . mysql_error($this->link_web) . '<br />Error No: ' . mysql_errno($this->link_web) . '<br />' . $sql);
exit();
}
}
I want to add tenent_id = '1' in SELECT query also for INSERT query. Likewise I need to do it for UPDATE.
I want to bring the query like this
SELECT * FROM table_name WHERE tenent_id = 1 and user_id = 1
INSERT INTO table_name('tenant_id, user_id') VALUE('1','1')
UPDATE table_name SET user_id = 1 WHERE tenant_id = '1'
Can anyone give me the idea about how to insert tenant_id in select, insert and update
Thanks in advance
It's better practice to use the correct mysql functions rather than just a query function.
For example, if you want to cycle through many items in a database, you can use a while loop:
$query = mysql_query("SELECT * FROM table WHERE type='2'");
while($row = mysql_fetch_array($query)){
echo $line['id'];
}
This would echo all the IDs in the database that have the type 2.
The same principle is when you have an object, using mysql functions, you can specify how you want the data to return. Above I returned it in an array. Here I am going to return a single row as an object:
$query = mysql_query("SELECT * FROM table WHERE id='1'");
$object = mysql_fetch_object($query);
echo $object->id;
echo $object->type;
echo $object->*ANY COLUMN*;
This would return as:
1.
2.
Whatever the value for that column is.
To insert your data, you don't need to do "query()". You can simple use mysql_query($sql).
It will make life much easier further down the road.
Also, its best to run one query in a function, that way you can handle the data properly.
mysql_query("INSERT...");
mysql_query("UPDATE...");
mysql_query("SELECT...");
Hope this helps.
The simple answer is: just add the condition to your query. Call query("SELECT * FROM table_name WHERE tenant_id = 1 and user_id = 1").
If you're concerned about escaping the parameters you pass to the SQL query (which you should be!), you can either do it yourself manually, e.g.
$query = sprintf("SELECT * FROM table_name WHERE tenant_id = %d", intval($tenant_id));
query($query);
Or better use prepared statement offered by mysqli extension (mysql_query is deprecated anyway):
$stmt = $mysqli->prepare("SELECT * FROM table_name WHERE tenant_id = ?");
$stmt->bind_param("i", $tenant_id);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_array(MYSQLI_ASSOC)) {
// ...
}
If I still haven't answered your question, you can use a library to handle your queries, such as dibi:
$result = dibi::query('SELECT * FROM [table_name] WHERE [tenant_id] = %i', $id);
$rows = $result->fetchAll(); // all rows
The last option is what I would use, you don't need to write your own query-handling functions and get query parameter binding for free. In your case, you may utilize building the query gradually, so that the WHERE condition is not part of your basic query:
$query[] = 'SELECT * FROM table_name';
if ($tenant_id){
array_push($query, 'WHERE tenant_id=%d', $tenant_id);
}
$result = dibi::query($query);

Categories