Use parameter of php function as column name in SQL query - php

This is for a school project. I am new in PHP and MySQL.
I am trying to write a function in PHP with one string parameter, which will become the column name of a SQL query which is used in a prepare() statement inside this function.
Here is the code:
function checkCredentials($dbFieldToCheck) {
$statement = $conn->prepare("SELECT id FROM user WHERE ".$dbFieldToCheck." = ? AND password = PASSWORD(?)");
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error);
$statement->bind_param("ss", $_POST["username/email"], $_POST["password"]);
$statement->execute();
$result = $statement->get_result();
$row = $result->fetch_assoc();
return $row;
}
Then I call this function twice in two different variables:
$row1 = checkCredentials('email');
$row2 = checkCredentials('username');
Finally I do something with these two variables (not useful here I guess).
I have tried different ways to write the parameter in the SQL statement also different ways to write it in the function call. Now I am even starting to think that my function is not even called at all...
What I want to achieve works if I just execute the code inside the function two times with the column name hard coded. But this is not nice :)
Any help is very much appreciated. Thanks!

Add to the parameter of your function the submitted POST data and your connection variable. When you call your function, it will look like this:
checkCredentials($dbFieldToCheck, $conn, $_POST["username/email"], $_POST["password"]);
Your function will look something like this:
function checkCredentials(string $dbFieldToCheck, $conn, $username, $password) {
$statement = $conn->prepare("SELECT id FROM user WHERE ".$dbFieldToCheck." = ? AND password = PASSWORD(?)");
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error);
$statement->bind_param("ss", $username, $password);
$statement->execute();
$result = $statement->get_result();
$row = $result->fetch_assoc();
return $row;
}
You can use global to call variables inside your function (you can refer here for the cons of using global).

My guess is that your function doesn't know about $conn because it wasn't declared in its scope.
Your function should begin like this :
global $conn;
See the manual for more information about variable scope.
EDIT :
As apokryfos pointed out in the comments, the use of global is not recommended. It would be better to pass $conn as a parameter to checkCredentials.
See the accepted answer to this question for details. Quote :
A function call should not have to rely on anything outside

I guess you can modify your code like this:
$servername = "localhost:3306";//replace with your mysql server address
$username = "username";//replace with your mysql user
$password = "password";//replace with your mysql password
// Create connection
$conn = new mysqli($servername, $username, $password);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
echo "Connected successfully";
function checkCredentials(string $dbFieldToCheck, $conn, $username, $password) {
$statement = $conn->prepare("SELECT id FROM user WHERE ".$dbFieldToCheck." = ? AND password = PASSWORD(?)");
if (!$statement) die("Prepare failed: (" . $conn->errno . ") " . $conn->error);
$statement->bind_param("ss", $username, $password);
$statement->execute();
$result = $statement->get_result();
$row = $result->fetch_assoc();
return $row;
}
checkCredentials('email');
Using PHP with MYSQL is not complex, this doc can help you get the basic idea how they work together
(http://www.w3schools.com/php/php_mysql_connect.asp).

Related

Getting error when calling connect as function in prepare statement

EDIT. My error ONLY occurs when calling database connection as a function, if I call my database connection normally, the error do not occur.
I'm trying to execute a prepare statement with database connection as a function so that it can be reused inside other functions. Executing normal SQL codes work when using database connection function but I'm getting errors when I try to use in a prepare statement.
This is my code.
function connect(){
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "test";
$conn = new mysqli($servername, $username, $password, $dbname);
return $conn;
}
if (connect()->connect_error) {
die("Connection failed: " . connect()->connect_error);
} else {
echo "GOOD";
}
$val = "1";
$stmt = connect()->prepare("SELECT * FROM countries WHERE id = ?");
$stmt->bind_param("s",$val);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
echo $row['name'];
}
$stmt->close();
When connecting database as a normal variable such as this works.
$stmt = $conn->prepare("SELECT * FROM countries WHERE id = ?");
However, I get "Call to a member function fetch_assoc() on bool" whenever I tried to call my connection as a function.
What am I doing wrong with this code?
After searching for a while and based on this answer, I was able fix my problem by declaring a variable for connection. However, this doesn't explain why directly calling connect doesn't work. Can somebody explain to me why the first way doesn't work?
$db = connect();
$stmt = $db->prepare("SELECT * FROM countries WHERE id = ?");

Output one result if criteria matches

I feel like this is probably an easy one but just can't see it!
I've built a test where results are saved into a database table. At the moment it's saving a row for every test taken. The test can be taken until it's passed.
At the moment it's outputting every result (as it's looping over every result in the table).
How can I only output $row['testname']; once if the output of $row['pass-fail']; is "Pass"?
<?php $current_user = wp_get_current_user();
$user = $current_user->user_login;
require("database.php");
// Opens a connection to a MySQL server
$con = mysql_connect("localhost", $username, $password);
if (!$con) {
die('Could not connect: ' . mysql_error());
}
mysql_select_db("tester", $con);
$sql = mysql_query("SELECT * FROM test WHERE name='$user' ORDER BY Date DESC");
if (!$sql) {
die('Error: ' . mysql_error());
} ?>
<?php while($row = mysql_fetch_array($sql)) { ?>
<p><?php $testname = $row['testname']; echo get_the_title( $testname ); ?> - <?php echo $row['pass-fail']; ?></p>
<?php } ?>
<?php mysql_close($con); ?>
Use a WHERE clause in your query to only select the ones that have pass-fail equal to "Pass". Also, use prepared statements.
$current_user = wp_get_current_user();
$user = $current_user->user_login;
require("database.php");
// Opens a connection to a MySQL server
$conn = new mysqli("localhost", $username, $password, "tester");
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$stmt = mysqli_prepare($conn, "SELECT * FROM `test` WHERE `name`=? AND `pass-fail`='Pass' ORDER BY `Date` DESC");
$stmt->bind_param("s", $user);
$stmt->execute();
$result = $stmt->get_result();
while($row = $result->fetch_assoc()) {
$testname_title = get_the_title($row['testname']);
echo "<p>{$testname_title}</p>";
}
$conn->close();
For this to work you must have the mysqlnd driver.
If you don't have this, I suggest PDO (which, IMO, is also easier to use in general) - If you need help learning how to use PDO for safe and secure queries, then you can check out this answer that I wrote that demonstrates a function that I wrote that makes Prepared Statements easy, clean, and secure. Alternatively you can learn more about Prepared Statements for MySQLi

MYSQL AES_ENCRYPT issues

I have a simple application that needs to store sensitive data in a Wordpress installation.
The data comes from the user via a Form, and up until now, I have been storing the data using $wpdb->insert, however as we get closer to launching this project, I want to make sure that sensitive user information is encrypted, and only decrypted when read.
I have no clue how to make this work using the $wpdb class, so I resorted to using mysqli for this component. So far, I run the $wpdb->insert statement to insert all the normal data, then open a new connection to try and insert the sensitive data.
$id = $wpdb->insert_id;
$servername = 'localhost';
$username = 'root';
$password = 'root';
$db = 'wp_database';
$conn = new mysqli( $servername, $username, $password, $db );
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// Fetch Data and store it
$sud = $form['sens_user_data'];
$key = 'mysecretkey';
$tbl = $wpdb->prefix . 'sensitive';
$sql = "UPDATE $tbl SET sens_user_data = AES_ENCRYPT(?, ?) WHERE id = ?";
if ( $stmt = $conn->prepare($sql) ) {
$stmt->bind_param('ssi', $sud, $key, $id);
$stmt->execute();
} else {
$error = $conn->errno . ' ' . $conn->error;
ChromePhp::log($error);
}
$conn->close();
This appears to work correctly, except all the values always encode to a single character, and then decode to NULL
What am I doing wrong?

Error occurred ... no database selected

I'm trying to connect to a database, check a column for whether a value exists or not, then execute a function based on whether or not that value exists.
Here's my code.
$con = mysql_connect('localhost','root','','users');
$sql = "SELECT * FROM allUsers WHERE username = '".mysql_real_escape_string($_POST["username"]) . "'";
$result = mysql_query($sql,$con) or die("Error occurred in [$sql]: " . mysql_error());
$count = mysql_num_rows($result);
if ($count != 0){
echo "Username is already taken";
echo "$count";
mysql_close($con);
}
else{
createUser($_POST["name"],$_POST["username"],$_POST["password"],$_POST["email"]);
}
The thrown error is:
Error occurred in [SELECT * FROM allUsers WHERE username = 'Admin']: No database selected.
I'm almost entirely sure that it comes from the $result line, but haven't a clue as to why.
I feel like this is a simple solution, and I'm just missing something minor.
I'm very new to MySQL (today is my first day, actually), so please keep solutions as simple as possible.
You forgot to call mysql_select_db after connecting:
$con = mysql_connect('localhost','root','');
mysql_select_db('users', $con);
Unlike MySQLi or PDO, mysql_* libraries does not take database as argument on the connection string, however if you were to migrate to either MySQLi or PDO.
MySQLi:
$con = new mysqli('localhost', 'root', '', 'users');
PDO:
$con = new PDO('mysql:host=localhost;dbname=users', 'root', '');
In MySQLi your code would look like this:
<?php
$host = "localhost";
$user = "root";
$pass = "";
$database = "users";
$con = mysqli_connect($host,$user,$pass,$database);
if($con->connect_error)
die('Connect Error (' . mysqli_connect_errno() . ') '. mysqli_connect_error());
$stmt = $con->prepare("SELECT * FROM allUsers WHERE username = ? LIMIT 1");
$stmt->bind_param('s',$_POST["username"]);
if (!$stmt->execute())
die('Failed to excute with error ' . $con->error);
$stmt->store_result();
$count = $stmt->num_rows;
$stmt->close();
if ($count > 0)
{
echo "Username is already taken.";
}
else
{
createUser($_POST["name"],$_POST["username"],$_POST["password"],$_POST["email"]);
}
I think your error is quite obvious, you need to specify the database you want.
mysql_select_db("databaseName", $con);
With that taken care of, please, please don't use mysql_ libraries the are vulnerable to SQL injection and will soon be removed.

Passing mysqli connection to a PHP function - out of synch

I have a problem when performing mysql commands when I invoke a function in another file. If I have the code in the same file, it works fine. The code looks like:
authenticate:
{
$conn = new mysqli($dbserver, "dbuser", "pass", $dbname);
$sql = 'SELECT userId, salt, pwd, isAdmin FROM users where username = ?';
$stmt = $conn->stmt_init();
$stmt->prepare($sql);
$stmt->bind_param('s', $username);
$stmt->bind_result($userId, $salt, $storedPwd, $isAdmin);
$stmt->execute();
$stmt->fetch();
}
Now, if I call a function, immediately after fetch, it fails on the bind_param line. I call it like this:
updateUserActivity ($conn, $tpcLang, 'LI', $userId);
the beginning of this function is:
function updateUserActivity ($conn, $lang, $activityType, $userId)
{
// check that activity is valid
$sql = 'SELECT activityType
FROM activityType
WHERE activityType = ?';
$stmt = $conn->stmt_init();
$stmt->prepare($sql);
$stmt->bind_param('s', $activityType);
$stmt->bind_result($activityTypeInDB);
$stmt->execute();
$stmt->fetch();
if ($activityType == $activityTypeInDB){
$success=1;
} else {
$success=0;
$msg = $lang->get('UPDATE_USER_INVALID_ACTIVITY_ERROR_MSG') . " " . $activityType . " (" . $stmt->errno . "): " . $stmt->error;
error_log ($msg);
}
// continue on to add a row in the userActivity table
}
The error I get on the bind_param is: invalid object or resource mysqli_stmt, and the DB error is: Commands out of sync; you can't run this command now.
Any suggestions would be greatly appreciated.
try adding this after your fetch.
mysqli_free_result($result);
or
mysqli_close($conn);

Categories