Status:
Apprentice.
My PHP knowledge:
Beginner level.
What I am trying to achieve with my PHP code:
Update the health bar input when ever the user clicks on the submit button.
<form>
<input type="submit" value="Attack">
</form>
So if the condition is true and the post has been done then I want to subtract 25 from the variable health which is then equal to another variable named input.
The problem:
I cant figure out why the health is not updating and how to save the updated value even if the user refreshes and then substracting 25 with the updated health everytime the user clicks on "attack".
What I tried:
Apart from doing some PHP research about Session_start() im not sure how to use it in this context. Im not even entirely sure why my conditional is faulty. I get no error messages what so ever but when I remove my if statement and echo the my bar variable then it doesnt work either as I dont get any number at all, which of course makes me suspect that my math is not working.
<?php
$health = 100;
$input = "";
$bar = '<div>' . $health . $input . '%' . '</div>' . '<div>' . 'Stamina' . '</div>';
echo $bar;
if (isset($_POST['submit'])) {
$health - 25 == $input;
echo $bar;
}
?>
Question:
Why does'nt my value of health / input update? How can I save the session and substract from the new variable the next time an attack is made?
Your PHP is stateless so it has no record of what health was - it's simply reset to 100 every time.
You need to either use sessions, or simply pass back in the value of health each time:
<?php
$health = (isset($_REQUEST['health']) ? (int) $_REQUEST['health'] : 100);
if (isset($_REQUEST['submit'])) {
$health = $health - 25;
}
$input = "";
$bar = '<div>' . $health . $input . '%' . '</div>' . '<div>' . 'Stamina' . '</div>';
echo $bar;
?>
<form action="attack.php" method="post">
<input type="submit" name="submit" value="Attack">
<input type="hidden" name="health" value="<?php echo $health; ?>">
</form>
A couple of other points:
1) I'm not sure what the significance of $input is
2) You should really include a method in your form tag of either get or post - in the PHP I've used I have referenced $_REQUEST which features the values of both $_GET and $_POST
3) Notice I cast the value of $_REQUEST['health'] to an integer because this is output in the hidden HTML field and this helps to avoid XSS exploits.
If you want the health variable to carry over on to other pages or scripts then you might prefer to use a session. Revised code as follows:
<?php
session_start();
$health = (isset($_SESSION['health']) ? $_SESSION['health'] : 100);
if (isset($_REQUEST['submit'])) {
$health = $health - 25;
$_SESSION['health'] = $health;
}
$input = "";
$bar = '<div>' . $health . $input . '%' . '</div>' . '<div>' . 'Stamina' . '</div>';
echo $bar;
?>
<form action="attack.php" method="post">
<input type="submit" name="submit" value="Attack">
</form>
One final comment is that using the session method a user cannot tamper with their own health score. Whereas using the hidden input method the user could potentially change the value of the field and tamper with their health score if they had the technical know-how.
change the form to the form below -
<form action='' method='POST'>
<input type="submit" name='submit1' value="Attack">
</form>
Then you can do -
if (isset($_POST['submit1']))
{
echo "button was pressed";
/// do other stuff.....
}
Define your form like:
<form method="POST">
That might do the trick. And you might need an hidden input field for the current health.
Firstly, forms default to a GET method if omitted.
Therefore, you need to specify it in your form tag
method="post"
Then your conditional statement will fail, since the submit input doesn't have the name attribute.
Add name="submit" to it.
Then this $health - 25 == $input; that doesn't make any sense and I don't know what you're trying to do here.
As stated in another answer by Mr Carrot, you'd want to use $health = $health - 25;
I'll let you look through the answers given, but this gives you a good indication as to what's going on.
Using error reporting would have signaled notices.
Add error reporting to the top of your file(s) which will help find errors.
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
// rest of your code
Sidenote: Displaying errors should only be done in staging, and never production.
Related
I have a minor problem. When I use this code:
<!DOCTYPE HTML>
<html>
<head>
<title>Declare Nerf War!</title>
</head>
<body>
<?php
$form="<center><form action='decwargen.php' method='POST'>
Your Name: <input type='text' name='yname' placeholder='John Doe'><br>
Opponent's Name: <input type='text' name='oname' placeholder='Jane Doe'><br>
Why? <input type='text' name='why' placeholder='for stealing my stuff'><br>
Date of war: <input type='text' name='dwar' placeholder='10/11/13'><br>
Time of war: <input type='text' name='twar' placeholder='10:56 PM'><br>
Created on: <input type='text name='crtd' placeholder='10/10/13'><br>
<input type='submit' name='subbut' value='Submit'></center>
</form>";
$ok = $_POST ['subbut'];
if($ok){
$yname = $_POST ['yname'];
$oname = $_POST ['oname'];
$why = $_POST ['why'];
$dwar = $_POST ['dwar'];
$twar = $_POST ['twar'];
$created = $_POST ['crtd'];
echo("<center><h1>Declaration of war</h1><br><p contenteditable='true'>I, " . $yname . " declare war on " . $oname . " for/because " . $why . ". This will happen on " . $dwar . " at " . $twar . ".<br>Created on" . $created);
} else echo($form);
?>
</body>
</html>
The web browser says:
Notice: Undefined index: subbut in /Applications/MAMP/htdocs/decwargen.php on line 17
when I first go to the page, then
Notice: Undefined index: crtd in /Applications/MAMP/htdocs/decwargen.php on line 24
when I enter data. Can anyone please help?
Change your
<input type='text name='crtd' placeholder='10/10/13'>
-------^ quote not closed properly
to
<input type='text' name='crtd' placeholder='10/10/13'>
From your recent question edit, also make the following change:
Replace your
$ok = $_POST ['subbut'];
if($ok){
to
if(isset($_POST ['subbut']))
{
As an additional safety tip, DO NOT EVER print something without sanitizing it.
-- edit --
When writing any code that can accept user submitted content, you need to bear in mind that user content can never be trusted. Malicious users can submit specially crafted data that could allow them to gain access to your application, the end user's computer, or much more.
One way to reduce (or control) the threat is to do the following:
Validate the data: Make sure that the type of data matches what you expect for a field (number, text, email, etc).
Sanitize the data: Perform some cleanup to remove undesirable things contained in the data.
Validate the legitimacy of the form (Optional but recommended): If applicable, ensure that the code is being submitted by a form that was truly generated by your web site and use CAPTCHA to prevent automated content submission when possible.
Escape the data: When displaying the data or passing it on to other systems (database, api call, etc.), make sure that you escape the received data so that it does not negatively after those systems.
You can get more information about doing these things and much more using a simple Google search. You can also look at PHP Sanitize filters
Now going back to the actual code that was used in the original question.
I have taken the liberty to print the form below the declaration of war so that you can declare even more wars if you wish.
The code looks like the following ...
<!DOCTYPE HTML>
<html>
<head>
<title>Declare Nerf War!</title>
</head>
<body>
<?php
$form="<center><form action='decwargen.php' method='POST'>
Your Name: <input type='text' name='yname' placeholder='John Doe'><br>
Opponent's Name: <input type='text' name='oname' placeholder='Jane Doe'><br>
Why? <input type='text' name='why' placeholder='for stealing my stuff'><br>
Date of war: <input type='text' name='dwar' placeholder='10/11/13'><br>
Time of war: <input type='text' name='twar' placeholder='10:56 PM'><br>
Created on: <input type='text' name='crtd' placeholder='10/10/13'><br>
<input type='submit' name='subbut' value='Submit'></center>
</form>";
$ok = $_POST['subbut'] ?? false;
if($ok){
$yname = $_POST['yname'];
$oname = $_POST['oname'];
$why = $_POST['why'];
$dwar = $_POST['dwar'];
$twar = $_POST['twar'];
$created = $_POST['crtd'];
echo "<center><h1>Declaration of war</h1><br><p contenteditable='true'>I, " . $yname . " declare war on " . $oname . " for/because " . $why . ". This will happen on " . $dwar . " at " . $twar . ".<br>Created on " . $created;
};
?>
<hr>
<?php echo $form; ?>
</body>
</html>
I realize that the question was originally asked in 2013. Still, I am going to solve the Notice: Undefined index: subbut ... using a more modern PHP feature.
I would replace ...
<?php
$ok = $_POST ['subbut'];
with ...
<?php
$ok = $_POST['subbut'] ?? false;
You can find out more about the new PHP Null coalescing operator (the Elvis operator ??) at http://php.net/manual/en/language.operators.comparison.php#example-105
When you submit and declaration of war, you will have something similar to the following image ...
HTML Injection
Now, you are going to see what happens with your form when someone performs a simple HTML injection on your page.
Instead of submitting the name as John Doe, I am going to submit John Doe</form><form action="http://example.com" target="_blank"><input value="You got hacked">
The result is visible on the following image ...
If you try to submit another declaration, you will notice that the form will be submitted to the example.com domain. That's because:
The </form> tag will try to close the current form in case the submitted value was printed inside a form. If there was no form to close off, than the tag will be invalid and the browser will ignore it.
Then, my new form is added using <form action="http://example.com" target="_blank">. Browsers will usually reject a nested form tag. Because of this, my form will take over the next form by invalidating its opening tag.
Someone could argue by saying that the original example was not printing a form. Sure. But that does not change what I am trying to convey.
Instead of creating a form, I could have injected a tag what would load an elaborate Javascript application that would then run on your site's domain and do whatever is possible using Javascript. I could have also added an iframe or other things.
The bottom line is, do not use or directly print anything submitted to your script. Heck, you cannot even trust content coming for your own database because you don't know if it's been altered by someone else. You still need do perform some clean up to guard against XSS and CSRF using the data.
When you first go to the page
$_POST['subbut']
Does not exist. It only exists once the form has been posted. In order to avoid this you need to use isset. For example use the following code instead
if(isset($_POST ['subbut'])){
$yname = $_POST ['yname'];
$oname = $_POST ['oname'];
$why = $_POST ['why'];
$dwar = $_POST ['dwar'];
$twar = $_POST ['twar'];
$created = $_POST ['crtd'];
echo("<center><h1>Declaration of war</h1><br><p contenteditable='true'>I, " . $yname . " declare war on " . $oname . " for/because " . $why . ". This will happen on " . $dwar . " at " . $twar . ".<br>Created on" . $created);
} else echo($form);
Also change this line
Created on: <input type='text name='crtd' placeholder='10/10/13'><br>
to this
Created on: <input type='text' name='crtd' placeholder='10/10/13'><br>
You have a quote mistake. Try to change
type='text name='crtd'
to
type='text' name='crtd'
I have been working on a coding problem for some pages I inherited where the values of two variables are not showing up in the URL of the next page.
The code written by the author, which is probably quite old is
"completeyourorder.php?p=" . $p . "&service=" . $service;
as far as I can tell from my research there should be at least an echo in there
"completeyourorder.php?p=" echo . $p . "&service=" . $service;
or maybe I am missing much more than that.
I'd be grateful for a bit of education on this as I am a newbie and have not been able to find an answer despite many hours of tickering and reading.
Thanks
UPDATE:
PAGE 1
<form action="send-order.php" method="post">
<p>Name<br /><input name="clientname" value="<?echo $clientname;?>" type="text" style="width: 350px;" /></p>
<p><br /><input type="hidden" name="service" value="<?
echo $_GET['service'];
?>" />
<input type="hidden" name="p" value="<?
echo $_GET['p'];
?>"
/>
<input type="submit" value="Order now" /></p>
</form>
PAGE 2
$go = "completeyourorder.php?p=" . $p . "&service=" . $service;
return header("location:$go");
Let me know if you need anything more
SOLVED:
Brilliant thanks it works! I see now that my error was assuming that I could use the variable values in the location: completeyourorder..... on page 2 without having used $_POST earlier in the code on the same page. Thanks to everyone!
What you have shown here is just building part of a string. In php the period is the concatenation operator so it ties two strings together. You need an echo, print, header, or variable assignment on the whole string to make it do something. In that other script then you could get at the variables as
$p = $_REQUEST['p'];
$service = $_REQUEST['service'];
EDIT: upon seeing the update what it is doing is using the header to redirect the script to a new page
You recently asked a similar question regarding $_GET vars.
In this case, it looks like you're building a string to echo out in a link or something. So perhaps this is the what you may be experiencing: (only an example)
<?php
if(isset($_GET['p']))
{
$p = $_GET['p'];
}
if(isset($_GET['service']))
{
$service = $_GET['service'];
}
//defaults in case they are not set
$p or $p = 1; //assuming p = page
$service or $service = 'laundry'; //since I don't know what service refers to
$link = "completeyourorder.php?p=" . $p . "&service=" . $service;
?>
string to click on
Where in this example you can see that you are expecting to build the $link var based on the $_GET vars "p" and "service" and if they do not exist, default to the standard set of page 1 and service of "laundry"
Obviously you would tailor this to fit your needs, but you will need to provide more info for a better, more relevant answer.
EDIT
As per your edit, the basic answer is that your form should be populating the vars for $p and $service, so the revised code would be like this:
<?php
if(isset($_POST['p']) && isset($_POST['service']))
{
$p = $_POST['p'];
$service = $_POST['service'];
// do some kind of post processing here
// possibly do some kind of filtering to ensure the post vars are sanitized
header("location: completeyourorder.php?p=" . $p . "&service=" . $service);
exit;
}
?>
isset is not necessary on both, but you can change that to reflect your preferred choice for verifying post data. Some just do:
if(!empty($_POST))
$i=0;
while (db_data) {
$i++;
echo '<input type="checkbox" name="v['.$i.']" value="'.$url.'"';
if ($v[$i]) {
echo ' checked';
$s .= $url;
}
echo '/>';
}
I have the above array of checkboxes. It worked on my pc, but not on the server; it seems like the confusing part is on $v[$i].
$v is not defined, but sure used no where else. the problem is my checkbox selection never restored, and code never get into the if statement.
however, if i add the following, i can see the value. just the checkbox lost after the processing
$v=$_POST['v'];
while (list ($key,$val) = #each ($v)) {
$x .= ' 11*'.$key.'-'.$val.'*22 ';
}
my goal is to preserve the checkbox checked on the form, and i need the $s elsewhere. any solution to replace $v[$i]?
Can anybody help me fix this? Thank you.
The issue seems to be $v = $_POST. If you are just doing that then your conditional statement would need to be
if ($v['v'][$i]) {
///Checkbox
}
or just do $v = $_POST['v'].
Sorry, ignore above as you did mention you did that part. See below.
Here is working code.
<form action="" method="post">
<?php
$v = $_POST['v'];
$i=0;
while ($i < 4) {
$i++;
$url = "test.com/".$i;
echo '<input type="checkbox" name="v['.$i.']" value="'.$url.'"';
if ($v[$i]) {
echo ' checked="checked"';
$s .= $url;
}
echo '/> '.$url.'<br />';
}
?>
<input type="submit" name="submit" value="submit" />
</form>
I left the code pretty much the same to show you where you went wrong, but you should be checking the $_POST variable for exploits before using. If I were doing this as well, I would use a for count, but it's setup as a placeholder for your database code. Make sure that $url gets populated as well.
You could also do away with the $i variable like:
<?php
$v = $_POST['v'];
while (db_data) {
echo '<input type="checkbox" name="v[]" value="'.$url.'"';
if (is_array($v)) {
if (in_array($url,$v)) {
echo ' checked="checked"';
$s .= $url;
}
}
echo '/> '.$url.'<br />';
}
?>
Try to print_r($_POST) and then print_r($v) and see if anything comes up. If the $_POST works, then you know that it is being posted back to the page correctly. Then if the $v is working, then you know you set $v = $_POST correctly. Due to the fact that you don't actually give us any information on the db_data, I assume this is working correctly and displaying all the checkboxes on first load, so as long as it is posted and you are setting the $v variable, it should be working.
A side note is that you should validate the $_POST variables before using, but do that after you get things working.
change
name="v['.$i.']"
to
name="v[]"
the fact that PHP picks that up as an array is a unintended feature of PHP that wasn't intentionally designed. you don't need to set the indexes, just define it as an array.
I'm having difficulty using hidden forms with PHP data. I cannot for the life of me figure out what I'm doing wrong.
My code should
Check to see if an attack succeeded;
If it succeeded, subtract damage from health;
Rewrite the $health variable.
Use the new $health value for the next round.
The problem is, it keeps resetting the health value.
Here is my code (it's set so that the attack always succeeds):
<?php
$health = $_REQUEST["health"];
$attack = rand(10,20);
$defend = rand(1,9);
$damage = rand(1,5);
$health =50;
if ($attack>$defend){
print "<p>Jim hit the robot for $damage.</p>";
$health = $health - $damage;
print "<p>The robot has $health health remaining.</p>";
} else {
print "<p>Jim missed.</p>";
print "<p>The robot has $health health remaining.</p>";
} // end if statement
print <<<HERE
<input type="text"
name="openMonsterHealth"
value="$health">
<input type="hidden"
name="hdnMonsterHealth"
value="$health">
<input type="submit"
value="click to continue">
HERE;
?>
If you want $health to follow you to the next page, use sessions.
PHP Manual on Sessions
Basically, you'd start your pages with
session_start();
if(isset($_SESSION['health'])) {
$health = $_SESSION['health'];
}
else {
//However you normally set health when the user is just starting
}
which would load the health value from the previous page, if you set it like this:
$_SESSION['health'] = $health;
PHP scripts automatically write and close sessions, so you don't have to worry about anything other than creating a variable in the session global array. Just don't forget to start your sessions when you want to retrieve the data in the session array from the previous page. Your users, however, will have to be able to accept cookies.
If you keep using hidden fields, a player could change that information before sending it back to you (plus, they're more trouble to keep track of).
edit:
Your bugs, however, are you're resetting your health to 50 on the 5th line of your code, you're not using the right variable name for health from the request, and you don't have any form tags.
<?php
if(isset($_REQUEST['hdnMonsterHealth']))
$health = $_REQUEST['hdnMonsterHealth'];
else
$health = 50;
$attack = rand(10,20);
$defend = rand(1,9);
$damage = rand(1,5);
if ($attack > $defend) {
print "<p>Jim hit the robot for $damage.</p>";
$health = $health - $damage;
print "<p>The robot has $health health remaining.</p>";
} else {
print "<p>Jim missed.</p>";
print "<p>The robot has $health health remaining.</p>";
} // end if statement
print <<<HERE
<form method="post">
<input type="text"
name="openMonsterHealth"
value="$health">
<input type="hidden"
name="hdnMonsterHealth"
value="$health">
<input type="submit"
value="click to continue">
</form>
HERE;
?>
Edit: Sorry for all of the weirdness, formatting is broken by this block of code, so I had to manually insert every < in the code with <. This code works now, however.
You still have a bug of negative health. I'm not writing your game for you, though.
Sorry, you haven't mentioned what scope your $health variable is. Does it belong to the session, or just for the lifetime of the request?
I'd strongly encourage using session variables, i.e.:
$_SESSION["health"] = $_SESSION["health"] - $_REQUEST["DAMAGE"];
I can't for the life of me find a form that doesn't email the results that you submit.
I'm looking to find a form that I can have users enter simple data that i can then spit back out at them in different arrangements. If they submit First and Last, I'll spit out, amongst other things, FirstLast#domain.com. I'm willing to scrounge the code manually to do this, but I cant find a simple form that would allow me to do this.
Edit: PHP or similar simple languages. I've never touched .NET before.
Form:
<form action="process.php" method="post">
First: <input type="text" name="first" />
Last: <input type="text" name="last" />
<input type="submit" />
</form>
Next page:
<?php
$first = $_POST['first'];
$last = $_POST['last']
echo $first . "." . $last . "#domain.com";
?>
See http://www.w3schools.com/php/php_forms.asp for more examples and explanation
Regardless of how you get it, always remember to never trust user input.
<?php
$sfirst = htmlentities($_POST['first']);
$slast = htmlentities($_POST['last']);
echo $first . "." . $last . "#domain.com";
?>
Also, running a validator on the final result may be helpful. But please don't write your own email address validator.
What language/platform/environment are you working in?
I guess you might be looking for a hosted script or webform (the way that people will host web-to-mail scripts I suppose) but I doubt there would be one out there that does this.
But if you have a specific framework to work in, e.g. PHP or .net, please update the question and let us know which.
Thing that simple doens't even need server-side support.
<form onsubmit="magic(this);return false">
<p><label>First <input name=first/></label>
<p><label>Last <input name=last/></label>
<input type="submit">
<div id="output"></div>
</form>
<script type="text/javascript">
var output = document.getElementById('output');
function toHTML(text)
{
return text.replace(/</g,'<');
}
function magic(form)
{
output.innerHTML = toHTML(form.first.value + form.last.value) + '#domain.com';
}
</script>
If I get your question right, sounds like this might do what you need..
Note: This PHP code doesn't require any knowledge of the fields in the form that submits to it, it just loops through all of the fields, including multiple-choice fields (like checkboxes), and spits out their values.
<?php
// loop through every form field
while( list( $field, $value ) = each( $_POST )) {
// display values
if( is_array( $value )) {
// if checkbox (or other multiple value fields)
while( list( $arrayField, $arrayValue ) = each( $value ) {
echo "<p>" . $arrayValue . "</p>\n";
}
} else {
echo "<p>" . $value . "</p>\n";
}
}
?>