Kinda new to mysql and php
I have a hit counter for each page on my site and a private page that list all pages and hits.
I have a button that will reset all pages to zero and next to each page listing I have a reset button that will reset each page individually. This all was using a text file but now I am swtching to mysql database. I have coded the "RESET ALL" button to work but can not get the individual page buttons to work.
the processing code is:
if($_POST[ind_reset]) {
$ind_reset = $_POST[ind_reset];
mysql_connect("server", "username", "password") or die(mysql_error());
mysql_select_db("database") or die(mysql_error());
$sql = 'UPDATE counters SET Hits =\'0\' WHERE Page = \'$ind_reset\';';
}
and the html form code is a string:
$page_reset = "<form id='Reset' action='counter_update.php' method='post'>
<button type='submit' name='ind_reset' value='$formPage'>RESET</button>
</form>";
Let's start with the first thing:
if($_POST[ind_reset]) {
should be
if($_POST['ind_reset']) {
It works without quotes because PHP is silently correcting your error. If you turned error reporting to E_ALL, you would get to see the error message.
One thing that you need to consider is that you can never trust POST data to be what you think it's supposed to be. Maybe you put in a typo. Maybe a hacker is sending you fake POST data. Whichever it is, it will mess up your code if the wrong thing gets put in that database update. For this reason, instead of simply plugging in that POST value into your database, you should have a checker to make sure that the value is a valid one. When I do things like this, I make an array of possible values and use only those values when updating or inserting into the database. Example:
$pages = array('value_on_page'=>'value_put_in_database',
'xyz'=>'thing_in_database_2');
//the valid things to post are either 'value_on_page' or 'xyz',
//but what goes into the database are the values those keys point to
//e.g. if $_POST['ind_reset'] == 'xyz', $ind_reset will be 'thing_in_database_2'
$key = $_POST['ind_reset'];
if(!isset($pages[$key])) {
//if that posted value isn't a key in the array, it's bad
error_log('Invalid posted page'.$key);
} else {
//this is a valid posted page
$ind_reset = $pages[$key];
//** do the database stuff right here in this spot **//
}
Now, for the reason your posted code doesn't work, you are missing the final, crucial part of doing a database query: the part where you actually run the query.
$conn = mysql_connect("server", "username", "password") or error_log(mysql_error());
mysql_select_db("database") or error_log(mysql_error());
$sql = 'UPDATE counters SET Hits =\'0\' WHERE Page = \'$ind_reset\';';
mysql_query($sql, $conn) or error_log(mysql_error());
I hope you have noted that I replaced "die" with "error_log." If you do error_log(mysql_error(), 1, 'youremail#example.com'), it will email it to you. Otherwise, as with in my examples, it gets put into wherever your system's error log file is. You can then have a nice history of your database errors so that, when you inevitably return to StackOverflow with more questions, you can tell us exactly what's been going on. If you use a file, just make sure to either rotate the error log file's name (I name them according to the day's date) or clear it out regularly, or it can get really, really long.
Using the mysqli code you posted in your comment is a better idea than the mysql_* functions, but you don't quite have it correct. The "bind_param" part sticks your variable into the spot where the question mark is. If your variable is a string, you put "s" first, or if it's an integer, you put "i" first, etc. And make sure you close things once you're done with them.
$db = new mysqli("server", "username", "password", "database");
if(!$db->connect_errno) {
$stmt = $db->prepare("UPDATE counters SET Hits = '0' where Page = ?");
$stmt->bind_param('s',$ind_reset); //assuming $ind_reset is a string
if(!$stmt->execute()) {
error_log($stmt->error);
}
$stmt->close();
} else {
error_log($db->connect_error);
}
$db->close();
Related
I was wondering if some one could direct me on the right path to take because every way I have tried has failed or really broken my code. To keep it simple I have page with a dynamically created select box populated with peoples names from a mySQL database its element id is 'insert'. This page also holds the php query
my query on the database works if I hard code a name in but I want to pass it as a variable from the select box. I can't seem to get it to post my variable and return me an id.
heres my query
<?php
function getElementById($id) {
$xpath = new DOMXPath(NEW domDocument);
return $xpath - > query("//*[#id='$id']") - > item(0);
}
$insertName = getElementById('insert');
printf($insertName);
$con = mysqli_connect("localhost", "root", "", "karaoke");
// Check connection
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: ".mysqli_connect_error();
}
$sql = "Select id FROM queue where singer = '$insertName'";
$result = mysqli_query($con, $sql) or die("Bad SQL: $sql");
while ($row = mysqli_fetch_assoc($result)) {
$insertAt = ("{$row['id']}");
printf($insertName);
printf($insertAt);
};
?>
whats the best way to get my variable sent to the script and then return me the answer.
thanks
You can use either the POST or GET form methods to send data from your HTML form to your PHP script. In the form element, you will want to set the action to your PHP script like so: <form action = 'your_php_file.php' method = 'GET or POST'>. This means that when the form is submitted, you can get the data from this PHP file. Then, in your PHP, you will want to use the global variable for either POST or GET (depending on which you have used for the form method) to get the value from the select box. Using this method means you can replace your GetById function and assign the value from the form to the $insertName variable using the superglobals.
Another problem in your code is that you use your PHP variables in your SQL query. This means that your code is open to an SQL injection which could lead to problems such as people getting all of the database info (which is bad for a database storing poorly encrypted/hashed passwords, or even storing them in plain text)or could even lead to your database being deleted. To avoid this, you should use prepared statements and parameters whereby the statement is sent first without the variable and the variable is bound after.
Also, take a look at the links above about POST and GET and also about the PHP global variables which will allow you to get the data from your HTML form. Also, here are some links which explain prepared statements and parameters so that you can write more secure PHP code:
Mysqli prepare statement used to prepare the statement. The use of question marks are as placeholders as you later bind your variables to the query.
Mysqli Bind Param used to add in the variable to the SQL statement after the statement has been prepared which prevents SQL injection.
That's all for now, but be sure to ask any questions you may have and I will try my best to answer them all.
EDIT
ADDED CODE - hopefully will demonstrate what you were after, there are some small changes that may need to be made. There may be some extra code needed to fit in with any other code you have, but this should demonstrate the principle of POST and prepared statements with parameters. Written in OOP as opposed to your procedural as I find it cleaner and easier (personal opinion). If there are any problems integrating this be sure to tell me about any errors or issues/further questions. I too am fairly new to PHP.
<?php
$insertName = $_POST['insert']; // Get the value of the select box which will need to have the attribute 'name = "insert"' by POST
printf($insertName);
$con = new mysqli("localhost", "root", "", "karaoke");
// Check connection
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: ".mysqli_connect_error();
}
$sql = "Select id FROM queue where singer = ?";
$stmt = $con->prepare($sql);
$stmt->bind_param("s", $insertName); //Binds the string insertName to the question mark in the query
$stmt->execute();
while ($row = $stmt->fetch_assoc()) { // Left as was because syntax is different from PDO which I use. Therefore, I am assuming this part is correct.
$insertAt = ("{$row['id']}");
printf($insertName);
printf($insertAt);
};
?>
Have the following code that's executed when a script is ran. (I've just changed the login for display purposes).
<?php
$conn = mysql_connect("localhost", "root", "pw123");
mysql_select_db("test_db", $conn);
$sql = "INSERT INTO test_table (fname)
VALUES ('$fname')";
mysql_query($sql);
mysql_close($conn);
?>
I've edited the code down slightly so it doesn't show every value I'm trying to enter, but essentially, everything is entering as a blank value, or in the case of numerical inputs is defaulting to 0. I can't seem to figure out why this is. The variables are definitely not blank before hand as I've got them out putting on the web page to test as such.
For reference I assign $fname a value when the input box is changed using :
fname = $("#fname").val();
(Posted on behalf of OP):
Solved this myself anyway, instead of executing the MySQL statements in the initial page that user enters data, I moved it to the secondary web page, which opens once a user has submitted their information.
$fname is empty in your script and you need declarate the variable before:
$fname = 'David';
$sql = "INSERT INTO test_table (fname) VALUES ('$fname')";
:)
I'm currently doing a school project and I'm using dreamweaver along with a backend database using phpMyAdmin.
Now, what i need to do is, when I click the button, it will reduce the stock column value in the "products" table by 1.
However there are different products in the table. Shown below:
http://i.stack.imgur.com/vLZXQ.png
So lets say, A user is on the game page for "Destiny" and clicks on the Buy now button, how can i make it reduce the stock level by one, but only for the Destiny record and not for the Fifa 15 column. So Destiny stock becomes 49, but Fifa stays 50. Will i just need to make each button have a different script or?
Currently, I made a button in the page, which links to an action script, but im not sure what sort of code i will be using.
Thank you
xNeyte is giving you some good advice, but it comes across to me that you - Xrin - are completely new to programming database contents with PHP or similar?
So some step by steps:
MYSQL databases should be connected with one of two types of connection - PDO and MySQLi_ . MySQL databases will also always work using the native MySQL but as xNeyte already mentioned - this is deprecated and highly discouraged .
So what you have is you pass your information to the PHP page, so your list of games is on index.php and your working page that will update the number of games ordered would be update.php, in this example.
The Index.php file passes via anchor link and $_GET values (although I highly recommend using a php FORM and $_POST as a better alternative), to the update.php page, which needs to do the following things (in roughly this order) to work:
Update.php
Load a valid database login connection so that the page can communicate with the database
Take the values passed from the original page and check that they are valid.
establish a connection with the database and adjust the values as required.
establish the update above worked and then give the user some feedback
So, step by step we'll go through these parts:
I am going to be a pain and use MySQLi rather than PDO - xNeyte used PDO syntax in his answer to you and that is fully correct and various better than MySQLi, for the sake of clarity and your knowledge of MySQL native, it may be easier to see/understand what's going on with MySQLi.
Part 1:
Connection to the database.
This should be done with Object Orientated - Classes,
class database {
private $dbUser = "";
private $dbPass = ""; //populate these with your values
private $dbName = "";
public $dbLink;
public function __construct() {
$this->dbLink = new mysqli("localhost", $this->dbUser, $this->dbPass, $this->dbName);
}
if (mysqli_connect_errno()) {
exit('Connect failed: '. mysqli_connect_error());
}
if ( ! $this->dbLink )
{
die("Connection Error (" . mysqli_connect_errno() . ") "
. mysqli_connect_error());
mysqli_close($this->dbLink);
}
else
{
$this->dbLink->set_charset("UTF-8");
}
return true;
} //end __construct
} //end class
The whole of the above code block should be in the database.php referenced by xNeyte - this is the class that you call to interact with the database.
So using the above code in the database.php object, you need to call the database object at the top of your code, and then you need to generate an instance of your class:
include "database.php"; ////include file
$dataBase = new database(); ///create new instance of class.
Now When you write $dataBase->dbLink this is a connection to the database. If you do not know your database connection use the details PHPMyAdmin uses, it carries out its tasks in exactly the same way.
Sooo
Part 2:
That is that your database connection is established - now you need to run the update: First off you need to check that the value given is valid:
if (is_numeric($_GET['id']) && $_GET['id'] >0 ){
$id = (int)$_GET['id'];
}
This is simple code to check the value passed from the link is a integer number. Never trust user input.
It is also a good idea never to directly plug in GET and POST values into your SQL statements. Hence I've copied the value across to $id
Part 3:
$sql = "UPDATE <TABLE> SET STOCK = STOCK-1 WHERE Product_ID = ? LIMIT 1";
The table name is your table name, the LIMIT 1 simply ensures this only works on one row, so it will not effect too many stocked games.
That above is the SQL but how to make that work in PHP:
first off, the statement needs to be prepared, then once prepared, the value(s) are plugged into the ? parts (this is MySQLi syntax, PDO has the more useful :name syntax).
So:
include "database.php"; ////include file
$dataBase = new database(); ///create new instance of class.
if (is_numeric($_GET['id']) && $_GET['id'] >0 ){
$id = (int)$_GET['id'];
$sql = "UPDATE <TABLE> SET STOCK = STOCK-1 WHERE Product_id = ? LIMIT 1";
$update = $dataBase->dbLink->prepare($sql);
$update->bind_param("i",$id);
$update->execute();
$counter = $update->affected_rows;
$update->close();
//////gap for later work, see below:
}
else
{
print "Sorry nothing to update";
}
There's probably quite a lot going on here, first off the bind_param method sets the values to plug into the SQL query, replacing the ? with the value of $id. The i indicates it is meant to be an Integer value. Please see http://php.net/manual/en/mysqli-stmt.bind-param.php
The $counter value simply gets a return of the number of affected rows and then something like this can be inserted:
if ($counter > 0 ){
print "Thank you for your order. Stock has been reduced accordingly.";
}
else {
print "Sorry we could not stock your order.";
}
Part 4
And finally if you wish you can then just output the print messages or I tend to put the messages into a SESSION, and then redirect the PHP page back.
I hope this has helped a bit. I would highly recommend if you're not used to the database interactions in this way then either use PDO or MySQLi but do not combine the two, that will cause all sorts of syntax faults. Using MySQLi means that everything you know MySQL can do, is done better with the addition of the letter "i" in the function call. It is also very good for referencing the PHP.net Manual which has an excellent clear detailed examples of how to use each PHP function.
The best is to set a link on each button with the ID of your game (1 for destiny, 2 for Fifa15).
Then your script which the user will launch by clicking will be :
<?php
include('database.php'); // your database connection
if($_GET['id']) {
$id=$_GET['id'];
} else throw new Exception('Invalid parameter');
$statement = myPDO::getInstance->prepare(<<<SQL
UPDATE TABLE
SET STOCK = STOCK-1
WHERE Product_id = :id
SQL
);
$statement->execute(array(":id" => $id));
This script will do the job
I have run into a small problem which I can't seem to figure out.
I am creating an application that when a user clicks a button, depending on which button they click, it will post a number into the database.
There are 9 numbers (0-9) and if they click 0 then 0 gets put into the database, if they click 1 then 1 gets put into the database, etc...
I have an onclick call using JQuery and Ajax to submit the data silently:
$(function(){
$('#1A').click(function(e) {
alert("You clicked 1A");
var poll_ans = 1;
$.ajax
({
url: 'postpoll.php',
data: {"pollAns": poll_ans},
type: 'post',
success: alert("Submitted " + poll_ans)
});
});
});
This works fine, and when I click the DIV with ID 1A I get the alert, and the "Submitted!" alert.
However, it does not post to the SQL Database. When I test the postpoll.php file by itself setting the variables in the URL it seems to load indefinitely.
Here is my code:
postpoll.php
<?php
session_start();
$mysqli=mysqli_connect("***","***","***","***");
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
if(isSet($_POST['pollAns']))
{
$answer=intval($_POST['pollAns']);
$query = "INSERT INTO test VALUES '$answer'";
$result = $mysqli->query($query) or die($mysqli->error.__LINE__);
}
?>
Not sure what the problem is here - I am sure I missed something, and it's probably a simple solution!
Also, a side note - I eventually want to make it where the can only vote once, would the best way to accomplish this to simply set a cookie, then check if that cookie is present before posting? I know they could circumvent this by clearing their cookies, but it's not a problem.
SOLUTION:
It would appear that the culprit was CloudFlare. After checking on the httpd.conf file it showed that the sql connection was timing out. This was due to the fact that I was trying to connect to the DB using the actual URL, which is routed through CloudFlare's servers. In order to get to the actual physical server, I ended up using the IP. You can also add a DNS record that points to the IP and make sure you have it not being routed through CloudFlare.
Suggested Action in the Future: Remember that you are using CloudFlare!
When you establish the connection you name it $con, then you try to query using the variable $mysqli. Change $con to $mysqli when establishing the connection. I also changed VALUE to VALUES and added single brackets around $answer.
<?php
session_start();
$mysqli=mysqli_connect("***","***","***","***"); // Change from $con to $mysqli
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
if(isSet($_POST['pollAns']))
{
$answer=intval($_POST['pollAns']);
$query = "INSERT INTO test VALUES '$answer'"; // Add single brackets around $value and changed VALUE to VALUES
$result = $mysqli->query($query) or die($mysqli->error.__LINE__); // Here you are using $mysqli to perform query
}
?>
Make sure your login credentials are correct. Also you have not properly handled the success and error events in your ajax request and alert the error message you get.
Try "isset" instead of "isSet", also set a session in the if statement. if (isset($_POST['pollAns'])) { $_SESSION['verify'] = "true"; } then echo $_SESSION['verify'] to see if the page is even getting to the sql statement.
See if changing the $mysqli->query($query) to this changes anything: $result = mysqli_query($mysqli, $query); (this shouldn't, I know that both ways work)
Also, a side note - I eventually want to make it where the can only vote once, would the best way to accomplish this to simply set a cookie, then check if that cookie is present before posting? I know they could circumvent this by clearing their cookies, but it's not a problem.
You can check the table first to see if that users IPAddress is listed:
$sq = "select * from test where IPAddr = '".$_SERVER['REMOTE_ADDR']."'";
$qu = mysqli_query($mysqli,$sq);
// if it does then the mysqli_num_rows will return 1 or greater.
if (mysqli_num_rows($qu) == 0) {
$query = "Insert into"...
}
It would appear that the culprit was CloudFlare. After checking on the httpd.conf file it showed that the sql connection was timing out. This was due to the fact that I was trying to connect to the DB using the actual URL, which is routed through CloudFlare's servers. In order to get to the actual physical server, I ended up using the IP. You can also add a DNS record that points to the IP and make sure you have it not being routed through CloudFlare.
Suggested Action in the Future: Remember that you are using CloudFlare!
I'm trying to make a voting system for a database currently records are rendered in php on screen with images for an up or down vote. When clicked they run the php scripts upvote.php or downvote.php respectively, they pass the id value (integer of the record being manipulated.
Currently it works, the scripts increment and decrement the records votes value as intended. I was, however, trying to stop a user doing this multiple times for one record. I was trying to achieve this by using a session and naming it the value of the id and before altering the votes value checking if the session for that id has been set.
I am going to use my 'upvote.php' as my example:
//Upvote Script
//begin session
session_start();
//database connection credentials import
include("../scripts/connection_variables.php");
//connect to mysql or display error
#mysql_connect("$db_host","$db_username","$db_pass") or die ("Could not connect to the database, please try again shortly. If problem persists please refer to help then contact support.");
//select database or or display error
#mysql_select_db("$db_name") or die ("Could not connect to the database, please try again shortly. If problem persists please refer to help then contact support.");
//collect id
$id = $_GET['id'];
//check if user has already voted for this
if(isset($_SESSION[$id])) {
//session has been set for this id, so don't execute the script
exit();
}else{
//set the session
$_SESSION[$id] = "The punniest thing about puns is that they are really punny.";
//increment the votes value
$query = "UPDATE punniest_database SET votes= 1 + votes WHERE id='$id'";
mysql_query($query);
}
The default serializer used for sessions cannot handle numeric-only keys. It also emits a warning message during shutdown, you should see it in your logs (assuming you have logging enabled, look for Unknown).
Older serialize handlers cannot store numeric index nor string index contains special characters
(quote from link below)
You can test it with the following script, save it somewhere and refresh a few times:
<?php
session_start();
$_SESSION[time()] = true;
var_dump($_SESSION);
The most portable solution is prefixing the keys with a static string. Alternatively you can change the serialize handler used for sessions.