Why is my $_SESSION super global not persistent across multiple pages? - php

I am trying to implement a shopping cart object for the user, storing a serialized version of the cart in the $_SESSION super global at the index 'user_cart', however I am running into an issue where the data I have stored at that index no longer exists when I move to a new page.
I do have session_start at the top of every page, and when I echo session_id(), I do get the same session id across multiple pages. In addition, when I echo $_SESSION on both pages, the page the object gets created on displays correctly as follows:
Array ( [user_cart] => Array ( [count] => 0 [items] => Array ( ) ) )
However, once I actually click on add to cart to order something, then navigate to my 'view cart' page, I get the following as my $_SESSION variable:
Array ( [user_cart] => )
Where it recognizes that my $_SESSION array has an index 'user_cart' however nothing is stored inside of it.
This ONLY happens if I add something to cart first, if I were to just go to the view cart page without adding anything to the cart, I get the same array printed as I did on the homepage where the session is created.
Here is some of the code I have in my 'add_to_cart_handler.php' file where I think the issue is arises:
$serialized=$_SESSION['user_cart'];
$cartobj=new ShoppingCart();
$cartobj->__unserialize($serialized);
$cartobj->addToCart($new_item_id, 1);
$_SESSION['user_cart']=$cartobj->__serialize();
header('Location: http://localhost/website/heroku/order.php');
Here is a snippet of both my __serialize() and __unserialize():
public function __serialize() {
return [
'count'=>$this->count,
'items'=>$this->serialize_items()
];
}
public function __unserialize(array $data) {
$this->count=$data[0];
$this->items=$this->unserialize_items($data[1]);
}
public function serialize_items() {
$serialized=array();
foreach($this->items as $item) {
$serialized[]=$item->__serialize();
}
return $serialized;
}
public function unserialize_items() {
$unserialized=array();
foreach($unserialized as $item){
$tmpItem=new CartItem();
$tmpItem->unserialize($item);
$unserialized[]=$tmpItem;
}
}
Where unserialize_items() and serialize_items() are essentially the same thing, but with the CartItem object.
EDIT:
It might be worth noting that my $_SESSION['user_cart'] has a value of null.

The solution can be found here: PHP session lost after redirect
The issue was that the script was still running in the addtocart_handler, and when redirected back to the most previous page, the script was still running.

Related

Wordpress - array not treated as array if manually entered

I am building a Wordpress site to track user progress. I have created a custom user text field called completed_sections which stores an array of sections of my website the user has completed. I am building that array like this:
<?php
if (is_user_logged_in()) {
global $completed;
$completed = get_field('completed_sections', 'user_'.$userID);
}
function update_completed_sections() {
global $completed;
global $userID;
$completedID = $_POST['quizID'];
$completionDate = $_POST['date'];
$completed_section[] = array(
'ID' => $completedID,
'date' => $completionDate
);
if (!empty($completed)) {
$combined = array_merge($completed, $completed_section);
} else {
$combined = $completed;
}
update_field('completed_sections', $combined, 'user_'.$userID);
}
add_action('wp_ajax_complete_section', 'update_completed_sections');
?>
This is working perfectly fine so long as I am using an AJAX call to fire the update_completed_sections function. The array that is added to the custom user field looks like this:
[{"ID":"58","date":"07\/31\/20"},{"ID":"79","date":"08\/03\/20"}]
However, if I go in to the user section of the Wordpress backend and manually try tp update the array, it breaks it. Even if I don't change anything and I just go in there and hit "Update User" it will cause Wordpress not to treat that field as an array anymore. Any ideas on how to make sure this field is treated as an array, even if it is manually entered through the Users section of Wordpress or through PHPMyAdmin?

specific php session variables lost in Chrome only,

I lose some session variables in Chrome only
After reading every similar question and answer on this site, I have to note:
It is not a 404 / missing favicon issue
Also not a redirect issue. The session is started and closed properly.
I have a $_SESSION['customer'] and $_SESSION['order'] variable, for instance.
As expected, $_SESSION['customer'] holds an object of customer data, $_SESSION['order'] holds an array of products.
When I add a product to the order, I need to look up any customer discounts for this specific product. Then it turns out in Chrome, the $_SESSION['customer'] variable is missing, and the sql query returns no discounts, since there is no customer number.
Let's give you some code to work with:
I am on the update order page, where I still have my customer and order variable.
I call this function with an ajax request to return a list of products:
public function live_search_product(){
$this->load->model('orders', 'orders');
$qry = $_GET['qry'];
if (strlen($qry)>0) {
$products = $this->orders_model->search_products($qry, false);
if ($products){
foreach ($products as $product){
echo ''.$product['short_title'] . '<br>';
}
}
}
}
I select the product from the dropdown list, and end up in this function, where I suddenly have lost my $_SESSION['customer'] object and $_SESSION['order'] array. Please note that all my other session variables still exist.
public function add_product() {
$this->load->model('orders', 'orders');
$product = $this->orders_model->get_product_by_id($this->router->id);
$discount = $this->discount->get_discount($product->id, $product->product_group_id, $_SESSION['customer']->id, $_SESSION['customer']->group_id );
$_SESSION['order'][$this->router->id] = array('product' => $product ,
'quantity' => 1,
'rental' => 0,
'bruto' => $product->price_ex,
'discount' => $discount->discount_percentage,
'netto' => ((100 - $discount->discount_percentage)/100) * $product->price_ex,
'total' => ((100 - $discount->discount_percentage)/100) * $product->price_ex);
$this->calculate_order_totals();
}
In firefox and iexplorer and edge there is no problem, it works.
I really hope you have any other suggestions.
**** EDIT ****
Every controller has an index function that is called automatically. route orders/orders will call orders/orders/index, and for instance route orders/orders/add_product, will call the function add_product in the orders controller (residing in the orders folder).
It turns out that in Chrome, somehow I get routed to the index function of this orders controller. Which is an overview orders function where I reset all order variables, to make sure nothing is left when I open a new order.
I have changed that, so this specific situation is solved.
However, can not understand why I get redirected to this function, when calling the add_product function directly.
Any ideas?

Adding custom option to order line

I'm currently trying to add a custom option to a specific orderline on add to cart via the following:
public function addToPackageQuote()
{
$cart = Mage::getSingleton("checkout/cart");
$quote = Mage::getSingleton("checkout/session")->getQuote();
$packageId = Mage::getModel('MyTuxedo_OPP/Package')->checkPackageId();
$products = $this->sortArray();
foreach ($products as $productInfo) {
try {
$split = explode(",", $productInfo);
$_product = Mage::getModel('catalog/product')->load($split[0]);
if($_product->isConfigurable()) {
$simpleId = $this->getConfigurableSimple($split[1],$split[3],$split[0]);
} else {
$simpleId = $split[0];
}
$product = Mage::getModel('catalog/product')->load($simpleId);
$options = new Varien_Object(array(
"qty" => 1,
"custom_options" => array(
"package" => $packageId,
"packageName" => Mage::helper('MyTuxedo_OPP')->getPackageName()
)
));
$quote->addProduct($product, $options);
$this->_getSession()->setCartWasUpdated(true);
$quote->save();
} catch (Exception $e) {
echo $e->getMessage();
}
$this->addFreeItems();
}
$cart->save();
unset($_SESSION['products']);
unset($_SESSION['productId']);
$cart->save();
// Let's unset all the package sessions (apart from a few that are needed!).
$this->kill();
}
This method is completely seperate from the generic add to cart handler, and is used purely in a packages system so that it adds simple products exclusively (also breaks down configurables super attribute to find the simple product too).
These simple products have no custom options attached to them in the Magento backend, nor is it a goal to add custom options to the product itself. What I would like to do is attach custom options to the order-line that is then transferred over to the order if a purchase is made. So effectively data that is added at the add to cart method and no where else!
The add to cart method works as expected it's just not including the custom options I am trying to attach. I have also tried defining the options object as simply:
$options = new Varien_Object(array(
"qty" => 1,
"package" => $packageId,
"packageName" => Mage::helper('MyTuxedo_OPP')->getPackageName()
)
The above info, not including qty is not in the orderline object at all, and I can't seem to work out where to move on from here.
Endlessly googling at the moment so some help would be most appreciated!!
I do appreciate I’m instantiating the product model object twice in this, however the plan is to just get it working then optimise! :)
You have to set the custom options for the product before adding it to cart.
$product->setCustomOptions($options);
The in Mage_Sales_Model_Quote::_addCatalogProduct() the custom options will be added to the cart item.
See also here: http://www.magentocommerce.com/boards/viewthread/49659/
By the way: Your code may be pretty slow because you are loading products twice in a foreach loop. You should consider some refactoring by using the product collection instead. Also it looks kind of hackish to directly access the $_SESSION variable here. You could rather use the Checkout Session for that (Mage::getSingleton('checkout/session')).
I have now resolved this, after much headache. You can add a custom option to the cart and not have to instantiate the product object and save a custom option to do this, it can be done via tacking onto an observer, and pulling the quote items.
After tacking onto: sales_quote_add_item
I then used:
public function addCustomData($observer) {
$event = $observer->getEvent();
$quote_item = $event->getQuoteItem();
$quote = $session->getQuote();
$quote_item->addOption(array("product_id" => $quote_item->getProduct()->getId(),
"product" => $quote_item->getProduct(),
"code" => 'PackageId',
"value" => Mage::getModel('MyTuxedo_OPP/Package')->checkPackageId()
));
$quote->save();
}
It is most important to include the product object and id, as the function doesn't use the loaded object for some reason.
You can then get at the object via:
$_item->getOptionByCode('PackageId')->getValue();
Quick piece of handy info, if it dumps a stack trace in front of you it can't find the defined option, lose the getValue() (if using var_dump) function to see if you are getting a null value, otherwise xdebug will give you a ton of hints to get around it.

function for including pages

I'm trying to make a function for including pages.
In fact For the beginning I used to work with a long code that checked for all pages:
if (isset($_GET]['p']) && $_GET['p']=='something') {include 'something.php'};
Now I work with more than 600 pages and this code is too long and I would like to simplify it.
Sometimes I do have pages that are note entitled like they are used, for example home will correspond to accueil.php etc.
So I've done an array in which I listed all exceptions:
like that:
$paramListepages = array(
'corbeille' => array(
'libelle' => 'corbeille',
'page' => 'php/trash.php'
),
'nouveaumessage' => array(
'libelle' => 'nouveaumessage',
'page' => 'php/envoyer.php'
),
etc...
In this array I have about 20 pages.
Now I've tried to create a function for including pages so here is my code:
function getPage($var)
{
if (isset($var)) {
$key = array_search($var, $paramListepages);
if ($key == false()) {
include('php/'.$var.'.php');
} else {
}
}
}
I do not understand why the first part does not work.
I first of all check if the var does exist in the array, if not I include the page corresponding to the var.
I do still do not know how to do the second part, but for now the first one does not work.
I have no message error, even if in my ubunto I activated the displaying of all errors.
In the main page index.php I call the function getPage($_GET['p'])
Any kind of help will be much appreciated.
I'd suggest accessing the entries in your array directly:
function getPage($var) {
if (empty($var))
// no page specified => default page
inlude('index.php')
elseif (array_key_exists($var,$paramListepages))
// page found => include it!
include (sprintf('php/%s.php', $paramListepages[$var]['page']));
else
// page not found => default page
inlude ('index.php')
}

how to use drupal_write_record. my db doesnt update when form submits

Im using drupal and im trying to create my own form in a block.
Ive wrote a module which creates a block with a submit button.
When the form is submitted im trying to write the values to my db.
im using this code
function my_module_my_form_submit($form, &$form_state) {
block_example_insert_credits($credits_record);
}
function block_example_insert_credits() {
global $user;
$credits_record = array(
'nid' => $node->nid,
'uid' => $user->uid,
'credits' => $form_state['values']['bids'],
);
drupal_write_record('example_table', $credits_record, 'nid');
}
the form submits and validates, and the table and columns exist in my db. When I submit the form nothing gets sent to database, why isnt my code correct?
There are a few things not quite right:
You're not passing any parameters to block_example_insert_credits()
You have no reference to $credits_record in my_module_my_form_submit() so nothing would be passed to the insert function anyway.
You're trying to access $form_state from a function in which it doesn't exist
You don't have a reference to the node object anywhere so you can't use it. $node isn't a globally available variable, if you want a node object it will have to come from a value save in your form or from the menu_get_object() function (if the block is being displayed on a node page).
Try this code and see if you have any luck:
function my_module_my_form_submit($form, &$form_state) {
block_example_insert_credits($form_state);
}
function block_example_insert_credits($form_state) {
global $user;
$node = menu_get_object();
$credits_record = array(
'nid' => $node->nid,
'uid' => $user->uid,
'credits' => $form_state['values']['bids'],
);
drupal_write_record('example_table', $credits_record, 'nid');
}
Hope that helps.
i'm a drupal novice so apologies if i'm wrong...isn't it the $node or &$form_state that should be passed to the insert method from form_submit?......maybe you could check by using watchdog for the credit records array to check values are passed properly...cheers

Categories