Returning a value from an SQL Method - php

]i'm completely out of idea's as to why the code below does not return the value. I have 2 sql tables that related to one another. Within a class i have the following method, and within the scope of that method all is well. The var dump shows the correct data. The following code is stated in class.php.
public function getId($username, $password) {
if (isset($_SESSION['username'])) {
$sql = "SELECT person_id FROM user WHERE username = ?";
$stmt = $this->dbh->prepare($sql);
$stmt->bindParam(1, $_SESSION['username']);
$stmt->execute();
$id = $stmt->fetch(PDO::FETCH_NUM);
$id = $id[0];
}
ELSE {
echo "Failed to retreive person_id";
}
var_dump($id);
return $id[0];
}
However when i return that value to the showinfo.php which is the main document and state the following:
$user_id = $id[0];
var_dump($user_id);
Then the var dump echoes "NULL". And I need it for the follwing method which is also in class.php.
public function showInfo($user_id) {
$sql = "SELECT * FROM person WHERE person_id = ?";
$stmt = $this->dbh->prepare($sql);
$stmt->bindParam(1, $user_id);
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
foreach ($result as $row) {
echo "<pre>".print_r ($row, true)."</pre>";
}
}
Could anybody be so kind as to show me ways to get this done?
Many thanks in advance for your time and effort in helping me.

I'm guessing you are trying to access the field with the index [0] twice.
Maybe try to return just $id and then access [0] on the outer class.

My PHP is a bit rusty and I don't have access to test right now, but don't you need single quotes around the question mark so it goes to SQL quoted?
i.e.
$sql = "SELECT * FROM person WHERE person_id = '?'";
or
$stmt->bindParam(1, "'" + $_SESSION['username'] + "'");
(but not both!)
so that SQL sees
SELECT * FROM person WHERE person_id = 'MyVal'
instead of
SELECT * FROM person WHERE person_id = MyVal
which it would interpret as a column name

You don't show where the method is called.
You tried this in showinfo.php:
$user_id = $id[0];
Shouldn't this be...
$user_id = getId('someusername', 'somepassword')
Or something similar? Sorry this isn't an answer, but I can't comment.

Related

How can I delete a like from my database if user_id and post_id are the same?

I want to check if user already liked the post, if so than delete the user from database likes.
I've tried to do an if statement but it wont get to the else and only add likes even when user_id and post_id are the same.
Like.class.php
private function Addlike(){
$conn = db::getInstance();
$query = "insert into likes (post_id, user_id) values
(:post_id, :user_id)";
$statement = $conn->prepare($query);
$statement->bindValue(':post_id',$this->getPostId());
$statement->bindValue(':user_id',$this->getUserId());
$statement->execute();
}
private function Deletelike(){
$conn = db::getInstance();
$query = "DELETE FROM likes WHERE post_id = :post_id
AND user_id =:user_id";
$statement = $conn->prepare($query);
$statement->bindValue(':post_id',$this->getPostId());
$statement->bindValue(':user_id',$this->getUserId());
$statement->execute();
}
public function CheckLike(){
$conn = db::getInstance();
$query = "SELECT COUNT(*) FROM likes WHERE
post_id=:post_id AND user_id=:user_id";
$statement = $conn->prepare($query);
$statement->bindValue(':post_id',$this->getPostId());
$statement->bindValue(':user_id',$this->getUserId());
$statement->execute();
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
if($result["COUNT(*)"] == 0){
$this->Addlike();
}else{
$this->Deletelike();
}
return $result;
}
If you press like for the first time you should like the post and it should be stored in the database, if you press again you unlike the post and it gets deleted from the database. But now it only does the Addlike function...
I think PDO::FETCH_ASSOC returns a multidimensional array when used with PDOStatement::fetchAll, according to https://www.php.net/manual/en/pdostatement.fetchall.php#refsect1-pdostatement.fetchall-examples.
Try changing your code to something like this and see if it works. You could also try dumping the $result variable to see what the structure looks like.
if($result[0]["COUNT(*)"] == 0){
$this->Addlike();
}else{
$this->Deletelike();
}
If an array index doesn't exist, PHP considers it false, which would explain why you're always adding likes, since false == 0 in PHP.
If you want to avoid this equivalency of false and 0, use the identical operator to also compare types:
if ($result["COUNT(*)"] === 0) {
...

What's the proper way to return a single database result?

All I want to do is get the firstname result from this function, but it feels it's too much code to do that based on session id.
//query_functions.php
function find_name_by_id($id) {
global $db;
$sql = "SELECT firstname FROM admins ";
$sql .= "WHERE id='" . db_escape($db, $id) . "' ";
$sql .= "LIMIT 1";
$result = mysqli_query($db, $sql);
confirm_result_set($result);
$name = mysqli_fetch_assoc($result); // find first
mysqli_free_result($result);
return $name; // returns an assoc. array
}
// admin.php
id = $_SESSION['admin_id'];
$name = find_name_by_id($id);
// what is the shortest way to get this $name result?
To do this properly using prepared statements you actually need more code than that:
function find_name_by_id($db, $id) {
$stmt = $db->prepare("SELECT firstname FROM admins WHERE id=?");
$stmt->bind_param("i", $id);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();
$stmt->free_result();
return $row[0];
}
I'm not sure what confirm_result_set is so I left it out.
Let's pretend that $db was a PDO object:
function find_name_by_id($db, $id) {
$stmt = $db->prepare("SELECT firstname FROM admins WHERE id=?");
$stmt->execute([$id]);
return $stmt->fetchColumn();
}
Much less code involved. And for a higher-level API this will be abstracted to a single line of code.
In reality for all cases you'd want to do some error checking, account for no records being returned, etc. Also you should avoid global variables, they're very poor form. Put your code into a class or just use dependency injection as I've done.

PHP/MySQL keeping track of uses

I'm trying to update my tables with a total number of uses when a function is called. What I need to do is grab the former number of uses, and add one. I have a pretty good general idea how to go about this, but I don't quite know how to get unique ID's with their respective uses. This is what I have so far...
<?php
$query = $conn->query('select name, uses from users');
$i = 0;
while($r = $query->fetch(PDO::FETCH_OBJ)){
$name[$i] = $r->name;
$uses[$i] = $r->uses;
$i = $i+1;
}
if(isset($_POST['mName']))
{
$mName = urldecode($_POST['mName']);
$mUses = $uses + 1;
"UPDATE users
SET uses=:uses WHERE name=:name";
$stmt = $conn->prepare($sqlUPDATE);
$stmt->bindParam(':uses', $mUses);
$stmt->bindParam(':name', $mName);
$stmt->execute();
?>
I can see my issue is that I'm assigning the uses variable to an array, I don't know how to get it specific to the username. Is this a simple SQL query I'm missing?
You can store the data in an array called $uses with the key being the user name and the value being the number of uses. Then if you detect a POST with the mName parameter set, you can reference your $uses array with that name and get the number of uses, and add 1.
<?php
$query = $conn->query('select name, uses from users');
while($r = $query->fetch(PDO::FETCH_OBJ)){
$uses[$r->name] = $r->uses;
}
if(isset($_POST['mName'])) {
$mName = urldecode($_POST['mName']);
$mUses = $uses[$mName] + 1;
$sqlUPDATE = "UPDATE users SET uses=:uses WHERE name=:name";
$stmt = $conn->prepare($sqlUPDATE);
$stmt->bindParam(':uses', $mUses);
$stmt->bindParam(':name', $mName);
$stmt->execute();
}
?>
Though there is no error checking and handling in here. If there happens to be a POST with mName and that name doesn't exist, nothing will update, but nothing will insert for new users. Also, instead of using a name, it would be better to use an id for the user if possible.

Function/Trigger already in use?

Im having problems getting an update function to work. The function marks badges as seen so that they are hidden from a notification window.
The function is called when the user clicks a button to mark them as seen.
I have two triggers on the table its trying to update which I think may be causing the problem.
The problem is : Can't update table 'users' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
Triggers:
Function:
function markAsSeen() {
require "connect.php";
$seen = mysqli_query($connection,"Update userbadges
INNER JOIN users ON users.id = userbadges.user_id
SET seen='1'
WHERE studentid = '".$_SESSION["studentid"]."' && seen=0") or die(mysqli_error($connection));
while ($data = mysqli_fetch_array($seen)) {
echo 'Done';
}
}
Is there any way around this?
Your issue is that the update_users_trigger trigger makes changes to the contents of the table users, while the query that is triggering the execution of this trigger also uses the table users.
You will need to adjust your query so that this deadlock doesn't occur. It isn't clear which fields are from each table, but I suspect that in your initial query you need to join on users so that you can query on studentid.
You could create a different function to get the userID that you need something like the following:
require_once "connect.php";
function getUserIDFromStudentID($student_id, mysqli $connection)
{
$query = 'SELECT id FROM users WHERE studentid = ? LIMIT 1';
$stmt = $connection->prepare($query);
// Replace the below s to an i if it's supposed to be an integer
$stmt->bind_param("s", $student_id);
$stmt->execute();
$result = $stmt->get_result();
$record = $result->fetch_object();
$result->free();
if ($record) {
return $record->id;
}
}
function markAsSeen(mysqli $connection) {
$user_id = getUserIDFromStudentID($_SESSION["studentid"], $connection);
if (! $user_id) {
throw new Exception('Unable to get user id');
}
$seen_query = 'UPDATE userbadges SET seen = 1 WHERE user_id = ? and seen = 0';
$stmt = $connection->prepare($seen_query);
// Replace the below s to an i if it's supposed to be an integer
$stmt->bind_param("s", $user_id);
$result = $stmt->execute();
if (! $result) {
die(mysqli_error($connection));
}
echo 'Done';
}
Passing the connection object around rather than requiring a global file to be required every time will allow for more flexibility.

Why do I get Call to a member function bind_param() on a non-object...?

I am making a game for class and I have added a commenting system to go with it. I am now wanting to add the ability to report the comment.
I have added a column in the comments table called report_active and my idea was to set this to 1 when it is active (meaning it has been reported) and 0 when it isn't. Then just list in the adminCP all of the comments with an active report on them.
I have made a file called report_comment.php which I intend to only be used to run the queries then redirect back to another page.
This is my report_comment.phppage:
<?php
require_once('db_connect.php');
require_once('security.php');
if (isset($_GET['id'])) {
$report_active = 1;
$id = $_GET['id'];
$select = $db->query("SELECT * FROM comments WHERE id = ?");
$select->bind_param('i', $id);
if ($select->execute()) {
if ($select->num_rows) {
// Run the update query
$update = $db->query("UPDATE comments SET report_active = ? WHERE id = ?");
$update->bind_param('ii', $report_active, $id);
if ($update->execute()) {
header('Location: comments.php');
die();
}
}
}
}
?>
What am I doing wrong? As this is the error I am returned with:
Fatal error: Call to a member function bind_param() on a non-object
$select = $db->query("SELECT * FROM comments WHERE id = ?");
^^^^^---execute the query immediately
You want
$stmt = $db->prepare("SELECT * FROM comment WHERE id = ?");
^^^^^^^---note the diff
instead. Plus, you should be checking for failure, e.g.
if ($stmt === false) {
die("Prepare failed with error: " . $db->errorInfo);
}
or similar for your particular DB library.

Categories