PHP - Merging Form to Show Results on One Page Causing Issues - php

I previously had a HTML file containing a form separately from a PHP file containing the script which actions the form results - this worked perfectly without errors.
The problem with this is that the page would redirect to the PHP script whereas I prefer that the form results are shown on the same page so that the user can "search" again. When adding the PHP script on to the end of my HTML page and thus converting the HTML page to a PHP page, the following issues arise:
1) Error "Notice: Undefined index: product_sku in /my_api.php on line 16" is shown.
2) I added an if statement which will echo the text "Product SKU xxx does not exist in the database." if the variable that contains the results isn't set. This now shows permanently.
Screenshot of the results:
I assume these errors both occur because the form hasn't been submitted yet and therefore the posted form data and script results are not yet set. The results when submitting the form are still correct for both successful and unsuccessful queries, so the question is what do I need to do to do to have these two errors hidden before the form is submitted?
Please see my code below:
<html>
<head>
<title>My API</title>
<link rel="stylesheet" type="text/css" href=/api.css">
</head>
<body>
Enter a product SKU to get the price
<form class="get_price" action="<?php echo $_SERVER['PHP_SELF'];?>" method="post">
<input type="text" name="product_sku">
<input type="submit" class="form_submit">
</form>
</body>
</html>
<?php
/* Call form Submission SKU Field */
$product_sku = $_POST['product_sku'];
/* Variables */
$callbackURL = "Edited";
$temporaryCredentialsRequestURL = "https://ts564737-container.zoeysite.com/oauth/initiate?oauth_callback=" . URLencode($callbackURL);
$adminAuthorizationURL = 'https://ts564737-container.zoeysite.com/admin/oauth_authorize';
$accessTokenRequestURL = 'https://ts564737-container.zoeysite.com/oauth/token';
$URL = 'https://ts564737-container.zoeysite.com';
$apiURL = $URL . '/api/rest';
$consumerKey = 'Edited';
$consumerSecret = 'Edited';
/* Create/Resume Session */
session_start();
if (!isset($_GET['oauth_token']) && isset($_SESSION['state']) && $_SESSION['state'] == 1) {
$_SESSION['state'] = 0;
}
try {
/* Variables */
$authType = ($_SESSION['state'] == 2) ? OAUTH_AUTH_TYPE_AUTHORIZATION : OAUTH_AUTH_TYPE_URI;
$oauthClient = new OAuth($consumerKey, $consumerSecret, OAUTH_SIG_METHOD_HMACSHA1, $authType);
$oauthClient->enableDebug();
if (!isset($_GET['oauth_token']) && !$_SESSION['state']) {
$requestToken = $oauthClient->getRequestToken($temporaryCredentialsRequestURL);
$_SESSION['secret'] = $requestToken['oauth_token_secret'];
$_SESSION['state'] = 1;
header('Location: ' . $adminAuthorizationURL . '?oauth_token=' . $requestToken['oauth_token']);
} else if ($_SESSION['state'] == 1) {
$oauthClient->setToken($_GET['oauth_token'], $_SESSION['secret']);
$accessToken = $oauthClient->getAccessToken($accessTokenRequestURL);
$_SESSION['state'] = 2;
$_SESSION['token'] = $accessToken['oauth_token'];
$_SESSION['secret'] = $accessToken['oauth_token_secret'];
header('Location: ' . $callbackURL);
} else {
$oauthClient->setToken($_SESSION['token'], $_SESSION['secret']);
$resourceURL = "$apiURL/products/?order=entity_id&filter[0][attribute]=sku&filter[0][in][0]=" . $product_sku;
//echo $resourceURL;
//exit;
$oauthClient->fetch($resourceURL, array(), 'GET', array('Content-Type' => 'application/json', 'Accept' => 'application/json'));
$productList = json_decode($oauthClient->getLastResponse());
}
} catch (OAuthException $e) {
echo '<pre>';print_r($e);echo '</pre>';
}
/* Get price of the product SKU */
if ($productList) {
foreach ($productList as $product) {
echo '<br><br>Price of <b>' . $product_sku . '</b> is <span style="color: #ff0000; font-weight: bold;">£' . round($product->price, 2) . '</span>';
}
} else {
echo '<br><br>Product SKU <b>' . $product_sku . '</b> does not exist in the database.';
}
?>
Thank you.

You have a couple options
Rather than move your code to the form (because separating logic and view is a good idea) you could store the results of the query in the session and then redirect back to the form. Make the form a PHP page and then output what is in session for the results.
//Whatever come back from your query even an array
$_SESSION['query_result'] = "...";
//You can redirect by putting
//this at the end of the script
//This url should be what you have in the browser when on the form.
$urlForForm = 'www.sitename.com/products/search';
header('Location: '.$urlForForm);
Then change the html page to a php and have in there
<?php session_start();?>
<!--HTML FORM-->
<?php
//Check that value exists
if(isset($_SESSION['query_result'])){
//If it does output it
echo $_SESSION['query_result'];
//unset it so it does not keep showing up
unset($_SESSION['query_result']);
}
?>
If you want to keep them together as mentioned you could check if the value is set for that index
if(isset($_POST['product_sku'])){//Do stuff with SKU}
Or rather then checking specifically for a value to be set you could use $_SERVER['REQUEST_METHOD']=='POST' as a global check on the output logic. The only way you would have a POST request method is if the form was submitted.
if($_SERVER['REQUEST_METHOD']=='POST'){
//All your form processing and posting code.
//Will only run when form is submitted
}

You can avoid this using the following snippet.
$product_sku = "";
if(isset($_POST['product_sku'])){
$product_sku = $_POST['product_sku'];
}else {
echo "product doesn't exist in the database";
}
This way the error will only be shown when the form is not submitted, once the form is submitted the error will be gone.

Related

Change a page for other users by what a admin selects in a form in PHP

I am stuck with a bit of a problem.
I have to build an application that shows everyone that visits the webserver a message wich sais if there is maintenance or a failure on the server.
Wich of the 2 messages gets shown to the user depends on what the admin sets it to. This is done by clicking one of two buttons on the admin page.
I got it working to the point where if I click one of the two buttons on the admin page it redirects me to the index page and shows the right text.
My problem is that the choice I made is a one time thing and will not be saved.
Meaning that if anyone else visits the site he/she gets to see an empty index page.
I am not allowed to use a database to store the choice i made, so I will have to store the variable somewhere else.
But I have no idea how to save a variable without a database.
My code goes something like this:
Index.php:
if(!session_id()) session_start();
$filename = $_SESSION['filename'];
$page = $_POST['sb'];
// // echo $page;
//
if($page == 'Maintenance')
{
require './pages/index.html';
}
elseif($page == 'Failure')
{
require './pages/fail.html';
}
Admin.php:
if(!session_id()) session_start();
//include("global.php");
$_SESSION['filename'] = $page;
require './functions.php';
$page = $_POST['sb'];
change();
Functions.php:
if(!session_id()) session_start();
$filename = "test";
if(!isset($_SESSION['filename'])) {
$_SESSION['filename'] = $filename;
}
echo '<div class="switch">' .
'<form method="POST" action="../index.php">' .
'<input class="button" type="submit" name="sb" value="Maintenance">' .
'<input class="button" type="submit" name="sb" value="Failure">' .
'</form>' .
'</div>';
}
I would recommend using a txt file as a place to store your data and retrieve it in the index file to display the correct page.
Posting "sb" to txt file on server:
<?php
if($_POST['sb'] != ""){
$file = fopen('sbstore.txt', 'w');
fwrite($file, $_POST['sb']);
fclose($file);
}
?>
Retrieving data from txt file on server:
<?php
if (filesize('sbstore.txt') != 0){
$txt_file = file_get_contents('sbstore.txt');
$sb = $txt_file;
} else {
$sb = "Default";
}
?>

PHP session variable does not survive

Pretty simple setup: When the page is loading, a random session token is generated and saved in $_SESSION["token"]. A Form contains this token in a hidden input field. No problems until this point. I submit the form to the very same page (action="") and then I try to check if the $_SESSION["token"] is equal to the token that has been sent via POST. A variable is changed accordingly, and then I generate a new session token that replaces the old $_SESSION["token"] before the page loads again.
Problem is: The $_SESSION["token"] is changed again the moment the page is called (Before I can compare both SESSION and POST tokens) Therefore, both tokens never match. And I can't figure out WHY it changes. It's not the lines of code I wrote, because these are executed aswell, replacing the random token of unknown origin once again, before the page loads.
INDEX:
<?php
session_start();
date_default_timezone_set("Europe/Berlin");
$BASE_URL = "http://" . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
$form_valid = false;
if (isset($_POST["token"]) && isset($_SESSION["token"])) {
if ($_POST["token"] == $_SESSION["token"]) {
$form_valid = true;
}
}
//Set (new) session token
$token = bin2hex(random_bytes(10));
$_SESSION["token"] = $token;
//Load actual page
include ("/backend/admin.php");
?>
INCLUDED PAGE:
<?php echo "FORM VALID:"; var_dump($form_valid); ?>
<?php if (!isset($_SESSION["admin"]) || !$_SESSION["admin"]) { ?>
<form id="verify" method="POST" action="">
<label>Password</label>
<input type="password" name="access">
<input type="hidden" name="token" value="<?= $_SESSION['token'] ?>">
<input type="submit" value="Senden">
</form>
<?php } else { ?>
...
<?php } ?>
any help is appreciated. thank you.
There was a problem in your logic, session token updates every time regardless the form is submitted is not,
$token = bin2hex(random_bytes(10));
$_SESSION["token"] = $token
Try this,
<?php
session_start();
date_default_timezone_set("Europe/Berlin");
$BASE_URL = "http://" . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
$form_valid = false;
if(empty($_SESSION["token"] )){
$_SESSION["token"]= bin2hex(random_bytes(10));
}
if (isset($_POST["token"]) && isset($_SESSION["token"]))
{
if ($_POST["token"] == $_SESSION["token"]) {
$form_valid = true;
unset($_SESSION["token"]);
}
}
include ("/backend/admin.php");
?>

Strategy to pass data from included PHP file

The following code presents a way that I am currently rendering my pages through index.php. The problem is that I'm not sure how to re-think this so I can pass a page title before the template has been included.
How other way I could do this? This is just my index page, please ask if more code needed.
include($cms->GetTheme() . "/head.php"); This should get the Title information before being included, but I'm not sure how to pass data there from later included page.
include('config/config.inc.php');
$cms = new cms();
if(($_SERVER['REQUEST_METHOD'] === 'GET' || $_SERVER['REQUEST_METHOD'] === 'POST') && !empty($_GET['page'])) {
include($cms->GetTheme() . "/head.php");
$cms->IncludeModule($_GET['page']); <- actual page being included
include($cms->GetTheme() . "/foot.php");
} // end (GET || POST) && GET
else { // just index.php
include($cms->GetTheme() . "/head.php");
foreach($cms->GetModuleList() as $module) {
echo " $module <br />";
}
include($cms->GetTheme() . "/foot.php");
} // end ELSE
Example page being included. The $this->SetTitle($module_name); I would use to set the page title.
<?php
$module_name = 'Log out user';
$module_directory = 'admin';
$this->SetTitle($module_name); // setting page title
if(count(get_required_files()) < 2) {
header('Location: index.php');
}
else {
if(isset($_SESSION['user'])) {
$this->DestroyUser();
echo "You have been logged out! Please navigate to the Login Page.";
}
else {
header('Location: index.php?page=login');
}
}
?>
There are echos all over the place. Try and limit the places where you do that by storing the output, rather than printing it all out straight away.
In your module for example, you could do $this->content = "You have been logged out..."
Then you can change the order of execution:
$cms->IncludeModule($_GET['page']);
include($cms->GetTheme() . "/head.php");
echo $cms->content;
include($cms->GetTheme() . "/foot.php");

redirecting back message

I have a document called editprofile.php and I have another one that is called action.php. when the user submits their info using editprofile.php. the information get POSTed to action.php where I process the information and send it to mysql. After sending it I want to show a message that everything has been successfully changed. I used this :
if $everythingisdone{
$smarty->assign('sucess', 'Your changes have been made');
header('Location: ' . $_SERVER['HTTP_REFERER']);
}
I get redirected to the previous page, but there is no message even though I have this in my editprofile.tpl
{if $sucess}
<div class="sucess">
{$sucess}
</div>
{/if}
how can I assign the message when I redirect back?
you could do:
//custom smarty function to set session flash messages
function smarty_function_set_flash($params, $smarty) {
$flash = "";
if (isset($_SESSION['success'])) {
$flash = $_SESSION['success'];
$_SESSION['success'] = ""; //unset the session
}
return $flash; //return flash message
}
your code
....
if($everythingisdone) {
$_SESSION['success'] = 'Your changes have been made';
header('Location: ' . $_SERVER['HTTP_REFERER']);
}
and view:
{if isset($smarty.session.flash) && $smarty.session.flash != ''}
<div class="sucess">{set_flash}</div>
{/if}
You can't redirect to another page and expect variables to persist. When you call $smarty->assign() that change will persist only for that specific page request and no more, once you redirect its all gone.
You could do this with a GET parameter:
<?php
// action.php
if ($something) {
header ("Location: " . $_SERVER['HTTP_REFERER'] . "?success=1");
die;
}
else {
header ("Location: " . $_SERVER['HTTP_REFERER'] . "?success=0");
die;
}
Then in editprofile.php you could check for that value:
<?php
// editprofile.php
if ($_GET['success'] == '1') {
// yes!
}
else {
// aww :(
}
This would not be necessary if you wouldn't redirect like that. Why not have the form on the editprofile.php and submit it to the same page and check for errors there? Set a flag variable and show an error message if the form did not submit:
<?php
if ($ok) {
$smarty->assign ('form_processed', true);
}
else {
$smarty->assign ('form_processed', false);
}
Then simply use that in your form to check for an error.
Hope this helps

Form redirection with multiple variables

I found a wonderful example on form redirection when there is an error with the form elements. In validation.php the system checks if there is an error and if it's true it redirects the user to the form page.
My question is what if I have more than one form element?
As you see I renamed user_name to app_name and I added a new variable (adtext) so now I get two error messages when both form elements have some error (right now they not equal to a certain word), but I don't know what to do with the $query_string variable so the url would contain the second variable and its value as well.
This is how the url of the form page (adparameters.php) looks like when I click the submit button and there is an error with $appname:
/adparameters.php?appname=aa&error=App%20name%20is%20requiredAd%20text%20is%20required
<?php
# validate.php
$appname = trim($_POST['appname']);
$adtext = trim($_POST['adtext']);
$error = '';
if ($appname != 'myapp') $error = 'App name is required<br />';
if ($adtext != 'mytext') $error = $error . 'Ad text is required<br />';
$query_string = '?appname=' . $appname;
$server_dir = $_SERVER['HTTP_HOST'] . rtrim(dirname($_SERVER['PHP_SELF']), '/\\') . '/';
header('HTTP/1.1 303 See Other');
if ($error != '') {
// Back to register page
$next_page = 'adparameters.php';
// Add error message to the query string
$query_string .= '&error=' . $error;
// This message asks the server to redirect to another page
header('Location: http://' . $server_dir . $next_page . $query_string);
}
// If Ok then go to confirmation
else $next_page = 'confirmation.php';
/*
Here is where the PHP sql data insertion code will be
*/
// Redirect to confirmation page
header('Location: http://' . $server_dir . $next_page . $query_string);
?>
The greatness of this code is that if I type something in the first input type object and it doesn't equal 'myapp' it is still filled with the text after redirection. That's what I want with the second object as well.
Best practice would be to send them in a $_SESSION.
session_start();
$_SESSION['form'] = array();
$_SESSION['form']['myapp'] = 'App Error Code';
$_SESSION['form']['adtext'] = 'AdText Error Code';
Then on the new page you would get the values as an array;
session_start();
$form_error = $_SESSION['form']['myapp'];
$form_error = $_SESSION['attext']['myapp'];
If you insist on using GET parameters why not append them on with the & character.
?field1=one&field2=two
I woldn't do it the way you do it but if you want it like that just change few things
if ($appname != 'myapp') $error = 'App name is required<br />';
if ($adtext != 'mytext') $error .= 'Ad text is required<br />';//note contatenation
$query_string = '?appname=' . $appname .'&addtext='.$adtext;

Categories