Good evening everyone!
I need your help again. Please bear with me because I am very new to this. Hoping for your understanding. So, I am having a project on oop and pdo. I am having quite hard time converting this into pdo.. Here is my code..
bookReserve.php
while($row=mysql_fetch_array($sql))
{
$oldstock=$row['quantity'];
}
$newstock = $oldstock-$quantity;
Here's what i've done
while($row = $code->fetchAll())
{
$oldstock=$row['quantity'];
}
$newstock = $oldstock-$quantity;
Is that even correct?
And for the oop part, after this while loop I have a query to execute.
$sql="update books set no_copies = '$newstock' where book_title = '$book_title'";
Here's what I've done trying to convert it into pdo
public function bookreserve2($q)
{
$q = "UPDATE books SET quantity WHERE = $newstock where book_title = '$book_title'";
$stmt = $this->con->prepare($q);
$stmt->execute(array(':newstock'=>$newstock));
$result = $stmt->fetch(PDO::FETCH_ASSOC);
return $result;
}
Again, Is that even the correct converted query?
and how would I call $newstock?
P.S. my oop class and pdo is placed in a separate file. Thought this might help.
Thanks
You are not including your query parameters in your function, and your query has syntax errors (extra WHERE) and you are directly inserting your values not using placeholders.
It should look something like -
public function bookreserve2($newstock,$book_title)
{
$q = "UPDATE books SET quantity = :newstock WHERE book_title = :book_title";
$stmt = $this->con->prepare($q);
$stmt->execute(array(':newstock'=>$newstock,':booktitle'=>$book_title));
if($stmt){
return true;
}
else {
return false;
}
}
Related
This question already has answers here:
Single result from database using mysqli
(6 answers)
Closed 2 years ago.
I am trying to write a function that will check for a single value in the db using mysqli without having to place it in an array. What else can I do besides what I am already doing here?
function getval($query){
$mysqli = new mysqli();
$mysqli->connect(HOST, USER, PASS, DB);
$result = $mysqli->query($query);
$value = $mysqli->fetch_array;
$mysqli->close();
return $value;
}
How about
$name = $mysqli->query("SELECT name FROM contacts WHERE id = 5")->fetch_object()->name;
The mysql extension could do this using mysql_result, but mysqli has no equivalent function as of today, afaik. It always returns an array.
If I didn't just create the record, I do it this way:
$getID = mysqli_fetch_assoc(mysqli_query($link, "SELECT userID FROM users WHERE something = 'unique'"));
$userID = $getID['userID'];
Or if I did just create the record and the userID column is AI, I do:
$userID = mysqli_insert_id($link);
Always best to create the connection once at the beginning and close at the end. Here's how I would implement your function.
$mysqli = new mysqli();
$mysqli->connect(HOSTNAME, USERNAME, PASSWORD, DATABASE);
$value_1 = get_value($mysqli,"SELECT ID FROM Table1 LIMIT 1");
$value_2 = get_value($mysqli,"SELECT ID FROM Table2 LIMIT 1");
$mysqli->close();
function get_value($mysqli, $sql) {
$result = $mysqli->query($sql);
$value = $result->fetch_array(MYSQLI_NUM);
return is_array($value) ? $value[0] : "";
}
Here's what I ended up with:
function get_col($sql){
global $db;
if(strpos(strtoupper($sql), 'LIMIT') === false) {
$sql .= " LIMIT 1";
}
$query = mysqli_query($db, $sql);
$row = mysqli_fetch_array($query);
return $row[0];
}
This way, if you forget to include LIMIT 1 in your query (we've all done it), the function will append it.
Example usage:
$first_name = get_col("SELECT `first_name` FROM `people` WHERE `id`='123'");
Even this is an old topic, I don't see here pretty simple way I used to use for such assignment:
list($value) = $mysqli->fetch_array;
you can assign directly more variables, not just one and so you can avoid using arrays completely. See the php function list() for details.
This doesn't completely avoid the array but dispenses with it in one line.
function getval($query) {
$mysqli = new mysqli();
$mysqli->connect(HOST, USER, PASS, DB);
return $mysqli->query($query)->fetch_row()[0];
}
First and foremost,
Such a function should support prepared statements
Otherwise it will be horribly insecure.
Also, such a function should never connect on its own, but accept an existing connection variable as a parameter.
Given all the above, only acceptable way to call such a function would be be like
$name = getVal($mysqli, $query, [$param1, $param2]);
allowing $query to contain only placeholders, while the actual data has to be added separately. Any other variant, including all other answers posted here, should never be used.
function getVal($mysqli, $sql, $values = array())
{
$stm = $mysqli->prepare($sql);
if ($values)
{
$types = str_repeat("s", count($values));
$stm->bind_param($types, ...$values);
}
$stm->execute();
$stm->bind_result($ret);
$stm->fetch();
return $ret;
}
Which is used like this
$name = getVal("SELECT name FROM users WHERE id = ?", [$id]);
and it's the only proper and safe way to call such a function, while all other variants lack security and, often, readability.
Try something like this:
$last = $mysqli->query("SELECT max(id) as last FROM table")->fetch_object()->last;
Cheers
Im learning, and am still struggling to get the hang of many OOP concepts so please keep that in mind when reading / answering the question.
So one of the primary purposes of object orientated programming is not to repeat yourself right. However, when I am creating methods, I constantly find myself repeating the same statements when querying the database. As can be seen in the below code taken from class I created.
function getCategory()
{
$sql = "SELECT * FROM jobs";
$stmnt = $db->prepare($sql);
$stmnt->execute();
$results = $stmnt->fetchAll();
foreach ($results as $result) {
$cat[] = $result['category'];
}
return $this->category = $cat
}
function selectCategory($selectedCategory){
$sql = "SELECT * FROM jobs
WHERE category =:category";
$stmnt = $db->prepare($sql);
$stmnt->bindValue(':category', $selectedCategory);
$stmnt->execute();
$results = $stmnt->fetchAll();
foreach($results as $result){
$result= array('category' => $result['category'], 'headline' => $result['headline']);
}
return $this->category = $result
}// selectCategory
My question.
Is there a way / what should I do to avoid having to continuously write the same database queries in my methods? I feel im a little out of depth here, however its not going to stop me from trying. Any help, advice welcomed (please keep in mind im a beginner)
You can run the query to get all data, then extract the data from fetched data using PHP.
But I don't like it, and it is not efficient.
You have 2 different query , so you need to calls, just improve your code a little more, you can make a model like this:
class Category
{
private $db;
public function __construct(PDO $db)
{
$this->db = $db;
}
function getAll()
{
return $this->db->query('SELECT * FROM jobs');
}
function getByCategory($category){
$stmt = $this->db->prepare(
"SELECT * FROM jobs WHERE category =:category"
);
$stmt->bindValue(':category', $category);
$stmt->execute();
return $stmt->fetchAll();
}
}
This is perfectly fine, and it is not really repeating
I'm having some difficulty returning an array out of a while lopp which I have in a function. Here is the code I am using. I am meant to be able to return an array of results from the function which contains the id numbers of pictures associated with a particular user id - in this case I want to print_r the array for the user id of 17. When this code isn't in the function it works, but when I place it in the function, no luck. I presume its related to a mistake I am making in the returning of the array. Your help is greatly appreciated.
function picture($id)
{
$sql = "SELECT * FROM avatar WHERE user_id={$id}";
$result = $database->query($sql);
$results = array();
while ($row = mysql_fetch_assoc($result))
{
$results[] = $row;
}
return $results;
}
$results = picture(17);
print_r($results);
Your function can't access your MySQL link identifier
First of all, you're mixing object-oriented paradigm ($database->query($sql)) with procedural paradigm (mysql_fetch_assoc($result)) which will make your code a nightmare to maintain.
Assuming that $database is a mysql_ link identifier, you'll need to pass it into your function in order to access it there.
function getUserAvatar($database, $id){
$sql = 'SELECT * FROM `avatar` WHERE `user_id`=' . intval($id) . ' LIMIT 1;';
$result = mysql_query($database, $sql);
$row = mysql_fetch_assoc($result);
return $row;
}
$results = picture($database, 17);
Don't just copy-paste that, keep reading!
The above will probably work, but if you're allowing a user to pass that user ID into the function, it's quite possible that they'll be able to find a vulnerability to inject an SQL statement of their choice into your MySQL database.
mysql_ functions are deprecated, so you should ideally stop using them and switch to mysqli or PDO. You'll also want to get an understanding of prepared statements in order to prevent SQL injections. If you can't upgrade, look at the mysql_real_escape_string and intval functions and make sure you sanitize all user inputs before processing them.
The resulting code will look something like this, if you switch to mysqli and prepared statements:
function getUserAvatar($db, $userId) {
$stmt = $db->prepare("SELECT * FROM `avatar` WHERE `user_id`=? LIMIT 1;");
$stmt->bind_param("i", $userId);
$stmt->execute();
$res = $stmt->get_result();
return $res->fetch_assoc();
}
$db = new mysqli("localhost", "user", "password", "database");
$result = getUserAvatar($db, 17);
may be you should try this..
function picture($id)
{
$sql = "SELECT * FROM avatar WHERE user_id={$id}";
$result = $database->query($sql);
$row = mysql_fetch_assoc($result);
return $row;
}
$results = picture(17);
print_r($results);
I am not familiar in this style of coding syntax but I want to use this for my project.
I have a question on how to integrate this query:
SELECT max(id) FROM assignment_billing WHERE assignment_id = 37
into this syntax.
public function fetchBillingByParentId($db,$id) {
$select = $db->select()->from('assignment_billing')->where('assignment_id = '.$id);
$stmt = $select->query();
$result = $stmt->fetchAll();
return $result;
}
I want to use max to get the highest id on that table but my syntax doesn't work.
public function fetchBillingByParentId($db,$id) {
$select = $db->select('max(id)')->from('assignment_billing')->where('assignment_id = '.$id);
$stmt = $select->query();
$result = $stmt->fetchAll();
return $result;
}
Did I forgot something? the first syntax is working though. But in the second syntax it doesn't return any value? I think I have an error in 'select('max(id)')->' line. What might be the proper arrangement in this kind of syntax?
Anytime you use an aggregate you must alias the column.
$select = $db->select('max(id) AS balloon')->from('assignment_billing')->where('assignment_id = '.$id);
You would then reference balloon as the column.
I'm pretty new to using PDO so I'm not sure if I have it down correctly, however with the following test I'm able to do some injection which I would like to bypass.
In my models class I have some shortcut methods. One of them is called return_all($table,$order,$direction) which simply returns all rows from a table:
public function return_all($table,$order = false, $direction = false) {
try {
if($order == false) {
$order = "create_date";
}
if($direction != false && !in_array($direction,array("ASC","DESC"))) {
$direction = "DESC";
}
$sql = "SELECT * FROM ".mysql_real_escape_string($table)." ORDER BY :order ".$direction;
$query = $this->pdo->prepare($sql);
$query->execute(array("order" => $order));
$query->setFetchMode(PDO::FETCH_ASSOC);
$results = $query->fetchAll();
} catch (PDOException $e) {
set_debug($e->getMessage(), true);
return false;
}
return $results;
}
This works fine, except, if I pass the following as $table into the method:
$table = "table_name; INSERT INTO `users` (`id`,`username`) VALUES (UUID(),'asd');";
Now it's unlikely that someone will ever be able to change the $table value as it's hard-coded into my controller functions, but, i'm a little concerned that I'm still able to do some injection even when I use PDO. What's more surprising is that the mysql_real_escape_string() did absolutely nothing, the SQL still ran and created a new user in the users array.
I also tried to make the table name a bound parameter but got a sql error I assume due to the `` PDO adds around the table name.
Is there a better way to accomplish my code below?
You have already solved your problem with direction.
if($direction != false && !in_array($direction,array("ASC","DESC"))) {
$direction = "DESC";
}
Use the same technique for table names
$allowed_tables = array('table1', 'table2');//Array of allowed tables to sanatise query
if (in_array($table, $allowed_tables)) {
$sql = "SELECT * FROM ".$table." ORDER BY :order ".$direction;
}