Prepared statement LIKE wildcard - php

I've made a function that accepts a search column, search term and an id number, and am trying to construct a prepared statement and fetch results, and return in json.
Here is what I have:
function searchBooks($searchColumn, $searchTerm, $teacherid) {
$books = array();
$link = connect_db();
$sql = "SELECT * FROM book WHERE teacher_id = ? AND ? LIKE ?";
$searchTerm = "%{$searchTerm}%";
$stmt = $link->stmt_init();
$stmt->prepare($sql);
$stmt->bind_param('iss', $teacherid, $searchColumn, $searchTerm);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_array(MYSQLI_BOTH)) {
$book = new Book();
$book->id = $row['id'];
$book->title = $row['title'];
$book->author = $row['author'];
$book->ar_quiz = $row['ar_quiz'];
$book->ar_quiz_pts = $row['ar_quiz_pts'];
$book->book_level = $row['book_level'];
$book->type = $row['type'];
$book->teacher_id = $row['teacher_id'];
array_push($books, $book);
}
mysqli_stmt_close($stmt);
return json_encode($books);
}
I'm using a test page that passes values that I know should return results (using 'the' as a wildcard and 'title' for search column):
echo searchBooks('title', 'the', 1);
...but I am not getting any results at all... [] output on the test page.
Assume connect_db() retrieves a connection. Assume I'm doing all my error checking and everything in my controller level, and might add stuff like that later. Just trying to get results right now. Thanks in advance for anything you can point out.

searchcolumn cannot be a bind variable. You can't bind table/column names
$sql = sprintf("SELECT * FROM `book` WHERE teacher_id = ? AND `%s` LIKE ?", $searchColumn);
$searchTerm = "%{$searchTerm}%";
$stmt = $link->stmt_init();
$stmt->prepare($sql);
$stmt->bind_param('is', $teacherid, $searchTerm);
It would also be a good idea to whitelist $searchColumn, validating that it really is a column in your book table before executing this
EDIT
And why bother using fetch_array(MYSQLI_BOTH) when you're only using associative values from the array? Using fetch_assoc() would be better, or you could be even cleverer, and use fetch_object(), and then you wouldn't need to populate your Book object property by property
Consider:
while ($book = $result->fetch_object('Book')) {
array_push($books, $book);
}

Related

Display the result of an SQL search in multiple places

I am trying to display the results of an SQL search in multiple places, but I can only seem to get it to print once (the first time it is called).
Here is what I have:
$stmt = $connection->prepare("SELECT DISTINCT genre FROM movies");
$stmt->execute();
$results = $stmt->get_result();
while ($row = mysqli_fetch_array($results)){
print ($row['genre'] . "<br>");
}
It makes sense to me that doing this "uses up" all of the results, so if I were to call the while again, there would be nothing, and therefore it would print nothing.
So, is it possible to copy the results to another variable for later use? I have tried:
$results2 = $results;
$results2 = array();
$results2 = $results;
$results2 = new stdClass();
$results2 = $results;
But I keep getting the same result... and empty array after the first call.
Do I just need to call the SQL query again? It seems like there's gotta be a better way.
As mentioned in the comments, instead of fetching them each time, store the results and then simply loop over them each time you need to use them...
$stmt = $connection->prepare("SELECT DISTINCT genre FROM movies");
$stmt->execute();
$results = $stmt->get_result();
$movies = mysqli_fetch_all($results);
foreach ( $movies as $row){
print ($row['genre'] . "<br>");
}

How to store multiple variables returned from a SELECT in arrays of their own - PDO

I'm rewriting all my old mysql code as PDO code but I can't think of a way to store multiple variables returned from a SELECT in arrays of their own.
I can put ONE set of values in a new array as follows:
$stmt1 = $db->prepare("SELECT P_ID
FROM personal
WHERE personal.firstname=:firstname
AND personal.lastname=:lastname");
// Bind
// Execute
// Fetch
// Store
if ($row)
{
foreach ($row as $key)
{
$PIDs[] = $key;
}
}
But in this query I want to put firstnames and secondnames in different arrays:
$stmt2 = $db->prepare("SELECT FirstName, LastName
FROM personal");
In mysql I was doing:
while ($row = mysql_fetch_array($result))
{
$firstnames[] = $row[0];
$lastnames[] = $row[1];
}
Can someone please help? Every sample PDO SELECT I can find only handles one returned field.
Assuming you fetch data from your statement $stmt:
$stmt2 = $db->prepare("SELECT FirstName, LastName FROM personal");
$stmt2->execute();
while ($row = $stmt2->fetch(PDO::FETCH_ASSOC))
{
$firstnames[] = $row['FirstName'];
$lastnames[] = $row['LastName'];
}
You want to set the PDO fetch mode so you can reference the 2D array by name and then fetch all of the rows.
$stmt = $dbh->query($sql);
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$result = $stmt->fetchAll();
More information can be found here.
And then you can use array_column, more information can be found here;
$firstNames = array_column($result, 'FirstName');
$lastNames = array_column($result, 'LastName');

how grab field value from a PHP query (PDO)

Super new to PHP here, only using PHP to create my json data and having a hard time to understand the syntax. Here is some partial code:
All I am trying to do is to retrieve the value '2af8ddda-2be4-11e5-9453-b82a72d52c35' and put it in variable #sharepointID:
function selectWithSharepointID($table, $columns, $where){
try{
//Get Sharepoint file ID first
$stmt = $this->db->prepare("SELECT ID FROM table1 ORDER BY DownloadedTimeStamp DESC LIMIT 1");
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
//$data[] = array("ID" => $rows['ID']);
//$sharepointID = $data[0];
//$sharepointID = $rows[0];
$where = array('id'=>$sharepointID);
//$where = array('id'=>'2af8ddda-2be4-11e5-9453-b82a72d52c35'); //this works fine
...
PS: also tried to use print_r and echo but cant see anything in the console.
Thank you
You don't need to fetchAll if you only have one record. Try:
$stmt = $this->db->prepare("SELECT ID FROM table1 ORDER BY DownloadedTimeStamp DESC LIMIT 1");
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$sharepointID = $row['ID'];
If you have multiple records the fetchAll makes sense but then you iterate through that to get each row, and its values.
For a rough example where I'd use fetchAll...
$stmt = $this->db->prepare("SELECT name, userid FROM users");
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach($rows as $row){
echo 'Name: ' . $row['name'] . ' userid :' . $row['id'];
}
This expression returns array of rows:
$stmt->fetchAll(PDO::FETCH_ASSOC);
So, you can get data from row 0 in your case:
$sharepointID = $rows[0]['ID'];

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);

Retrive an array stored in database using PDO

I have an array: productid = [1,2]. Now I want to fetch data from product table by using this part of code:
$sql = 'SELECT name FROM product WHERE id=:id';
$s = $pdo->prepare($sql);
foreach($productid as $id)
{
$s->bindValue(':id', $id);
$s->execute();
}
when I returned the names as follow:
foreach($s as $row)
{
$name[] = array(
'name' => $row['name']
);
}
I just got the product name of second id and didn't get both names.
What's the problem?
I just got the product name of second id and didn't get both names. What's the problem?
You've got to put your $name[] = $row['name']; (yes, that's right notation) code inside of the foreach loop, as well as code that actually fetches the data.
You may also form a IN() statement that should be looks like IN (?,?,?,?) and run it in one query. Something like this (not tested):
$in = trim(str_repeat('?,',count($productid)).",");
$sql = "SELECT name FROM product WHERE id IN ($id)";
$stmt = $db->prepare($sql);
$stmt->execute($productid);
$name = $stmt->fetchAll();

Categories