I'm writing a plugin which calls an API and uses an email address as part of the authentication.
I'm getting really confused regarding which way round parts of my code should go in terms of variables, and as such keep getting undefined variable errors.
This function outputs a form on a Worpdress admin page and allows the user to input their email address. I wish to sanitise the email after it has been input, then spit back out the sanitised version into the input field.
function dotmailer_options() {
?>
<div class="wrap">
<h2>Dotmailer API information</h2>
<form method="post" action="options.php">
<?php settings_fields( 'settings-group' ); ?>
<?php do_settings_sections( 'settings-group' ); ?>
<label>API key</label><br />
<input type="email" name="apiemail" value="<?php echo $sanitized_email; ?>"><br />
<label>Password</label><br />
<input type="password" name="apipassword" value="<?php echo get_option('apipassword'); ?>"><br />
<p><input type="submit" value="Save" class="button-primary" /></p>
<?php
// Store email field as var
$apiemail = get_option('apiemail');
// Sanitize var
$sanitized_email = filter_var($apiemail, FILTER_SANITIZE_EMAIL);
?>
</form>
</div>
However when I do this I get an "undefined" error actually in the input box.
I understand this is probably because the code to create $sanitized_email runs after the input has called for it, but I can't work out how else I should do this.
Also will having code directly in this function open me up to attacks? I have the following at the top of my plugin code: defined('ABSPATH') or die(); - but I don't know if that is enough.
you will need to use either javascript or ajax for this as php is server code rather than browser code (i.e. it runs on the serverside only) whilst javascript is browser code and can re-act to changes in the browser.
But there is no point in sanitizing at this stage, but you would of course sanitize and validate the form submission $_POST items. If displaying variable information from $_POST or the database to the user, you escape the values before inputting them into html.
You could validate the email using javascript to speed things up for the user if there is an issue..
<script>
function validateEmail() {
var x = document.forms["myForm"]["apiemail"].value;
var atpos = x.indexOf("#");
var dotpos = x.lastIndexOf(".");
if (atpos< 1 || dotpos<atpos+2 || dotpos+2>=x.length) {
document.elements["apiemail"].value = "Invalid email";
return false;
}
}
</script>
and in your form:
<input type="email" name="apiemail" value="" onchange="validateEmail()">
I think the reason you're getting an undefined error is you haven't defined the variable in advance - Try putting…
$sanitized_email = "";
in before your form processing code.
Also, are you using some form of checking if the form has been set or not? You can use a hidden field and check if_isset using php to see if the user has attempted to process the form. Only then would the sanitized variable be needed.
Related
How can I refresh a page with a form on submission pending the outcome of the submitted data and display a result.
e.g I have a page with a form:
<form action="" method="post">
<input type="name" value="" name="name" placeholder="Your Name" />
<input type="button" name="submit" value="submit form "/>
</form>
The engine that handles the form is external, but required in the page:
require_once 'form_engine.php';
form_engine.php checks the input,
$success = "true";
$errorMessage = " ";
$name = $_POST['name'];
if ( $name == '') {
$errorMessage = 'Please enter your name';
$success = false;
}
else (if $success = true) {
// do something with the data
}
The form page contains the result:
<form action="" method="post">
<input type="name" value="" name="name" placeholder="Your Name" />
<input type="button" name="submit" value="submit form "/>
</form>
<p><?php echo $errorMessage; ?></p>
Will the error message get displayed after the form is submitted incorrectly? Or do I have to use a session to store it?
You need something like this:
if (!isset($_POST['name']))
instead of
if ( $name == 'name')
UPDATE
Try this, it should give you the idea:
<?php
$errorMessage = false;
if (isset($_POST['submit'])) {
if (!isset($_POST['name']) || $_POST['name']=='') {
$errorMessage = 'Please enter your name';
}
else {
// do something with the data
echo "Success!!";
}
}
?>
<form method="post">
<input type="name" value="" name="name" placeholder="Your Name" />
<input type="submit" name="submit" />
</form>
<p><?php if ($errorMessage) echo $errorMessage; ?></p>
Note: leaving out the action attribute will just submit the form to the current page
Note 2: The PHP here could very well be stored in another page. Using require() is the same as putting the code directly into the page.
You can use redirect on php side:
header('Location: www.mysite.com/index.php');
You seem to be a little confused in terms of the exact process that occurs in terms of rendering a page, as do some of those commenting. You do not need to use sessions to solve this problem. There is no need to store anything server-side between page requests because the user's browser with retain everything that you need, at least for this situation. My guess is the others took you mentioning an "external engine" and thought that the form would be submitting away to a different site/page.
form loops
Below is a diagram showing a typical form request loop:
You do not have to do this, as coding is as much about personal preference to anything else, but typically people will design their form to submit back to the same URI that generated it — as you seem to be doing in your example, by leaving the action attribute blank. By doing this, as long as you embed everything you wish to pass back to the server side within the form — each time the user submits — that information will be resent and be available in PHP.
Obviously you need to be wary of what information might constitute as sensitive, as this data should only ever be written into markup if your requests are protected by HTTPS/SSL. You should also filter/escape any user input to prevent markup injection into your site. You can prevent many problems by using htmlentities, however this can cause issues depending on the values you are trying to capture from the user. Because you are using double quoted HTML attributes (the right way to do them ;) I have not set the ENT_QUOTES option.
back to the point
So in the above loop the user will be shown the form for the first time, and after any subsequent submit, which means that each time your PHP notices that there is an error you can just add your message into the page flow. The trick with this kind of system is what exactly do you do once the form is fully complete. To get out of the loop most people will use a header location call:
<?php
require_once 'form_engine.php';
$name = !empty($_POST['name']) ? trim($_POST['name']) : '';
$name = htmlentities($name);
if ( $success ) {
header('location: next-step.php');
exit;
}
?>
<form action="" method="post">
<input type="name" value="<?php echo $name; ?>" name="name" placeholder="Your Name" />
<input type="button" name="submit" value="submit form "/>
</form>
<?php
if ( $errorMessage ) {
echo "<p>$errorMessage</p>";
}
?>
form engine repairs
You should also rectify your form_engine.php as per my comments above and Shekhar Joshi's answer, although I would keep the header code outside of your engine logic, and leave that decision to the code that requires in the engine — as the above does.
may be, you are looking for this! the header() method.
$success = true;
$errorMessage = " ";
$name = $_POST['name'];
if(isset($_POST['name'])) {
if ( $_POST['name'] == '') {
$errorMessage = 'Please enter your name';
$success = false;
header('Location: www.something.com/some.php');
}
else if ($success == true) {
// do something with the data
}
}
So here's my full code
<!DOCTYPE html>
<html>
<body>
<h1>Encrypt</h1>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
Enter word to encrypt<input type="text" name="in">
<input type="submit">
<hr>
</form>
<h1>Decrypt</h1>
<form>
Enter word to decrypt<input type="text" name="out">
<input type="submit">
<hr>
</form>
</body>
</html>
<?php
$encrypt = $_POST['in'];
?>
And here's the error I get
Notice: Undefined index: in in /Users/idrisk/Colourity/si/index.php on line 20
Line 20 is $encrypt = $_POST['in']; and I don't see what I'm doing wrong with it. Any ideas?
As a general practice for forms in php, always check if the submit button has been clicked.
First name your submit button:
<input type="submit" name="submit">
then further in your php:
if (isset($_POST['submit'])) {
// do your stuff, eg...
$encrypt = $_POST['in'];
}
EDIT #1: Added to that, you seem to have 2 forms and 2 submit buttons. I suggest you keep only one form, and one submit button (remove the 2nd form element and submit button).
If you really need 2 forms, name your submit buttons differently and then you can call them separately.
<input type="submit" name="submit-in">
<!-- ... -->
<input type="submit" name="submit-out">
<?php // ...
if (isset($_POST['submit-in'])) {
// do your stuff, eg...
$encrypt = $_POST['in'];
}
if (isset($_POST['submit-out'])) {
// do your stuff, eg...
$dencrypt = $_POST['out'];
}
EDIT #2: If you want to echo stuff posted in your form, make sure you do the form submission checking and variable setting before the form and then echo the variable after the form (or wherever you want).
you need to first check if the form has been sent, if it hasn't then $_POST['in'] does not yet exist thus throwing the error
May be nothing but you called a php script after closing the form /form, the body /body and then then the HTML /html
replace this code $encrypt = $_POST['in']; by this $encrypt = #$_POST['in'];
this is an error on client server when you upload this file on remote server you will not saw this. use # sign on the client server when you saw this error in future.
I want to use back option on php without losing the form data.
I've tried this way;
if ($username==""){
echo 'Please fill. <input type="button" value="Back" onClick="history.back()">';
} else{
$doaction;
}
And this way;
$url= $_SERVER['HTTP_REFERER'];
if ($username==""){
echo "Please fill.";
header("refresh: 2; url=$url");
}
else{
$doaction;
}
On both ways I lose my data. How can I make this better?
This worked for me and using ob_start(); (in PHP below) needs to be included, otherwise it will throw an error, such as:
PHP Warning: Cannot modify header information - headers already sent by (output started)
Use the following exactly as shown, then modify to suit later.
Using Sessions is a way to achieve this. Each field will re-appear in the input boxes, if they were filled.
HTML form (form.php)
<?php
session_start();
?>
<form method="post" action="submitted.php">
<p>
<label for='name'>Your Name:</label>
<br>
<input type="text" name="username" value="<?php echo isset($_SESSION['username']) ? $_SESSION['username'] : '' ?>">
</p>
<p>
<label for='name'>Email:</label>
<br>
<input type="text" name="email" value="<?php echo isset($_SESSION['email']) ? $_SESSION['email'] : '' ?>">
</p>
<input type="submit" name="submit" value="Submit">
<br>
</form>
PHP (submitted.php)
<?php
ob_start();
session_start();
$_SESSION['username'] = $_POST['username'];
$_SESSION['email'] = $_POST['email'];
$url= $_SERVER['HTTP_REFERER'];
$username=$_POST['username'];
$email=$_POST['email'];
// use this one below, if you want to check more than one field
// if (empty($_POST['username']) || empty($_POST['email']) ){
if (empty($_POST['username'])){
echo "Fill in all fields.";
header("refresh: 2; url=$url");
}
else{
echo "OK, redirecting back to show fields are showing, or not.";
header("refresh: 2; url=$url");
}
Your approach reloads the formular, so the webserver will send a clean form to the client. If you want a prefilled form you will have to use a PHP script which knows the formerly filled in values and creates a prefilled form.
In the code you have used, (assuming you have a form further up) there is no data being passed between the pages because nothing is telling the script to transfer the data between that page and it's destination.
In your first example, history.back() simply tells the browser to go back to the last page viewed before the current one. In your second example, your header line essentially just tells the browser to go back to the previous page after two seconds.
To keep data between page transfers, without any further knowledge of what you're doing, I would suggest using JavaScript to fetch your form data and pass it into a URL used in a window.location call (forming a GET request with your form data in it), OR by using javascript to set a cookie containing the data input before you tell the browser to switch page.
In the first solution, you could then use php's $_GET global to access your form data.
In the second solution, you could use javascript to re-populate the form on page load (or at will)
I'm trying to execute a PHP function in the same page after the user enters a text and presses a submit button.
The first I think of is using forms. When the user submits a form, a PHP function will be executed in the same page. The user will not be directed to another page. The processing will be done and displayed in the same page (without reloading).
Here is what I reach to:
In the test.php file:
<form action="test.php" method="post">
<input type="text" name="user" placeholder="enter a text" />
<input type="submit" value="submit" onclick="test()" />
</form>
The PHP code [ test() function ] is in the same file also:
<?php
function test() {
echo $_POST["user"]; // Just an example of processing
}
?>
However, I still getting a problem! Does anyone have an idea?
This cannot be done in the fashion you are talking about. PHP is server-side while the form exists on the client-side. You will need to look into using JavaScript and/or Ajax if you don't want to refresh the page.
test.php
<form action="javascript:void(0);" method="post">
<input type="text" name="user" placeholder="enter a text" />
<input type="submit" value="submit" />
</form>
<script type="text/javascript">
$("form").submit(function(){
var str = $(this).serialize();
$.ajax('getResult.php', str, function(result){
alert(result); // The result variable will contain any text echoed by getResult.php
}
return(false);
});
</script>
It will call getResult.php and pass the serialized form to it so the PHP can read those values. Anything getResult.php echos will be returned to the JavaScript function in the result variable back on test.php and (in this case) shown in an alert box.
getResult.php
<?php
echo "The name you typed is: " . $_REQUEST['user'];
?>
NOTE
This example uses jQuery, a third-party JavaScript wrapper. I suggest you first develop a better understanding of how these web technologies work together before complicating things for yourself further.
You have a big misunderstanding of how the web works.
Basically, things happen this way:
User (well, the browser) requests test.php from your server
On the server, test.php runs, everything inside is executed, and a resulting HTML page (which includes your form) will be sent back to browser
The browser displays the form, the user can interact with it.
The user submits the form (to the URL defined in action, which is the same file in this case), so everything starts from the beginning (except the data in the form will also be sent). New request to the server, PHP runs, etc. That means the page will be refreshed.
You were trying to invoke test() from your onclick attribute. This technique is used to run a client-side script, which is in most cases Javascript (code will run on the user's browser). That has nothing to do with PHP, which is server-side, resides on your server and will only run if a request comes in. Please read Client-side Versus Server-side Coding for example.
If you want to do something without causing a page refresh, you have to use Javascript to send a request in the background to the server, let PHP do what it needs to do, and receive an answer from it. This technique is basically called AJAX, and you can find lots of great resources on it using Google (like Mozilla's amazing tutorial).
Here is a full php script to do what you're describing, though pointless. You need to read up on server-side vs. client-side. PHP can't run on the client-side, you have to use javascript to interact with the server, or put up with a page refresh. If you can't understand that, there is no way you'll be able to use my code (or anyone else's) to your benefit.
The following code performs AJAX call without jQuery, and calls the same script to stream XML to the AJAX. It then inserts your username and a <br/> in a div below the user box.
Please go back to learning the basics before trying to pursue something as advanced as AJAX. You'll only be confusing yourself in the end and potentially wasting other people's money.
<?php
function test() {
header("Content-Type: text/xml");
echo "<?xml version=\"1.0\" standalone=\"yes\"?><user>".$_GET["user"]."</user>"; //output an xml document.
}
if(isset($_GET["user"])){
test();
} else {
?><html>
<head>
<title>Test</title>
<script type="text/javascript">
function do_ajax() {
if(window.XMLHttpRequest){
xmlhttp=new XMLHttpRequest();
} else {
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
var xmlDoc = xmlhttp.responseXML;
data=xmlDoc.getElementsByTagName("user")[0].childNodes[0].nodeValue;
mydiv = document.getElementById("Test");
mydiv.appendChild(document.createTextNode(data));
mydiv.appendChild(document.createElement("br"));
}
}
xmlhttp.open("GET","<?php echo $_SERVER["PHP_SELF"]; ?>?user="+document.getElementById('username').value,true);
xmlhttp.send();
}
</script>
</head>
<body>
<form action="test.php" method="post">
<input type="text" name="user" placeholder="enter a text" id="username"/>
<input type="button" value="submit" onclick="do_ajax()" />
</form>
<div id="Test"></div>
</body>
</html><?php } ?>
Without reloading, using HTML and PHP only it is not possible, but this can be very similar to what you want, but you have to reload:
<?php
function test() {
echo $_POST["user"];
}
if (isset($_POST[])) { // If it is the first time, it does nothing
test();
}
?>
<form action="test.php" method="post">
<input type="text" name="user" placeholder="enter a text" />
<input type="submit" value="submit" onclick="test()" />
</form>
Use SAJAX or switch to JavaScript
Sajax is an open source tool to make
programming websites using the Ajax
framework — also known as
XMLHTTPRequest or remote scripting —
as easy as possible. Sajax makes it
easy to call PHP, Perl or Python
functions from your webpages via
JavaScript without performing a
browser refresh.
That's now how PHP works. test() will execute when the page is loaded, not when the submit button is clicked.
To do this sort of thing, you have to have the onclick attribute do an AJAX call to a PHP file.
in case you don't want to use Ajax , and want your page to reload .
<?php
if(isset($_POST['user']) {
echo $_POST["user"]; //just an example of processing
}
?>
Take a look at this example:
<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
<?php
// define variables and set to empty values
$name = $email = $gender = $comment = $website = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$name = test_input($_POST["name"]);
$email = test_input($_POST["email"]);
$website = test_input($_POST["website"]);
$comment = test_input($_POST["comment"]);
$gender = test_input($_POST["gender"]);
}
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
?>
<h2>PHP Form Validation Example</h2>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
Name: <input type="text" name="name">
<br><br>
E-mail: <input type="text" name="email">
<br><br>
Website: <input type="text" name="website">
<br><br>
Comment: <textarea name="comment" rows="5" cols="40"></textarea>
<br><br>
Gender:
<input type="radio" name="gender" value="female">Female
<input type="radio" name="gender" value="male">Male
<br><br>
<input type="submit" name="submit" value="Submit">
</form>
<?php
echo "<h2>Your Input:</h2>";
echo $name;
echo "<br>";
echo $email;
echo "<br>";
echo $website;
echo "<br>";
echo $comment;
echo "<br>";
echo $gender;
?>
</body>
</html>
You can submit the form without refreshing the page, but to my knowledge it is impossible without using a JavaScript/Ajax call to a PHP script on your server. The following example uses the jQuery JavaScript library.
HTML
<form method = 'post' action = '' id = 'theForm'>
...
</form>
JavaScript
$(function() {
$("#theForm").submit(function() {
var data = "a=5&b=6&c=7";
$.ajax({
url: "path/to/php/file.php",
data: data,
success: function(html) {
.. anything you want to do upon success here ..
alert(html); // alert the output from the PHP Script
}
});
return false;
});
});
Upon submission, the anonymous Javascript function will be called, which simply sends a request to your PHP file (which will need to be in a separate file, btw). The data above needs to be a URL-encoded query string that you want to send to the PHP file (basically all of the current values of the form fields). These will appear to your server-side PHP script in the $_GET super global. An example is below.
var data = "a=5&b=6&c=7";
If that is your data string, then the PHP script will see this as:
echo($_GET['a']); // 5
echo($_GET['b']); // 6
echo($_GET['c']); // 7
You, however, will need to construct the data from the form fields as they exist for your form, such as:
var data = "user=" + $("#user").val();
(You will need to tag each form field with an 'id', the above id is 'user'.)
After the PHP script runs, the success function is called, and any and all output produced by the PHP script will be stored in the variable html.
...
success: function(html) {
alert(html);
}
...
This is the better way that I use to create submit without loading in a form.
You can use some CSS to stylise the iframe the way you want.
A php result will be loaded into the iframe.
<form method="post" action="test.php" target="view">
<input type="text" name="anyname" palceholder="Enter your name"/>
<input type="submit" name="submit" value="submit"/>
</form>
<iframe name="view" frameborder="0" style="width:100%">
</iframe>
I am trying to create a validate-email javascript and get it working with forms and PHP. Of coures, some problems...
As you can see in my form, I did define "post" as the method. But I can only retreive the data as if it was a get method. It was working before I started to add the e-mail verification script and adopt the code to it.
If the e-mail is incorrect, I do return false. Isn't the point that the request to the test.php (defined in action) should not be executed? As it is now, the page is accessed even if I return false.
Depending on the answers to the questions above, do I need to submit the form from the Javascript if the e-mail is verified ok?
javascript:
function isValidEmail() {
regExp = /^[a-zA-Z]+([_\.-]?[a-zA-Z0-9]+)*#[a-zA-Z0-9]+([\.-]?[a-zA-Z0-9]+)*(\.[a-zA-Z]{2,4})+$/;
if(document.subscribe.email1.value.search(regExp) == -1){
alert(document.subscribe.email1.value + " Incorrect email address");
return false;
}
//document.subscribeForm.submit();
return true;
}
php:
<?php
echo $_POST['email1'];
$mysqli = mysqli_connect("localhost", "root", "", "test", "3306");
$result = mysqli_query($mysqli, "SELECT email, id, subscriber, subscribed_date FROM `user` u;");
while($row = mysqli_fetch_array($result, MYSQLI_ASSOC)){
foreach($row as $key => $value){
echo "$key = $value<BR/>";
}
}
mysqli_free_result($result);
mysqli_close($mysqli);
?>
html:
<div id="subscribe">
<form action="test.php" name="subscribe" method=post">
<p id="formlabel">E-mail</p> <input type="text" name="email1">
<br>
<p id="formlabel">Repeat e-mail</p> <input type="text" name="email2"> <br/>
<input type="submit" value="Subscribe" onclick="isValidEmail()">
</form>
<input type="submit" value="Subscribe" onclick="isValidEmail()">
This executes isValidEmail() and then throws away the result. The onclick itself returns undefined and the submission is not prevented.
You can say onclick="return isValidEmail()". However:
Put validation/submission stuff on form onsubmit, not input click, to ensure it is always called for all types of form submission.
Better to avoid inline event handlers.
You missed a " in your form's method attribute, which is presumably why it was defaulting back to get.
so:
<form id="subscribe" method="post" action="test.php">
...
</form>
<script type="text/javascript>
document.getElementById('subscribe').onsubmit= function() {
if (!this.elements.email1.value.match(/^[^#]+#[^#]+$/) {
alert('Please enter an e-mail address');
return false;
}
if (this.elements.email1.value!=this.elements.email2.value) {
alert('E-mail addresses do not match');
return false;
}
return true;
}
</script>
I replaced the regexp with a trivial one, because the expression you're currently using is bogus and will deny many valid e-mail addresses. Turning customers away because their e-mail address doesn't fit your conception of what an e-mail address is sucks.
‘Validating’ e-mail addresses correctly with regex is absurdly difficult. Better to include only a trivial check for obviously-malformed strings like the above. If you need to really check the e-mail address, you will have to actually try to send a mail to it, or at least try to lookup the domain name part of the address for an MXer.
See this question for discussion.
you should attach the function to the form's onsubmit event:
<form action="test.php" name="subscribe" method="post" onsubmit="isValidEmail()">
where you can stop the event returning false.
Also, you made a typo in method=post", that's why it doesn't get submitted as POST data.