Limit array size in cookie - php

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);
}

Related

Compare numbers through a loop to set a status accordingly

Let me change my question completely to explain myself better;
I have an order;
An order have multiple order rows. Each order row has two fields; Quantity ordered, and quantity delivered.
If all order rows' quantities delivered are the same as the quantity ordered, the entire order should get a status of '100% delivered'.
If multiple or even one order row's quantities delivered does not match the quantities ordered the entire order should get a status of 'partly delivered'.
If no order row have any deliveries (if all deliveries stands on 0) the status should be '0% delivered'.
What I have so far looks only at the last order row of the entire order because all the previous rows gets overridden by the latest check. This is my code;
public function deliveryAction(Request $request, $id) {
$em = $this->getDoctrine()->getManager();
$order = $em->getRepository('QiBssBaseBundle:PmodOrder')->find($id);
$orderRowsDelivered = $request->request->all();
$delivered = "0%";
foreach ($orderRowsDelivered['order_row_id'] as $orderRowId => $quantityDelivered) {
if($quantityDelivered != '' || $quantityDelivered != null) {
$orderRow = $em->getRepository("QiBssBaseBundle:PmodOrderRow")->find($orderRowId);
$orderDelivered = new PmodDelivery();
$orderDelivered->setOrderRow($orderRow);
$orderDelivered->setQuantity($quantityDelivered);
$orderDelivered->setTimeArrived(new \DateTime());
$em->persist($orderDelivered);
$em->flush();
if($orderRow->getQuantityDelivered() > 0 && $orderRow->getQuantityDelivered() < $orderRow->getQuantity()) {
$delivered = "partly";
} elseif ($orderRow->getQuantityDelivered() == $orderRow->getQuantity()) {
$delivered = "100%";
}
}
}
var_dump($delivered);exit;
return new RedirectResponse ... ;
}
Because as of this moment he looks at the last one with 10 and 8 in the example image, and give a status of 'partly', as soon as the 'quantity delivered' amounts is entered. But he should take all rows together.
I hope this makes more sense.
Based on what Cerad in the comments of his own answer said, this is my answer; (I'll make use of OP's scenario where he uses order rows per order.)
I've added an extra property to my OrderRow entity called $rowStatus.
After that I created a getter function for the $rowStatus called getRowStatus() that gives each row a status individually;
public function getRowStatus()
{
if ($this->getQuantityDelivered() == $this->getQuantity()) {
return $this->rowStatus = 100;
} elseif ($this->getQuantityDelivered() == 0) {
return $this->rowStatus = 0;
} else {
return $this->rowStatus = 50;
}
}
After that in my Order entity I've added a $deliveryStatus property, with a corresponding getter function called getDeliveryStatus() that looks like this;
public function getDeliveryStatus()
{
if (count($this->getOrderRows()) > 0) { //this check is to make sure there are orderRows, because you can't devide by zero if it might happen that there are no order rows. If not the delivery status will just be set on 0.
$sum = 0;
foreach ($this->getOrderRows() as $row) {
$sum += $row->getRowStatus();
}
$average = $sum / count($this->getOrderRows());
if ($average == 100) {
return $this->deliveryStatus = 100;
} elseif ($average == 0) {
return $this->deliveryStatus = 0;
} else {
return $this->deliveryStatus = 50;
}
} else {
return $this->deliveryStatus = 0;
}
}
That's it! After this I just use an enum function to display the 100 as "100% delivered", the 50 as "partly delivered", and the 0 as "0% delivered". I know this isn't really necessary, and you can instead change the status number directly to a string or whatever you want to display.
Just off the top of my head I might do:
$deliveredNone = true;
$deliveredAll = true;
$deliveredSome = false;
foreach ($orderRowsDelivered['order_row_id'] as $orderRowId => $quantityDelivered) {
if ($quantityDelivered) {
$deliveredNone = false; // Know that something has been delivered
}
...
if ($orderRow->getQuantityDelivered() != $orderRow->getQuantity()) {
$deliveredSome = true;
$deliveredAll = false;
}
}
$delivered = null;
if ($deliveredNone) $delivered = '0%';
if ($deliveredAll) $delivered = '100%';
if ($deliveredSome) $delivered = 'partly';
Though I would probably just update the order with the quantities delivered then use a different function to calculate the percentage delivered. As you can see, mixing the two processes can result in confusion.

Generating a Non-Repeating Random Number - PHP

I'm trying to get a custom function in php to return a random number between 1 and 20 that does not repeat i.e. produce the same number more than once, since I need to subsequently use this number to navigate to one of twenty web pages, and I don't want the same web page displayed.
Here is my code in three steps:
<form action="rand.php">
<p>Click this button to display a random number that does not repeat...</p>
<p><input type="submit" value="Generate"></p>
</form>
Here is rand.php:
require_once('functions.php');
$page = generateNumber();
echo $page;
Here is functions.php:
<?php
$check = array();
function generateNumber() {
global $check;
$page_no = mt_rand(1,20);
$check[] = $page_no;
if (count($check) != 1) {
foreach ($check as $val) {
if ($val == $page_no) {
$page_no = mt_rand(1,10);
continue;
}
}
return $page_no;
}
else {
return $page_no;
}
}
?>
My code seem to be functioning, however, it is repeating numbers so I am obviously doing something wrong. The reason I initially check the count is so that is returns the first number regardless, since it would be a single fresh number.
In order to see the number change I have been refreshing the rand.php page in my browser.
I would keep it simple.
// List numbers 1 to 20
$pages = range(1,20);
// Shuffle numbers
shuffle($pages);
// Get a page
$page = array_shift($pages);
In order to go through all the 20 numbers on each page visit, without repeating, you will need to set a session variable.
<?php
session_start();
if (!isset($_SESSION['numbers'])) {
$_SESSION['numbers']="*"; //---create the session variable
}
function get_number() {
$i = 0;
do {
$num=rand(1,20); //---generate a random number
if (!strstr($_SESSION['numbers'],"*".$num."*")) { //---check if the number has already been used
$_SESSION['numbers']=$_SESSION['numbers'] . $i . "*"; //---add the number to the session variable to avoid repeating
if (substr_count($_SESSION['numbers'],"*")>=21) { //---resets the session variable when all 20 number have been used
$_SESSION['numbers']="*";
}
$i=$num; //---ends the while loop to return the value
}
} while ($i==0);
return $i;
}
?>

Passing array of data to other page using session in PHP

I have some problem passing array of data in Php using session:
In my class, I have this function:
public function check_dupID($id)
{
$this->stmt="select id from student where id='$id'";
$this->res = mysql_query($this->stmt);
$this->num_rows = mysql_num_rows($this->res);
if($this->num_rows == 1)
{
while($this->row = mysql_fetch_array($this->res))
{
$dup_id = $this->row[0];
return $dup_id;
}
}
}
This code checks for duplicate ID of a student. Now, the reason for this is that I uploaded the file in the database using ".csv" file.
Before Uploading it I put all the data in the csv file into an array. Now, I check it one by one:
//created the variable for checking
$id = $check->check_dupID($array[0]);
if($id == TRUE)
{
session_start();
$_SESSION['id']; = $id;//passing it to the next back to array again.
$redirect->page($error);
}
Now when it redirect it gives me the result of an "Array" and if I parse it using foreach it shows only one id but there is more than of that. I want to know how to display it all.
This code will return the duplicate id when it is found for the first time. If you want to return all the duplicate ids, then add them into an array using the while loop and then return it.
To do this modify your code like this:
public function check_dupID($id)
{
$this->stmt="select id from student where id='$id'";
$this->res = mysql_query($this->stmt);
$this->num_rows = mysql_num_rows($this->res);
$dup_id = array();// added here to prevent invalid argument supplied to foreach loop error if nothing is found
if($this->num_rows >1)
{
while($this->row = mysql_fetch_array($this->res))
{
$dup_id[] = $this->row[0];// adding duplicates into the array
}
return $dup_id;
}
}
This code fixes my problem:
if($id == TRUE)
{
$get_id = array();
$get_id[] = $id;
session_start();
$_SESSION['id']; = $get_id;//passing it to the next back to array again.
$redirect->page($error);
}

PHP recently viewed script to session array

I've been given this bit of code:
if(isset($_GET['viewevent'])) {
if(count($_SESSION['e_lastviewed']) == 0) {
$_SESSION['e_lastviewed'][0] = $_GET['viewevent'];
} else if(!in_array($_GET['viewevent'], $_SESSION['e_lastviewed'])) {
$_SESSION['e_lastviewed'][2] = $_SESSION['e_lastviewed'][1];
$_SESSION['e_lastviewed'][1] = $_SESSION['e_lastviewed'][0];
$_SESSION['e_lastviewed'][0] = $_GET['viewevent'];
}
}
if($_GET['show']) {
$_SESSION['show'] = $_GET['show'];
} else if($_SESSION['show']=='') {
$_SESSION['show'] = "all";
}
It apparently saves ID's of recently viewed items, so i need to put these id's into an array.
Would this work?
$my_array = array($_SESSION['e_lastviewed'][2],$_SESSION['e_lastviewed'][1],$_SESSION['e_lastviewed'][0]);
I've ran it but it displays blank results (not sure if thats due to me not doing it right or incomplete code...Have i missed something? I'm not sure if i completley understand the script i was given...
try this:
if ( !isset($_SESSION['e_lastviewed']) )
$_SESSION['e_lastviewed'] = array();
// alt: while(count($_SESSION['e_lastviewed']) > 2 ) {
if(count($_SESSION['e_lastviewed']) > 2 ) {
array_shift($_SESSION['e_lastviewed']); // drop off from 3
array_unshift($_SESSION['e_lastviewed'],$_GET['viewevent']); // insert in the beginning
if($_GET['show']) {
$_SESSION['show'] = $_GET['show'];
} else if($_SESSION['show']=='') {
$_SESSION['show'] = "all";
}

cookie is being overwritten instead of creating a new one

I have written the following piece of code which works fine in Firefox.
// add product
if( isset($_GET['add']) ) {
$pointer = 1;
foreach ($_COOKIE['cart'] as $posit => $value) {
$pointer = $posit+1;
}
setcookie('cart['.$pointer.']', $_GET['add'] , time() + 60*60*24*$cookie_cart , '/' );
header('Location: cart.php');
}
The problem was when I tried it with Safari (so I guess the same problem may happen in other browsers. What happens is when the function foreach() runs, Safari reads the cookies in the opposite order Firefox does, so let's say the following cookies are defined: cart[1], cart[2], cart[3]. Firefox goes in this order, so when I add a new one it is stored as cart[4], whilst Safari does the opposite, making $pointer always be 1+1, storing it as cart[2] every time I add a new product.
I have tried many ways of fixing this, but so far unsuccessfully.
Thanks.
It looks like you don't even need a loop, you could just do
$position = count($_COOKIE['cart'])+1;
setcookie('cart['.$position.']',$_GET['add'] , time() + 60*60*24*$cookie_cart , '/' );
Edit:
Even better would be something like this:
function addItem($id) {
$cart = unserialize($_COOKIE['cart']);
$cart[] = $id;
setcookie('cart', serialize($cart) , time() + 60*60*24*$cookie_cart , '/' );
}
function removeItem($id) {
$cart = unserialize($_COOKIE['cart']);
$cart = array_diff($cart, array($id));
setcookie('cart', serialize($cart) , time() + 60*60*24*$cookie_cart , '/' );
}
function getCart() {
$cart = unserialize($_COOKIE['cart']);
return $cart;
}
And then you can just use those functions to interact with your cart.
For getting the next key, I would something simpler like:
//initial value
$newKey = 0;
//if cart is set and is an array
if(isset($_COOKIE['cart']) && is_array($_COOKIE['cart'])){
//get the max value from the keys and add 1
$newKey = max(array_keys($_COOKIE['cart']))+1;
}

Categories