Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
When I try to do it it fetches the entire column, not just one field.
$connection = mysqli_query($db, "SELECT * FROM users");
<?php
while($row = mysqli_fetch_array($connection)) {
?>
<p>Your balance is: <?php echo $row['balance']; ?></p>
<?php
}
?>
That was outputting
Your balance is: 5
Your balance is: 0
Your balance is:
So I tried
$query_for_selecting = mysqli_query($db, "SELECT balance FROM users");
<?php if (mysqli_num_rows($query_for_selecting) > 0) { ?>
<?php while($row = mysqli_fetch_assoc($query_for_selecting)) { ?>
<p>Your balance is <?php $row['balance']; ?></p>
<?php } ?>
<?php } ?>
And that wasn't outputting anything so eventually, I tried using a WHERE clause and a limit of 1
$query_for_selecting = mysqli_query($db, "SELECT * FROM users WHERE balance = '3' DESC LIMIT 1");
<?php if (mysqli_num_rows($query_for_selecting) > 0) { ?>
<?php while($row = mysqli_fetch_assoc($query_for_selecting)) { ?>
<p>Your balance is <?php $row['balance']; ?></p>
<?php } ?>
<?php } ?>
All I got was a white screen
I think a basic little tutorial might be in order here.
First off: SELECT * FROM users means: "give me everything in the users table". You will get the full table, every row and every column.
while($row = mysqli_fetch_array($connection)) will loop through every row your query returns. It will call mysqli_fetch_array() and put the result in $row until there are no more rows in your query's result.
If you only want to output a single row of data, you have three options:
Add a WHERE condition so that your query will only fetch a specific row
Add a LIMIT clause so that your query will only fetch a single row
Call mysqli_fetch_array() only once instead of in a while loop
From the comments in the discussion thread, it looks like you want to retrieve only the balance for the currently logged in user, and you have a session variable somewhere that tells you who that user is. That means you'll want to use a WHERE condition so that your query will only fetch the row for that specific user.
You haven't told us what that session variables is called or what the name is of the column in the users table that you can compare that session variable with, so I'll assume that your users table has an id column and your session variable is called user_id and should match the id value from your users table.
So let's say the user with id 123 is currently logged in. You'll want to end up with the query SELECT balance FROM users WHERE id = 123.
The quick solution is to change your code to:
$connection = mysqli_query($db, "SELECT balance FROM users WHERE id = " . $_SESSION['user_id']);.
This is bad code. We'll make it better, but try this first and see if it gets you the result you actually want. If it doesn't, let me know.
The reason this is bad code is because adding variables to a query string like this dramatically increases the risk of SQL injections. If there's any possibility at all that the value of the variable comes from user input, then at some point a user will figure that out and make sure it contains something that will break your application.
Best case scenario: the page simply won't render for that one user.
Bad case scenario: the user will be able to read out your entire database and will sell sensitive user data to the highest bidder.
Worst case scenario: the user will be able to inject some of their own Javascript code into your database in a column you're not sanitizing before rendering, letting them capture and intercept passwords and/or financial information your users are entering on your site and they will then use that information to make life miserable for all of your users.
So you don't want to just drop $_SESSION['user_id'] into your query like that. Instead, you'll want to use a prepared statement and let the database handle the problem of dropping the variable into the query.
First, you'll need to prepare your query:
$statement = mysqli_prepare($db, "SELECT balance FROM users WHERE id = ?");
The ? symbol is a placeholder where you can bind a parameter. Let's do that:
$statement->bind_param("i", $_SESSION['user_id']);
The "i" tells MySQL that you're binding an integer value. If you're not matching against a user id but a username, for example, you'll want to instead use "s" to tell MySQL you're binding a string value.
Now you can execute the query and get the result. Putting it all together:
$statement = mysqli_prepare($db, "SELECT balance FROM users WHERE id = ?");
$statement->bind_param("i", $_SESSION['user_id']);
$statement->execute();
$connection = $statement->get_result();
Let us know if that works. Some tweaking might be required.
I have a feeling as to what's going on. You're fetching the entire database without either using a LIMIT of 1 and/or use a WHERE clause, given that you have unique ID's somewhere for columns. I am sure that you have more than the one record in your database table.
I was going to post this in a comment but decided not to. Stack doesn't really want us to do that, (edit) and at this point, it is way too long for a comment.
#ADyson "I initially wanted to display the balance of the user that's logged in, but that didn't work out." – markthedark
About that. It seems that what you are looking for is to get the balance for a user/record in particular. For that, you definitely need to use a WHERE clause.
If your query failed, enable error reporting and checking for errors on the query.
References:
https://www.php.net/manual/en/function.error-reporting.php
https://www.php.net/manual/en/mysqli.error.php
Plus, the $i = 0; and $i++; may not be helping. It's hard to say what that is supposed to do. I know the syntax, I just don't know why you're wanting to increase it.
Side note: I would avoid in using $connection as a query variable assignment. It could be confusing. Try to use something clear like $query_for_selecting.
Related
I was running a site I purchased that I thought was fairly unhackable. However, after having an attack, I found it was not. He informed me of the vulnerability, however my question is what user input could have been done to get all the users usernames like he did? Here is the code...
$un=$_GET['username'];
$q=$db->query("SELECT * FROM users WHERE login_name='$un' OR username='$un'");
I realize that this is highley hackable. Therefore, I changed the site over to prepared statements to prevent this from happening again. I just want to know what he could have entered to get all the users usernames.
Someone posted the script on github, you can find it here:
https://github.com/sat312/Mafia-Game-Script/blob/master/checkun.php
' OR 1=1;
In the URL:
/yourScript.php?username=%27%20OR%201%3D1%3B
The idea is that since data is mixed with the command, you can just finish the command with data.
You get $un from the user, so I can type anything I want and it'll get substituted into your query. It's called a SQL Injection attack.
Lets say $un = ' OR 1 = 1;-- then your query becomes:
SELECT * FROM users WHERE login_name='' OR 1 = 1;--' OR username='' OR 1 = 1;--'
What will happen? this gets executed:
SELECT * FROM users WHERE login_name='' OR 1 = 1;
This will return every row in the table.
He may have used the GROUP_CONCAT statement in MySql which basically groups a column in multiple rows into a single row (see Can I concatenate multiple MySQL rows into one field? for more information). He may have terminated the original SQL statement or UNIONED it with his own and added a LIMIT and ORDER BY to ensure his result got returned and commented out the remained of the original statement.
This is one possibility, but there are probably a few others.
I am experiencing something so basic, yet so annoying that I thought I had to put it out to the wider community to save my sanity.
I am using a table within a database to store some very basic data. There is only two columns, Id and Campaign. I only want to use a single row of the table, however, campaign will be updated at various points. I have set up the table as follows:
$sql = "CREATE TABLE IF NOT EXISTS TestCampaign(id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
Campaign CHAR(20))";
Initially I write to the table to insert a null CHAR in campaign:
$sql = "INSERT INTO TestCampaign (Campaign) VALUES ('None')";
The based on a specific text field being filled in on an html form followed by a submit button press I intended to do the update of the campaign field:
$sql = "UPDATE TestCampaign SET Campaign = '$Test' WHERE id = '1'";
$Test is the POSTED campaign name from the form. Unfortunately although the INSERT works fine the UPDATE doesn't. I have checked the permissions and I have ALL on this database. I have also checked the syntax with various sites and it seems that it is fine.
Interestingly I do not get an error when I echo:
echo " ".mysqli_error($con);
I'm sure I have made some basic error somewhere but I have been looking at it for so long and changing the syntax that I can't seem to spot it.
Any help would be appreciated.
UPDATE:
I have played around with the code and it seems as though the UPDATE code does work, however, It only works when it is the next line of code after the INSERT. In fact I have found that it works as long as it is not where I need it to be. I have it placed in 'if' statement that is run only on a specific button press on the form:
if(isset($_POST['TestID']))
{
Some Code;
$sql = "UPDATE TestCampaign SET Campaign = '$Test' WHERE id = '1'";
Some More Code;
}
I have checked the rest of the code in the 'if' statement and it seems solid.
Is this odd behaviour or have I missed something?
SOLVED
Finally found out what the problem was, it ended up that when exiting the first 'if' statement as expected the html form code was revisited which must have closed the connection to the database, when the button was pressed to run the second 'if' statement there was a connection to MySQL but no connection to the database I needed access to. A quick fix to re-connect and all works fine.
$sql = "UPDATE TestCampaign SET Campaign = '$Test' WHERE id = 1";
Is the only thing I think is wrong... What do you get with :
Select * from TestCampaign
have you set up any triggers based on this table name? After update, before update triggers may prevent you from storing the required data on the table.
Also, MySQL may use 0 as id value if you don't specify the value of the id at sending insert command. Are you sure the value of your id is 1 in the record you want to update? If you have run insert statements before on your table, the id may be a larger number than 1, because of the MySQL indices (I guess this may be the problem).
I don't know how exactly PHP statements are processed when sending them to MySQL, but I would recommend you to use PDO statements, the PHP syntax would look something like this:
$sql = $pdo->prepare("UPDATE TestCampaign SET Campaign = ? WHERE id = ?");
$sql->bindParam(1, $Test);
$sql->bindParam(2, 1);
$sql->execute();
Tutorial: http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers
I would also echo your $Test variable to check what is stored in it.
Hope it helps...
Finally found out what the problem was, it ended up that when exiting the first 'if' statement as expected the html form code was revisited which must have closed the connection to the database, when the button was pressed to run the second 'if' statement there was a connection to MySQL but no connection to the database I needed access to. A quick fix to re-connect and all works fine.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Is there any simplification for this?
$query = $this->link->prepare('SELECT * FROM test WHERE id = :id LIMIT 1')
$query->bindParam(':id', $id);
$query->execute();
$row = $query->fetch(PDO::FETCH_ASSOC);
unlink($row['avatar']);
$query = $this->link->prepare('DELETE FROM test WHERE id = :id LIMIT 1');
$query->bindParam(':id', $id);
$query->execute();
I don't like to advise people to skip using query parameters. You should get into the habit of doing it.
It's actually not hard, and it makes it simpler to write queries because you never have to think about whether you got the right kind of escaping and quoting. I find it makes my code look more clear.
I've always been puzzled how people learn that they need to use bindParam() for everything with PDO. It's simpler in most cases to pass an array of parameters to execute(). The only case when I typically use bindParam() is if I need to pass a NULL value.
Also you don't need to use named parameters, you can use positional parameters (but don't mix these parameter types in a given query).
fetchColumn() is simpler if you only need one column. Speaking of which, avoid SELECT * when you don't need all the columns.
If you are querying for a specific id, assuming that's the primary key, then you don't need LIMIT 1. There can be at most one row for a specific value in any unique key.
I assume you've enabled the exception-based error reporting. If not, you should check the result from each call to prepare() and execute() because they return false on error.
$query = $this->link->prepare('SELECT avatar FROM test WHERE id = ?')
$query->execute([$id]);
$avatar = $query->fetchColumn();
unlink($avatar);
$query = $this->link->prepare('DELETE FROM test WHERE id = ?');
$query->execute([$id]);
PS: The short syntax for arrays, like [$id], requires PHP 5.4
Thank you for the good question. To my utter disappointment, such questions are extremely rare on this site.
Is there any simplification for this?
Sure.
This is called "programming".
Although for the average PHP user programming stands for just putting several predefined blocks together, like LEGO bricks, in reality programming stands more for invention, for creating something new. And no less for optimizing too, for taking less moves for the same action.
A programmer could always create a function to encapsulate repeated tasks. Eventually he may wish to put such functions together into a class, but that's not the point.
As you can see, most of your operators just repeated ones. Every time you see a repetition you know for sure there can be a function or at least a loop.
Here is your code using my attempt in programming, aimed (beside extra safety) to the very code shortening:
$name = $this->link->getOne('SELECT avatar FROM test WHERE id = ?i', $id)
unlink($name);
$this->link->query('DELETE FROM test WHERE id = ?i', $id);
As you can see, this code is Extra DRY (stands for Don't Repeat Yourself) - all the repeated code is just taken away into internals.
Well, as you can see, my class is built upon mysqli. but of course something similar can be done even using ugly PDO, using wrapper sort of one I posted recently:
$name = $this->link->query('SELECT avatar FROM test WHERE id = ?', [$id], "one");
unlink($name);
$this->link->query('DELETE FROM test WHERE id = ?', [$id]);
By the way, taking programming little further you may shorten this code even more:
unlink($avatar_dir.$id.".png");
$query = $this->link->query('DELETE FROM test WHERE id = ?i', $id);
as avatar image obviously don't need no dedicated name and just id can serve perfectly, saving you extra field in database and extra query. All avatars can be converted to single format at the time of upload, to reduce the headache even more.
Im trying to figure out how to update my table using PDO - I need to update 2 records simultaneously only im unsure how this works.
I have my session user, and my "befriended user".
My befriended user will have 10 credits or so in my table and he can offer other users X credits when they befriend him.
// $uid is my logged in session user
// $follow_id is the id of the person were trying to befriend
// Im confused by the whole process of this do i write 2 queries? 1 that minuses credits from the befirended user, and then one that adds the credits to the current session users column?
$upd_stmt = $conn->prepare('SELECT * FROM users WHERE user_id=? ');
$upd_stmt->bindParam(1, $uid, PDO::PARAM_INT);
$upd_stmt->execute();
while( $row = $upd_stmt->fetch(PDO::FETCH_ASSOC) ) {
$row['credits_offered'];
}
The short answer is, yes, you will need to write two queries, one to subtract and the other to add.
You could probably do it in one query, but I would recommend doing it in two for better readability. I would also recommend doing it via a transaction, if the first query executes successfully but the second doesn't, you would want to roll it back.
PHP + MySQL transactions examples
This is what transactions were made for. You don't need to do this in one query to make sure they are both executed succefully.
$dbh->beginTransaction();
$addQuery = "UPDATE ...";
$subtractQuery = "UPDATE ...";
$sth = $dbh->exec($addQuery);
$sth = $dbh->exec($subtractQuery);
$dbh->commit(); // or $dbh->rollback();
Read more about transactions here: http://en.wikipedia.org/wiki/Database_transaction
Short version - they ensure that either all your queries are executed succefully, or none.
I want to do something like this:
$query=mysql_query("SELECT userid FROM users WHERE username='$username'");
$the_user_id= .....
Because all I want is the user ID that corresponds to the username.
The usual way would be that:
$query=mysql_query("SELECT * FROM users WHERE username='$username'");
while ($row = mysql_fetch_assoc($query))
$the_user_id= $row['userid'];
But is there something more efficient that this?
Thanks a lot, regards
You've hit the nail right on the head: what you want to do is SELECT userid FROM users WHERE username='$username'. Try it - it'll work :)
SELECT * is almost always a bad idea; it's much better to specify the names of the columns you want MySQL to return. Of course, you'll stil need to use mysql_fetch_assoc or something similar to actually get the data into a PHP variable, but at least this saves MySQL the overhead of sending all these columns you won't be using anyway.
As an aside, you may want to use the newer mysqli library or PDO instead. These are also much more efficient than the old mysql library, which is being deprecated.
Not only can you, but you should. Unfortunately too many young developers get in the habit of selecting far too much data. Once you run your query, you don't need to do a while loop since you only have one record coming back. Instead, just use the following:
$sql = sprintf( "SELECT userid FROM users WHERE username = '%s'", $username );
$result = mysql_query( $sql ) or die( mysql_error() );
$data = mysql_result( $result, 0 );
if ( $data ) echo $data; // first userid returned
The second parameter of mysql_result() is the row index you would like to retrieve. 0 is first.
The "usual" way is to only select the columns that you need.
Any column that is part of the select and is not needed will slow down the retrieval. Partly because of network traffic and partly because the database engine can apply certain optimizations if only some columns are selected.
And select * is usually frowned upon in production code.
Your query is correct:
$query = mysql_query("SELECT userid FROM users WHERE username='$username'");
This will work if done correctly. Note that $username must be correctly escaped with mysql_real_escape_string. I'd recommend looking at parameterized queries to reduce the risk of introducing an SQL injection invulnerability.
One other thing you can change is to use mysql_result instead of your loop:
$the_user_id = mysql_result($result, 0);
This assumes that know you'll get only one row.
Yes, that's a great optimization practice!
Also, if you want to go a step further and make it super-optimized, try adding a LIMIT, like this: $query=mysql_query("SELECT userid FROM users WHERE username='$username' LIMIT 1");
This, of course, assumes you expect only one userid to be returned and will make the database engine stop once it finds it.
But, the most important thing: ALWAYS ESCAPE/SANITIZE YOUR INPUT DATA! (can't stress this well enough)
You can do this with a single line of code
echo array_values(mysqli_fetch_array($mysqli->query("SELECT name FROM user WHERE id='$userid'")))[0];
You must connect to the database as shown below before using this
$mysqli = new mysqli('HOST', 'USERNAME', 'PASSWORD', 'DATABASE');
Credits to #samuel t thomas