I'm new in php and right now I'm having a problem when storing data in the $_SESSION array. I have an index page that retrieves information from an XML file and displays each product from the XML file in the page each one with a button to add to a cart. When the button is pressed, I send an XMLHttpRequest with the id of the product I want to add to the $_SESSION array.
This is the main page:
function check_avi(id){
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var available = this.responseText;
if (available == "True") {
alert("Add to the cart successfully.");
} else {
alert("Sorry, the car is not available now. Please try other cars.");
}
}
};
xhttp.open("GET", "add_delete_session.php?action=add&id="+id, true);
xhttp.send();
In the php I open the xml, retrieve the info and store it into an array, I then copy the information to the $_SESSION[#number of product]
What is happening is that after I add a product, it deletes in the session array the previous products, so each time I'm only having one product in the array and I want to store all of them to show them later in a shopping cart. The php should return a variable to the main page indicating the availability of the product but I'll do that later.
$arra is the array in where I'm storing the values obtained from the XML file corresponding to the product of the Id sent from the main page, like the price or name. $rf is the variable which count the amount of products stored and serve the same function as $_SESSION['g']
This is my PHP:
<?php
session_start();
$id = $_GET[id];
$action = $_GET[action];
if (empty($_SESSION['g'])) {
$_SESSION['g'] = 0;
}
switch($action){
case "add" :
$xmlDoc = new DOMDocument();
$xmlDoc = simplexml_load_file("cars.xml");
for ($e = 0; $e < 10; $e++) {
$cont = 0;
unset($arra);
foreach ($xmlDoc->carrito[$e]->children() as $child) {
$arra[$cont] = $child;
$cont = $cont + 1;
}
if ($arra[0] == $id) {
for ($f = 0; $f < 10; $f++) {
$rf = $_SESSION['g'];
$_SESSION[$rf][$f] = $arra[$f];
}
$_SESSION['g'] = $_SESSION['g'] + 1;
}
}
break;
case "delete":
break;
}
If anyone could help me I'll be so grateful.
Thanks
I think your in your code
1:
if (empty($_SESSION['g'])) {
$_SESSION['g'] = 0;
}
Actually here you haven't even defined the session at all and you are checking for its value if empty or not that's gonna stop execution of your code there itself, first you need to define the session variable and the check the value for it.
2:
$rf = $_SESSION['g'];
$_SESSION[$rf][$f] = $arra[$f];
Because it means that
$_SESSION[$_SESSION['g']][$f] = $arra[$f];
Which is a wrong approach.
Better way first you make all the simplifications and then assign it to the $_SESSION[] and echo it.
Related
My first ever question on here as I'm completely stuck, so apologies if I leave out any key information - please let me know!
I am creating a PHP Battleships game and trying to use full OO. I'm really close, however, an array for one of my classes does not hold any updates I make to it.
First off, I dynamically
created a HTML table with an onclick event - which passes the coordinates to a JS function.
I then make an AJAX call in jQuery:
function shotFired(row, column) {
var coords = {
x: row,
y: column
};
$.post("data/game_controller.php", {
jsonCoords: JSON.stringify(coords)
}, function(results) {
console.log(results)
console.log(results[4])
var playerShotResult = results[0];
var computerShotX = results[1] + 1;
var computerShotY = results[2] + 1;
var computerShotResult = results[3];
var positionsClicked = document.getElementById("computer_" + row + "," + column)
switch (playerShotResult) {
case "MISS":
positionsClicked.classList.add("miss");
break;
case "HIT":
positionsClicked.classList.add("hit");
break;
case "Already Hit":
document.getElementById("outputMessage").innerHTML = result
break;
default:
console.log("Player shot defaulted");
}
}, "json")
I then use game_controller.php to handle the request and call shotFired:
<?php
session_start();
require("../classes/Game.class.php");
if (isset($_POST['jsonCoords'])) {
if (isset($_SESSION['newGame'])) {
$game = unserialize($_SESSION['newGame']);
$coords = json_decode($_POST['jsonCoords']);
$results = $game->shotFired($coords->x, $coords->y);
echo json_encode($results);
}
}
shotFired from the Game.php Class file, gets an instance of the Fleet class called computer, and runs the checkPosition function:
public function shotFired($x, $y)
{
$computer = $this->getComputer();
$playerHit = $computer->checkPosition(($x - 1), ($y - 1));
$computerGrid = $computer->getBattleshipsGrid();
$computerHit = $this->simulateComputerShot();
return [$playerHit, $computerHit[0], $computerHit[1], $computerHit[2], $computerGrid];
}
checksPosition checks the State of the Position instance in the BattleshipGrid array, and then attempts to update the array with a H or M - using a standard setter method:
public function checkPosition($x, $y): string
{
$positionObj = $this->battleshipsGrid["(" . $x . "," . $y . ")"];
$positionState = $positionObj->getState();
if ($positionState == "#") {
$positionObj->setState("M");
return "MISS";
} elseif ($positionState == "M" || $positionState == "H") {
return "Already Fired";
} else {
$positionObj->setState("H");
return "HIT";
}
}
For reference, I set the Battleships board in the constructor for Fleet.php:
// Populate associative array with instances of position
for ($y = 0; $y < $gridSize; $y++) {
for ($x = 0; $x < $gridSize; $x++) {
$coordinates = "(" . $x . "," . $y . ")";
$this->battleshipsGrid[$coordinates] = new Position($x, $y);
}
}
It works directly after it has been set - however, on the next onclick event, the H or M value is reset to it's previous value?
Seen here in console output
After a couple of hours, the closest I've come to is passing byRef in the setState function (didn't make a difference).
I've seen some notes on array_map, but I'm not sure this is what I'm looking for?
For ref, this is how I output the battleshipGrid to the console:
public function getBattleshipsGrid()
{
$readableGrid = "";
$grid = $this->battleshipsGrid;
foreach ($grid as $coordsID => $positionObj) {
$readableGrid .= "\n" . $coordsID . ": " . $positionObj->getState();
}
return $readableGrid;
}
Apologies for the long post, but I didn't want to leave anything out. Any and all help would be extremely appreciated!
Many thanks
It looks like you're not saving the state of the coordinates of the hits. If you are using the eloquent model, and setState is changing the attribute's value, make sure that you call $positionObj->save() as php does not save state on each ajax request. You will need to use a database or some sort of storage to have the server 'remember' that you clicked a specific location.
I have never done combining ajax and session before. So far i have done something like this.
var sessionvar;
$.ajaxSetup({cache: false})
$.get('test.php' ,function (data) {
sessionvar = data;
alert(sessionvar);
var checkedCbs = $('sessionvar:checked');
if (checkedCbs.length === 4) {
alert("You can only select 3 books");
this.checked = false;
}
});
I want to try set the limitations based on session. Inside the test.php i have something like this
<?php
session_start();
if(isset($_POST['sBorrow']) && $_POST['action']){
if(isset($_SESSION['sBorrow']) && is_array($_SESSION['sBorrow'])){
$sborrow = $_POST['sBorrow'];
$set = $_SESSION['sBorrow'];
}
else{
$set = array();
}
if($_POST['action'] == "SET"){
array_push($set, $_POST['sBorrow']);
$_SESSION['sBorrow'] = $set;
}
else if($_POST['action'] == "UNSET"){
$unset = $_SESSION['sBorrow'];
if(($key = array_search($_POST['sBorrow'], $unset)) !== false) {
unset($unset[$key]);
$_SESSION['sBorrow'] = $unset;
}
}
}
//session_destroy();
if(isset($_SESSION['sBorrow'])){
$countses = count($_SESSION['sBorrow']);
echo $countses;
}
// nothing requested, so return all values
print json_encode($_SESSION);
?>
Inside these i have create some array to store something. Never mind that, i just want to know how to run an ajax with session. Im not sure if my codes is right for implementing that.
While running my code through W3C's HTML validator for HTML5, I noticed that some of my files had this comment inserted before the tag:
<!-- This file should NOT be stored in the web root directory (or any sub-directory thereof) If this is not possible, place it in the 'include' directory and restrict access via Apache's .htaccess files -->
This only seems to happen with pages that are accessed via POST requests, though I have been unable to pin down any cause, nor have searches turned up anything.
I am using mod rewrites and the HTML is generated from multiple files from webroot/views/ and webroot/includes/, but other pages that are similarly generated do not have this issue.
Anyway, I normally wouldn't worry about it, but when sending an xml request to dynamically update a price field, the xml return results, which were supposed to be just the price value as a number, were prefixed by that entire comment.
Now, I can remove it in my application code, which is what I have done, but I'd really like to know under what circumstances Apache decides to inject this comment into outputted HTML files.
For reference, here is my JS to send/handle the xml request:
<script type="text/javascript">
/**
* Updates the currently displayed price based on currently selected options
* #param category_id Id of currently selected category
*/
function updatePrice(category_id) {
if (category_id === undefined || category_id < 1) {
return false;
}
if (!document.getElementsByTagName) { return; }
var aSelect = document.getElementsByTagName("SELECT");
var data = [];
data.push("category_id=" + category_id);
for (var i = 0; i < aSelect.length; i++) {
var sid = aSelect[i].id;
if (sid !== undefined && sid.indexOf("select_") > -1) {
data.push(sid + '=' + aSelect[i].value);
}
}
data = data.join('&');
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
// Hack to remove Apache's auto-generated comment/warning at top of some pages
var text = xmlhttp.responseText;
text = (text.length > 0 ? text.substring(text.lastIndexOf('>') + 1).trim() : '');
var price = document.getElementById("product-price");
if (price != null) {
price.value = (text.length < 1 ? 'N/A' : ('$' + text));
}
}
}
xmlhttp.open("POST", "rental_update_price.php", true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send(data);
}
</script>
And here is the php file that processes the request:
<?php
if (!isset($errors)) { $errors = array(); }
if (!isset($notifications)) { $notifications = array(); }
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (empty($_POST['category_id']) || !is_numeric($_POST['category_id'])) {
die('Sorry, there has been a system error.');
}
$category_id = (int) $_POST['category_id'];
require './includes/config.inc.php';
require MYSQL;
$att_tbl = selectWithCondition($dbc, 'att_table', 'rental_categories', 'id', $category_id, 'i', 'LIMIT 1');
if ($att_tbl === FALSE) {
die('Failed to retrieve product attribute table from database.');
}
// Retrieve all 'select' keys and values to query exact product id and price
$selected = array();
foreach($_POST AS $k=>$v) {
if (strpos($k, 'select_') > -1) {
// All select fields should be foreign key references, i.e. positive integers
if (ctype_digit($v) && $v > 0) {
$selected[(str_replace('select_', '', $k) . '_id')] = (int) $v;
} else {
$errors[$k] = 'Invalid value';
}
}
}
if (empty($selected)) {
die('No columns selected.');
}
// TODO select price instead of id
$q = "SELECT p.id FROM products p";
$where = '';
foreach($selected AS $k=>$v) {
if (empty($where)) {
$where = "t.$k=$v";
} else {
$where .= " AND t.$k=$v";
}
}
$q .= " JOIN $att_tbl t ON t.product_id=p.id WHERE $where LIMIT 1";
if (($r = $dbc->query($q))) {
if ($row = $r->fetch_assoc()) {
// Generate dummy price value for testing:
echo number_format((((int) $row['id']) * 31) / 100, 2);
}
$r->close();
} else {
$notifications['error'] = 'A system error has occurred. The system administrator will be notified automatically.';
$notifications['error_log'] = 'Error No: ' . $dbc->errno . '-' . $dbc->error;
}
}
require MYSQL;
if MYSQL is a file, give it an extension .php so it doesn't bypass the PHP interpreter.
I think PHP does print the warning when you include a file which is not parsed.
Answering my own question since it was one of those where you look for days and when you finally break down and ask, it becomes glaringly obvious almost immediately.
In my MYSQL file, I had that comment at the top, even before the php tags, and in certain situations the MYSQL file is included before any other HTML output, which then results in that comment being displayed.
Moving the comment to within the php tags so that it is not considered HTML fixes the issue.
Thanks to all who commented.
I have the following function to set a cookie on each indiviual product page a user visits on my website.
function setcookie() {
$entry_id = '787';
if (isset($_COOKIE['recently_viewed'])) {
$currentSession = unserialize($_COOKIE['recently_viewed']);
if (!in_array($entry_id, $currentSession)) {
if (count($currentSession) > 5) {
unset($currentSession[0]);
}
$currentSession[] = $entry_id;
} else {}
$currentSession = serialize($currentSession);
setcookie('recently_viewed', $currentSession, pow(2,31)-1, '/', '');
} else {
$recently_viewed[] = $entry_id;
$currentSession = serialize($recently_viewed);
setcookie('recently_viewed', $currentSession, pow(2,31)-1, '/', '');
}
}
In this function I am trying to limit the number of items stored in the cookies array.
When the cookies array has 6 items in it, I want to remove the first (oldest) item in that array and then add the new item (so there is never more than 6 items, but always adds the new one).
I have used the following, but it doesn't always seem to work. Sometimes it removes the first item when there are more than 5, but other times it just keeps adding them so there are more than 6.
if (count($currentSession) > 5) {
unset($currentSession[0]);
}
Can anyone tell me if there is a better way to achieve this?
You definitely should use session.
session_start();
$entry_id = '788';
if (!is_array($_SESSION['recently_viewed'])) {
$_SESSION['recently_viewed'] = array();
}
// add the item to the begining
array_unshift($_SESSION['recently_viewed'], $entry_id);
// ensure unique entries
$_SESSION['recently_viewed'] = array_unique($_SESSION['recently_viewed']);
// keep first 5 entries
$_SESSION['recently_viewed'] = array_slice($_SESSION['recently_viewed'], 0, 5);
echo 'recent: ' . print_r($_SESSION['recently_viewed'], true);
if (count($currentSession) > 5) {
$arr = array_shift($currentSession);
}
I am trying to create logic to see what checkbox is selected (of 5 possible checkboxes) and if it is selected assign it a value of 0. if it is not selected I was to assign it a value of 1. The proceeding code snippet highlight this but throws a parse error in my else statement and I cannot fighure out why.
//Check to see what checkbox is marked for correct answer
//Correct answer variables
$chkBox1 = 'unchecked';
$chkBox2 = 'unchecked';
$chkBox3 = 'unchecked';
$chkBox4 = 'unchecked';
$chkBox5 = 'unchecked';
if (isset($_POST['chkBox1'])) {
if ($chkBox1 == 'chkBox1Selected') {
$chkBox1 = '0';
}
else{
$chkBox1 = '1';
}
}//End of chkBox1Selected logic
You don't understand how checkboxes work. If a checkbox is deselected before posting, it will not be set on post.
Therefore, the only condition that will ever be present in your code is that every value will show as 1, since they cannot be overridden.
Take this snippet and try it out. It dynamically loops for the amount of variables you need and assigns the values based upon the submitted value.
$_POST['chkBox4'] = 'test';
for( $i = 1; $i <= 5; $i++ )
{
$name = 'chkBox' . $i;
$$name = !isset( $_POST[$name] ) ? 0 : $_POST[$name];
}
print $chkBox2 . ' // '. $chkBox4;
http://codepad.org/51RotnCf
Ok I got it to work from a syntax standpoint, however now no matter what is selected it is still assigning a value of 1 to all the checkboxes and not changing the selected checkbox to a value of 0. Here is the new code that is correct from a syntax standpoint but defaults to 1 no matter what:
//Check to see what checkbox is marked for correct answer
//Correct answer variables
$chkBox1 = '1';
$chkBox2 = '1';
$chkBox3 = '1';
$chkBox4 = '1';
$chkBox5 = '1';
if (isset($_POST['chkBox1'])) {
if ($chkBox1 == 'chkBox1Selected') {
$chkBox1 = '0';
}
}//End of chkBox1Selected logic
if (isset($_POST['chkBox2'])) {
if ($chkBox2 == 'chkBox2Selected') {
$chkBox2 = '0';
}
}//End of chkBox2Selected logic
if (isset($_POST['chkBox3'])) {
if ($chkBox3 == 'chkBox3Selected') {
$chkBox3 = '0';
}
}//End of chkBox3Selected logic
if (isset($_POST['chkBox4'])) {
if ($chkBox4 == 'chkBox4Selected') {
$chkBox4 = '0';
}
}//End of chkBox4Selected logic
if (isset($_POST['chkBox5'])) {
if ($chkBox5 == 'chkBox5Selected') {
$chkBox5 = '0';
}
}//End of chkBox5Selected logic