Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
show display nothing from cart menu sidebar when first i click on add to cart.
show display from cart menu sidebar when second i click on add to cart.
URL: https://www.bellastudio.pk/new/products.php?p_slug=olive-green
when i ty to start the add to cart i get this error:
PHP Warning: array_column() expects parameter 1 to be array, null given in
PHP Warning: array_search() expects parameter 2 to be array, null given in
i don't know how to make'it work, some help is appreciated. I'm new with this.
PHP
try {
if(isset($_POST['product_name']))
{
$name = $_POST['product_name'];
}
if(isset($_POST['product_price']))
{
$price = $_POST['product_price'];
}
if(isset($_POST['product_itemno']))
{
$itemno = $_POST['product_itemno'];
}
if(isset($_POST['product_quantity']))
{
$qty = $_POST['product_quantity'];
}
if(isset($_POST['product_color']))
{
$color = $_POST['product_color'];
}
if(isset($_POST['product_size']))
{
$size = $_POST['product_size'];
}
if(isset($_POST['sleeves']))
{
$sleeves = $_POST['sleeves'];
}
if(isset($_POST['neck']))
{
$neck = $_POST['neck'];
}
$stockitemno = $itemno.'-'.$size;
$host = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
$host->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $host->prepare( "SELECT * FROM productstock INNER JOIN product ON product.p_id = productstock.pid INNER JOIN productsize ON productsize.sid = productstock.size_id WHERE product.p_itemno = :itemno AND productsize.sname = :size" );
$stmt->bindValue( ':itemno', $itemno );
$stmt->bindValue( ':size', $size );
$stmt->execute();
while ( $row = $stmt->fetch( PDO::FETCH_ASSOC ) ) {
// Current stock quantity
$stockqty = $row[ 'stockqty' ];
// No stock, bail early
if ( !$stockqty ) {
echo '<p>No available stock for that item.</p>';
}
// User didn't provide a quantity value
else if ( !$qty ) {
echo '<p>Please enter a quantity</p>';
}
// Lets add to the cart
else {
// Find product in cart
$cartindex = array_search( $stockitemno, array_column( $_SESSION[ 'cart' ], 'stockitemno' ) );
// Product info
$product = null;
// If already exists in cart
if ( $cartindex !== false ) {
$product = $_SESSION[ 'cart' ][ $cartindex ];
}
// Does not exit in cart, create new product info
else {
$product = [
'name' => $name,
'price' => $price,
'item_no' => $itemno,
'qty' => 0, // Default to none added
'color' => $color,
'size' => $size,
'stockitemno' => $stockitemno,
'sleeves' => $sleeves,
'neck' => $neck,
'stockqty' => $stockqty
];
}
// Track how many items were able to be added to the cart
$totaladded = 0;
// If users full amount is available
if ( ( $product[ 'qty' ] + $qty ) <= $stockqty ) {
$totaladded = $qty;
}
// Else add all available stock
else if ( $stockqty - $product[ 'qty' ] ) {
$totaladded = ( $stockqty - $product[ 'qty' ] );
}
// If we were able to add new items to cart
if ( $totaladded ) {
// Update product new qty
$product[ 'qty' ] += $totaladded;
// Update cart item
if ( $cartindex !== false ) {
$_SESSION[ 'cart' ][ $cartindex ] = $product;
}
// Add new item to cart
else {
$_SESSION[ 'cart' ][] = $product;
}
// Example: 5 item (size) were successfully added to your shopping cart.
printf( '<p><strong>%d</strong> %s (%s)<br>was successfully added to your shopping cart.</p>', $totaladded, $name, $size );
} else {
echo '<p>Not enough stock</p>';
}
}
}
} catch ( PDOException $e ) {
echo 'Error: ' . $e->getMessage();
}
$host = null;
$cart_count = count( $_SESSION[ 'cart' ] );
AJAX
$(document).ready(function()
{
load_cart_data();
function load_cart_data()
{
$.ajax({
url:"asset/includes/fetch_cart1.php",
method:"POST",
success:function(data)
{
$('.cart_details').html(data);
$('.badge1').text(data.total_item);
}
});
}
$(document).on('click','#add_to_cart',function (e) {
var cart_count = $('.navbar-tool-badge').text();
cart_count = parseInt(cart_count);
if($('input[type=radio][name=size]:checked').length == 0)
{
$('.msg').html('Please choose size.');
return false;
} else {
var product_name = $('#hidden-name').val();
var product_price = $('#hidden-price').val();
var product_itemno = $('#itemno').val();
var product_quantity = $('.quantity').val();
var product_color = $('#color').val();
var product_size = $("input[name='size']:checked").val();
var sleeves = $('#sleeves').val();
var neck = $('#neck').val();
e.preventDefault();
$.ajax
({
type: "POST",
url: "asset/includes/insertcart.php",
data:{product_name:product_name, product_price:product_price, product_itemno:product_itemno , product_quantity:product_quantity, product_color:product_color, product_size:product_size, sleeves:sleeves, neck:neck},
cache: false,
success: function(response)
{
load_cart_data();
$("#getCode").html(response);
$("#myModal").modal('show');
// remove cart count
$('.navbar-tool-badge').html(cart_count + 1);
}
});
}
});
$(document).on('click', '.delete', function(){
var item_no = $(this).attr("id");
var cart_count = $('.navbar-tool-badge').text();
cart_count = parseInt(cart_count);
$.ajax({
url:"asset/includes/delete_item.php",
method:"POST",
data:{item_no:item_no},
success:function(data)
{
if(data){
load_cart_data();
$('#cart-popover').popover('hide');
}
// remove cart count
$('.navbar-tool-badge').html(cart_count - 1);
}
})
});
});
at the first attempt, your $_SESSION[ 'cart' ] might be empty and hence you are getting an error. try to validate for empty cart and then do a search like this
if(!empty($_SESSION[ 'cart' ])){
$cartindex = array_search( $stockitemno, array_column( $_SESSION[ 'cart' ], 'stockitemno' ) );
}
Related
I want to exclude WooCommerce revenue from the Google Analytics purchase event when the Product ID is 224112 or 159324.
I tried to find solutions to exclude sending the data to GA4 through GMT exclusion triggers or filters directly in the GA4 interface, but it seems the best way to accomplish this is to exclude the data from arriving into the datalayer in the first place.
I use the GTM4WP plugin to send the website data (WordPress, WooCommerce) to the GTM datalayer.
In the plugin, I found the part of the code that sends the purchase data to the datalayer. I'm not very familiar with this code and I dont want to mess things up on my site. Since the Google Analytics give the results only after 24 hours I want to make sure that I do the right thing right away.
This is the original plugin code:
function gtm4wp_get_purchase_datalayer( $order, $order_items ) {
global $gtm4wp_options, $gtm4wp_is_woocommerce3_7;
$dataLayer = array();
if ( $order instanceof WC_Order ) {
$woo = WC();
// variable for Google Smart Shopping campaign new customer reporting
// https://support.google.com/google-ads/answer/9917012?hl=en-AU#zippy=%2Cinstall-with-google-tag-manager
if ( $woo->customer instanceof WC_Customer ) {
// we need to use this instead of $woo->customer as this will load proper total order number and value from the database instead of the session
$woo_customer = new WC_Customer( $woo->customer->get_id() );
$dataLayer['new_customer'] = $woo_customer->get_order_count() === 1;
}
if ( $gtm4wp_options[ GTM4WP_OPTION_INTEGRATE_WCEXCLUDETAX ] ) {
$order_revenue = (float)( $order->get_total() - $order->get_total_tax() );
} else {
$order_revenue = (float) $order->get_total();
}
$order_shipping_cost = (float) $order->get_shipping_total();
if ( $gtm4wp_options[ GTM4WP_OPTION_INTEGRATE_WCEXCLUDESHIPPING ] ) {
$order_revenue -= $order_shipping_cost;
}
$order_currency = $order->get_currency();
if ( true === $gtm4wp_options[ GTM4WP_OPTION_INTEGRATE_WCTRACKCLASSICEC ] ) {
$dataLayer['event'] = 'gtm4wp.orderCompleted';
$dataLayer['transactionId'] = $order->get_order_number();
$dataLayer['transactionAffiliation'] = '';
$dataLayer['transactionTotal'] = $order_revenue;
$dataLayer['transactionShipping'] = $order_shipping_cost;
$dataLayer['transactionTax'] = (float) $order->get_total_tax();
$dataLayer['transactionCurrency'] = $order_currency;
}
if ( true === $gtm4wp_options[ GTM4WP_OPTION_INTEGRATE_WCTRACKENHANCEDEC ] ) {
$dataLayer['event'] = 'gtm4wp.orderCompletedEEC';
$dataLayer['ecommerce'] = array(
'currencyCode' => $order_currency,
'purchase' => array(
'actionField' => array(
'id' => $order->get_order_number(),
'affiliation' => '',
'revenue' => $order_revenue,
'tax' => (float) $order->get_total_tax(),
'shipping' => (float)( $order->get_shipping_total() ),
'coupon' => implode( ', ', ( $gtm4wp_is_woocommerce3_7 ? $order->get_coupon_codes() : $order->get_used_coupons() ) ),
)
)
);
}
if ( isset( $order_items ) ) {
$_order_items = $order_items;
} else {
$_order_items = gtm4wp_process_order_items( $order );
}
if ( true === $gtm4wp_options[ GTM4WP_OPTION_INTEGRATE_WCTRACKCLASSICEC ] ) {
$dataLayer['transactionProducts'] = $_order_items['products'];
}
if ( true === $gtm4wp_options[ GTM4WP_OPTION_INTEGRATE_WCTRACKENHANCEDEC ] ) {
$dataLayer['ecommerce']['purchase']['products'] = $_order_items['products'];
}
if ( $gtm4wp_options[ GTM4WP_OPTION_INTEGRATE_WCREMARKETING ] ) {
$dataLayer['ecomm_prodid'] = $_order_items['product_ids'];
$dataLayer['ecomm_pagetype'] = 'purchase';
$dataLayer['ecomm_totalvalue'] = (float) $_order_items['sumprice'];
}
}
return $dataLayer;
}
I think I could add an if statement just before the excludeTAX option. It would be something like this:
If ($productID = array (224112, 159324)) {
$order_revenue = 0;
} else {
$order_revenue = (float) $order->get_total();
}
I don't know what would be the correct variable for $productID and I am not sure that this would work.
Any help is appreciated.
$order_product_ids = array();
foreach ($order->get_items() as $item_key => $item) {
$product = $item->get_product();
$order_product_ids[] = $product->get_id();
}
$checklist_product_ids = array(224112, 159324);
$is_product_in_order = (count(array_intersect($order_product_ids, $checklist_product_ids))) ? true : false;
If ($is_product_in_order) {
$order_revenue = 0;
} else {
$order_revenue = (float) $order->get_total();
}
Been banging my head for weeks to solve this. Im abit novice programmer and trying to figure this out. So I would like to have cloned input box which is triggered by clicking on the .Plus button for adding quantity in product page for woocommerce.
The cloned input box is triggered by using jQuery code below.
<script>
(function($) {
var i=1;
var j=2;
$(document).on( "click", ".plus", function(){
console.log('plus:change');
$(".minus").prop('disabled', false);
$(".custom-text").clone().find("input").each(function() {
$(this).attr({
'id': function(_, id) { return id + i },
'name': function(_, name) { return name + i},
'placeholder':function(_, placeholder) {return placeholder + " "+ j},
'value': ''
});
}).insertAfter(".custom-text");
i++;
});
$(document).on( "click", ".minus", function(){
console.log('minus:change');
if ($(".wccpf-field").length > 1) {
$(".wccpf-field:last").remove();
j--;
i--;
}
else {
$(".minus").prop('disabled', true);
i=1;
j=2;
console.log(i,j);
}
});
})(jQuery);
</script>
PHP code
add_action( 'woocommerce_before_add_to_cart_button', 'add_fields_before_add_to_cart' );
function add_fields_before_add_to_cart( ) {
?>
<table class="custom-text">
<tr>
<td>
<?php _e( "Custom Quote:", "aoim"); ?>
</td>
<td>
<input type = "text" name = "custom_quote" id = "custom_quote" placeholder = "Custom Quote">
</td>
</tr>
</table>
<?php
}
/**
* Add data to cart item
*/
add_filter( 'woocommerce_add_cart_item_data', 'add_cart_item_data', 25, 2 );
function add_cart_item_data( $cart_item_meta, $product_id ) {
if ( isset( $_POST ['custom_quote'+$i] ) ) {
$custom_data = array() ;
for ($i = 0; $i <= 5; $i++){
$custom_data [ 'custom_quote' ] = isset( $_POST ['custom_quote'+$i] ) ? sanitize_text_field ( $_POST ['custom_quote'+$i] ) : "" ;
$cart_item_meta ['custom_data'] = $custom_data ;
}
return $cart_item_meta;
}
/**
* Display custom data on cart and checkout page.
*/
add_filter( 'woocommerce_get_item_data', 'get_item_data' , 25, 2 );
function get_item_data ( $other_data, $cart_item ) {
if ( isset( $cart_item [ 'custom_data' ] ) ) {
$custom_data = $cart_item [ 'custom_data' ];
for ($i = 0; $i <= 5; $i++){
$other_data[] = array( 'name' => 'Custom Quote 1',
'display' => $custom_data['custom_quote'+$i] );
}
}
return $other_data;
}
I am able to clone the input and even attach unique id,name for each cloned input box. However, I am having issue to display them in cart page.
UPDATE
Managed to resolve by myself. Here is the complete code. Not the most clean code but it works for me.
PHP CODE
add_action( 'woocommerce_before_add_to_cart_button', 'add_fields_before_add_to_cart' );
function add_fields_before_add_to_cart( ) {
global $product;
if ( $product->is_type( 'variable' ) ) {
?>
<table class="custom-text">
<tr>
<td>
<?php _e( '<b>'."Custom Quote".'</b>', "aoim"); ?>
</td>
<td>
<input type = "text" class="td-width-input" name ="custom_quote" id = "custom_quote" placeholder ="Custom Quote" maxlength="100">
</td>
</tr>
</table>
<table>
<tr>
<td class="custom-width">
</td>
<td>
<div class="custom-text-output"> </div>
</td>
</tr>
</table>
<div class="msg-custom-text-standard">
Ready-stock quote will be randomly selected by company
</div>
<div class="msg-custom-text-customized-quote">
*Requires 7 working days to prepare the customised quote.<br>
</div>
<?php
}
}
/**
* Add data to cart item
*/
add_filter( 'woocommerce_add_cart_item_data', 'add_cart_item_data', 25, 2 );
function add_cart_item_data( $cart_item_meta, $product_id ) {
$qty=$_POST['quantity'];
if ( isset( $_POST ['custom_quote'.$i] ) ) {
$custom_data = array() ;
$custom_data [ 'custom_quote' ] = isset( $_POST ['custom_quote'] ) ? sanitize_text_field ( $_POST ['custom_quote'] ) : "" ;
for ($i = 1; $i < $qty ; ++$i){
$custom_data [ 'custom_quote'.$i ] = isset( $_POST ['custom_quote'.$i] ) ? sanitize_text_field ( $_POST ['custom_quote'.$i] ) : "" ;
}
$cart_item_meta ['custom_data'] = $custom_data ;
return $cart_item_meta;
}
}
/**
* Display custom data on cart and checkout page.
*/
add_filter( 'woocommerce_get_item_data', 'get_item_data' , 25, 2 );
function get_item_data ( $other_data, $cart_item ) {
if ( isset( $cart_item [ 'custom_data' ] ) ) {
$custom_data = $cart_item [ 'custom_data' ];
foreach ($custom_data as $key => $value){
$i++;
$other_data[] = array( 'name' => 'Custom Quote ' . $i ,
'display' => $value );
}
}
return $other_data;
}
// }
/**
* Add order item meta.
*/
add_action( 'woocommerce_add_order_item_meta', 'add_order_item_meta' , 10, 2);
function add_order_item_meta ( $item_id, $values ) {
if ( isset( $values [ 'custom_data' ] ) ) {
$custom_data = $values [ 'custom_data' ];
wc_add_order_item_meta( $item_id, 'Custom Quote 1', $custom_data['custom_quote'] );
$k=1;
foreach ($custom_data as $key => $value){
$i++;
$k++;
wc_add_order_item_meta( $item_id, 'Custom Quote '.$k, $custom_data['custom_quote'.$i] );
}
}
}
// validate when add to cart
function validation_custom_quote($passed, $product_id){
$qty=$_POST['quantity'];
$product = wc_get_product( $product_id );
if (isset($_POST ['custom_quote'] ) && sanitize_text_field( $_POST ['custom_quote'] ) == '' ) {
wc_add_notice( sprintf( __( 'Please make sure custom quote is filled for product %s' ), $product->get_title() ), 'error' );
return false;
}
for ($i = 1; $i < $qty ; $i++){
if(isset($_POST ['custom_quote'.$i] ) && sanitize_text_field( $_POST ['custom_quote'.$i] ) == '') {
wc_add_notice( sprintf( __( 'Please make sure all custom quotes are filled for product %s' ), $product->get_title() ), 'error' );
return false;
} }
return $passed;
}
add_filter( 'woocommerce_add_to_cart_validation', 'validation_custom_quote', 10, 3 );
JQuery CODE
<script>
(function($) {
var i=1;
var j=2;
$(document).on( "click", ".plus", function(){
$(".custom-text").clone().find("input").each(function() {
$(this).attr({
'id': function(_, id) { return id + i },
'name': function(_, name) { return name + i},
'placeholder':function(_, placeholder) {return placeholder + " "+ j},
'value': ''
});
}).appendTo(".custom-text-output");
i++;
j++;
console.log('plus:change');
$(".minus").prop('disabled', false);
});
$(document).on( "click", ".minus", function(){
if(i==1){
alert("Minimum Quantity is 1");
return false;
}
else {
i--;
j--;
$("#custom_quote" + i).remove();
}
});
$(document).on( "ready", function(){
$('.custom-text').hide();
});
$(document).on( "change", "#pa_bottle-quotes", function(){
if ( this.value == 'customized-quote')
{
$(".custom-text").fadeIn(500).show();
$(".custom-text-output").fadeIn(500).show();
$(".msg-custom-text-standard").hide();
$(".msg-custom-text-customized-quote").fadeIn(500).show();
}
else if( this.value == 'standard-quote')
{
$(".custom-text").hide();
$(".custom-text-output").hide();
$(".msg-custom-text-standard").fadeIn(500).show();
$(".msg-custom-text-customized-quote").hide();
}
else {
$(".custom-text").hide();
$(".custom-text-output").hide();
$(".msg-custom-text-standard").hide();
$(".msg-custom-text-customized-quote").hide();
}
});
$(document).on( "ready", function(){
$(".custom-text").hide();
$(".custom-text-output").hide();
$(".msg-custom-text-standard").hide();
$(".msg-custom-text-customized-quote").hide();
});
$(document).on("click",".single_add_to_cart_button", function() {
if ( $("#pa_bottle-quotes option:selected").text() == 'Standard Quote') {
$(".custom-text").remove();
$(".custom-text-output").remove();
}
else {
console.log("customized");
}
});
})(jQuery);
</script>
I am trying to develop a shopping cart that lives in a session, the shopping cant has any duplicates so every item that needs to be added is unique otherwise it would just warn the user that it is already added.
I am doing this through merging an array and an if statement where it would check if it already exists in that variable, the logic seems to still allow duplicates and stops at a certain point for some reason.
//We search for the product that has been clicked on
$sql = $conn->prepare('SELECT * FROM product WHERE product_id= :product_id');
$sql -> execute(['product_id' => $product_id]); //execute the statement
$row = $sql->fetch();
$product_name = $row['product_name'];
$product_id = $row['product_id'];
$product_price = $row['product_price'];
//You could perform another search here to obtain the product image
$cartArray = array(
$product_id=>array(
'product_name'=>$product_name,
'product_id'=>$product_id,
'product_price'=>$product_price,
'product_quantity'=>1
)
);
// we perform some logic that detects if the product is already in the basket.
// If it is, we display an error message. Increasing quantity is handled on the cart page
if(empty($_SESSION["shopping_cart"])) {
$_SESSION["shopping_cart"] = $cartArray;
$status = "<div class='box'>Product is added to your cart!</div>";
}else{
$array_keys = array_keys($_SESSION["shopping_cart"]);
if(in_array($product_id,$array_keys)) {
$status = "<div class='box' style='color:red;'>
Product is already added to your cart!</div>";
} else {
$_SESSION["shopping_cart"] = array_merge(
$_SESSION["shopping_cart"],
$cartArray
);
$status = "<div class='box'>Product is added to your cart!</div>";
}
}
}
I would like to know if there was anything that I need to do differently to prevent duplication
I suggest this:
//We search for the product that has been clicked on
$sql = $conn->prepare('SELECT * FROM product WHERE product_id= :product_id');
$sql -> execute(['product_id' => $product_id]); //execute the statement
$row = $sql->fetch();
// Collect from $row just what must be in cart session
foreach ( $row as $index => $value ) {
if ( in_array( $index, $cartDesign ) ) {
$product[ $index ] = $value;
}
}
// Store session in Array
$currentCart = $_SESSION[ 'shopping_cart' ];
// Product properties. Quantity comes after.
$cartDesign = array(
'product_id',
'product_name',
'product_id',
'product_price',
);
// Checks if products is already in the cart
$inCart = false;
foreach ( $currentCart as $index => $cartItem ) {
if ( $cartItem[ 'product_id' ] === $product[ 'product_id' ] ) {
$inCart = true;
$indexInCart = $index;
}
}
if( $inCart ) {
// One more in quantity of prodduct (if desired). Comment it if the product just can be or not be in the cart
$_SESSION["shopping_cart"][ $indexInCart ][ "quantity" ] = $currentCart[ "shopping_cart" ][ $indexInCart ] + 1;
// Send status: product is already there
$status = "<div class='box' style='color:red;'>Product is already added to your cart!</div>";
} else {
// Send status: product was not there
$status = "<div class='box'>Product is added to your cart!</div>";
$array_keys = array_keys($_SESSION["shopping_cart"]);
// Adding to cart in session
$appendToCart = array( $product, "quantity" => 1 );
$_SESSION[ "shopping_cart" ][] = $appendToCart;
}
This way requires the session design $_SESSION[ "shopping_cart" ][ int $index ][ array $product ], $_SESSION[ "shopping_cart" ][ int $index ][ "quantity" ][ int $quantity ]
Before asking question on SO, I searched a lot about what I needed to make a ajax request with WordPress. All my code and the request is working, but is not doing what I need it to do.
What I need to do is When I click at the buttom on checkout page "Novo Dependente", the information with the values to calculate total must update. "Total" value must be updated with a value which I defined at product post type page on admin panel. This value I already get, but the updating the value is real problem to me.
This is the page that I working.
This is the form, that shows up when i click the button, when i Toogle the checkbox I need to add the second value to the Total, another request with ajax.
And here my code goes
Obs: it's a plugin.
Here is the php code.
public function add_total_value()
{
if (! $_POST['action'] || $_POST['action'] !== 'add_total_value' ) :
echo json_encode(
array(
'status' => 'failed',
'message' => 'erro'
)
);
wp_die();
endif;
$woocommerce;
$quantidadeDependentes = $_POST['quantiaDependentes'];
//$produto_valor = WC()->cart->total;
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item )
{
$product = $cart_item['data'];
$item_id = $cart_item['product_id'];
$endereco_igual = get_post_meta( $item_id, 'adicional_mesmo', true);
$endereco_igual = str_replace(',', '.', $endereco_igual);
$endereco_igual = floatval( filter_var( $endereco_igual, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION ) );
$produtoValor = floatval( get_post_meta( $item_id, '_regular_price', true) );
$valorTotal = $produtoValor + ( $endereco_igual * $quantidadeDependentes );
WC()->cart->total = $valorTotal;
WC()->cart->calculate_totals();
wc_price($valorTotal);
}
echo json_encode(
array(
'status' => 'success',
'valorTotal' => wc_price($valorTotal)
));
wp_die();
}
My Ajax request
function contagemDependentes()
{
$contagem = jQuery('.woocommerce-dependentes-contagem');
var quantiaDependentes = jQuery('.woocommerce-dependentes-card').length;
if ( quantiaDependentes <= 0 ) {
var mensagemNumeroDependentes = 'Nenhum dependente informado';
} else if ( quantiaDependentes === 1 ) {
var mensagemNumeroDependentes = '1 dependente';
} else {
var mensagemNumeroDependentes = quantiaDependentes+' dependentes';
}
jQuery($contagem).html(mensagemNumeroDependentes);
var quantiaDependentes = jQuery('.woocommerce-dependentes-card').length + 1;
var dados = {
action: 'add_total_value',
quantiaDependentes: quantiaDependentes
};
jQuery.ajax({
type: 'POST',
url: custom_values.ajaxurl,
data: dados,
dataType: 'json',
success: function(response)
{
console.log(response);
if (response.status === 'success')
{
console.log(response.status);
console.log(response.valorTotal);
var html = "<tr class='order-total'>";
html += "<th>Total</th>";
html += "<td>";
html += response.valorTotal;
html += "</td>";
html += "</tr>";
jQuery( '.order-total' ).remove();
jQuery( 'tfoot' ).append( html );
jQuery( 'body' ).trigger( 'update_checkout' );
}
}
});
}
before function() in functions.php always must be such code
add_action('wp_ajax_your_function_name', 'your_function_name');
add_action('wp_ajax_nopriv_your_function_name', 'your_function_name');
I'm using the starter theme Sage to create a custom Wordpress Theme. I made a very simple infinite scroll system to display every posts. On that point, everything seems to work fine.
Now, I have to display an advertisement block each N posts in the loop. At first sight, it seemed pretty easy, but unfortunately, it was not.
My system works this way :
When the blog page is displayed, the firsts N posts are shown. In that template (Template 1), in the loop, I call a method to check if I have to display an advertisement.
When the user starts to scroll, the next N posts are loaded with AJAX. So, JS calls a Wordpress action which loads the next posts and call the appropriate template (Template 2). In that template, I check again how many posts have passed and if I have to display an advertisement.
Counting informations are stocked in session variables.
The problem is this one :
When the page is loaded, everything is fine. When the infinite scroll operates for the first time, it still fine. But, when the system is called once again, the counting informations stocked in variables session are not good. They take the previous values like if the session variables were not incremented.
At first time, I used some static attributes and a static method but it didn't work. So, I thought it was because the script was not call at once and I used global variables. But it didn't work either.
It seems that the counting works fine but every time the template called by AJAX is loaded, the session variables are reset to their previous values, like if they were late.
Here are the files that I use :
Template 1, it's the index.php of the theme
Template 2, the file called by AJAX
Ajax functions, which contains all the AJAX actions I need in Wordpress
Advertisement Controller, which contains every method relative to the advertisements blocks
A JS file with the different AJAX queries.
Can somebody tell what I am doing wrong? It will be much appreciated.
Please, find my code below:
Template 1
/****************************************/
/********** TEMPLATE 1 - INDEX **********/
/****************************************/
use Roots\Sage\ThemeAdvertisementController;
$AdvertisementController = new ThemeAdvertisementController\AdvertisementController();
$_SESSION['globalCountAds'] = 0;
$_SESSION['globalArrayAds'] = '';
$_SESSION['globalCountPosts'] = 1;
get_template_part('templates/page', 'header');
while (have_posts()) {
the_post();
get_template_part('templates/content', get_post_type() != 'post' ? get_post_type() : get_post_format());
$theLoopAd = $AdvertisementController->getTheLoopAds();
if ( $theLoopAd ) {
echo $theLoopAd;
}
}
Template 2
/**************************************************/
/********** TEMPLATE 2 - CALLDED BY AJAX **********/
/**************************************************/
use Roots\Sage\ThemeAdvertisementController;
$AdvertisementController = new ThemeAdvertisementController\AdvertisementController();
while (have_posts()) {
the_post();
get_template_part( 'templates/content', get_post_type() != 'post' ? get_post_type() : get_post_format() );
$theLoopAd = $AdvertisementController->getTheLoopAds();
if ( $theLoopAd ) {
echo $theLoopAd;
}
}
Advertisement Controller
/**********************************************/
/********** ADVERTISEMENT CONTROLLER **********/
/**********************************************/
namespace Roots\Sage\ThemeAdvertisementController;
use Roots\Sage\ThemeViewController;
use Roots\Sage\ThemePostController;
class AdvertisementController {
public function __construct() {
}
private function getTheAds() {
$PostController = new ThemePostController\PostController();
$postType = 'advertisement';
$nbPosts = -1;
$status = 'publish';
$orderBy = 'title';
$order = 'ASC';
$meta = '';
$taxQuery = '';
$metaQuery = array(
array(
'key' => 'advertisement_in_news',
'value' => true,
'compare' => '='
)
);
return $PostController->getThePosts( $postType, $nbPosts, $status, $orderBy, $order, $meta, $taxQuery, $metaQuery );
}
private function displayTheAd() {
$ViewController = new ThemeViewController\ViewController();
$theAdsArray = $_SESSION['globalArrayAds'];
$theGlobalCountAds = $_SESSION['globalCountAds'];
$thePostID = $theAdsArray->posts[ $theGlobalCountAds ]->ID;
if ( !empty( $thePostID ) ) {
$_SESSION['globalCountAds']++;
$ViewController->postID = $thePostID;
$ViewController->postType = 'advertisement';
$ViewController->nbPosts = 1;
$ViewController->status = 'publish';
$ViewController->orderBy = 'ID';
$ViewController->order = 'ASC';
$ViewController->meta = '';
$ViewController->taxQuery = '';
return $ViewController->displayAdvertisementBlock();
} else {
return false;
}
}
public function getTheLoopAds() {
$arrayAds = $_SESSION['globalArrayAds'];
$adsCount = $_SESSION['globalCountAds'];
$postCount = $_SESSION['globalCountPosts'];
$_SESSION['globalCountPosts']++;
if ( empty( $arrayAds ) ) {
$theAds = $this->getTheAds();
$_SESSION['globalArrayAds'] = $theAds;
}
if ( $postCount%2 == 0 && $postCount != 0 ) {
$displayedAd = $this->displayTheAd();
if ( $displayedAd ) {
return $displayedAd;
} else {
return false;
}
} else {
return false;
}
}
}
Ajax functions
/************************************/
/********** AJAX FUNCTIONS **********/
/************************************/
function infinitePaginateAjax() {
$paged = $_POST['paged'];
$postsPerPage = get_option('posts_per_page');
$args = array( 'paged' => $paged,
'post_status' => 'publish',
'order' => 'DESC',
'post_type' => 'post',
'posts_per_page' => $postsPerPage
);
query_posts( $args );
get_template_part('templates/loop-news');
exit;
}
add_action( 'wp_ajax_infinitePaginateAjax','infinitePaginateAjax' );
add_action( 'wp_ajax_nopriv_infinitePaginateAjax','infinitePaginateAjax' );
function getNbPostsPerPageAjax() {
$value = array();
$nbPostsPerPage = get_option('posts_per_page');
if ( !empty( $nbPostsPerPage ) ) {
$value['answer'] = 1;
$value['value'] = $nbPostsPerPage;
$value['globalCountAds'] = $_SESSION['globalCountAds'];
$value['globalCountPosts'] = $_SESSION['globalCountPosts'];
} else {
$value['answer'] = 0;
$value['value'] = 0;
}
$data = json_encode( $value );
die( $data );
}
add_action( 'wp_ajax_getNbPostsPerPageAjax','getNbPostsPerPageAjax' );
add_action( 'wp_ajax_nopriv_getNbPostsPerPageAjax','getNbPostsPerPageAjax' );
function getTotalPostsAjax() {
global $wp_query;
$value = array();
$nbPosts = wp_count_posts( 'post' );
$nbPublishedPosts = $nbPosts->publish;
if ( !empty( $nbPublishedPosts ) ) {
$value['answer'] = 1;
$value['value'] = $nbPublishedPosts;
$value['globalCountAds'] = $_SESSION['globalCountAds'];
$value['globalCountPosts'] = $_SESSION['globalCountPosts'];
} else {
$value['answer'] = 0;
$value['value'] = 0;
}
$data = json_encode( $value );
die( $data );
}
add_action( 'wp_ajax_getTotalPostsAjax','getTotalPostsAjax' );
add_action( 'wp_ajax_nopriv_getTotalPostsAjax','getTotalPostsAjax' );
JS
jQuery(document).ready(function() {
var pageInfinite = '.infinite-page';
var loaderInfinite = '.infinite-loader';
var contentInfinite = '.main-content';
var getTotalPosts = function() {
var totalPosts = '';
jQuery.ajax({
type : "POST",
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
async: false,
url : data_sage_js.ajaxurl,
data: {
action: 'getTotalPostsAjax'
},
success: function( data ) {
data = jQuery.parseJSON( data );
if ( data.answer !== 0 ) {
totalPosts = data.value;
} else {
totalPosts = 0;
}
},
error: function () {
console.log( 'error: cannot get nb posts' );
totalPosts = 0;
}
});
return totalPosts;
};
var getNbPostsPerPage = function() {
var postsPerPage = '';
jQuery.ajax({
type : "POST",
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
async: false,
url : data_sage_js.ajaxurl,
data: {
action: 'getNbPostsPerPageAjax'
},
success: function( data ) {
data = jQuery.parseJSON( data );
if ( data.answer !== 0 ) {
postsPerPage = data.value;
} else {
postsPerPage = 0;
}
},
error: function () {
console.log( 'error: cannot get max posts page' );
postsPerPage = 0;
}
});
return postsPerPage;
};
var infiniteLoadArticle = function( pageNumber ) {
jQuery( loaderInfinite ).show( 'fast' );
setTimeout(function(){
jQuery.ajax({
type:'POST',
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
async: false,
url: data_sage_js.ajaxurl,
data: {
action: 'infinitePaginateAjax',
paged: pageNumber
},
success: function( html ) {
jQuery( loaderInfinite ).hide( 'fast' );
jQuery( contentInfinite ).append( html);
}
});
}, 1000);
return false;
};
if ( jQuery( pageInfinite ).length > 0 ) {
var postsTotal = parseInt( getTotalPosts() );
var incPost = parseInt( getNbPostsPerPage() );
var postsCount = parseInt( incPost );
var nbPage = parseInt( 1 );
var nbTotalPage = parseInt( Math.ceil( postsTotal / incPost ) );
jQuery(window).scroll(function() {
if ( jQuery(window).scrollTop() === jQuery(document).height() - jQuery(window).height() ) {
if ( nbTotalPage > nbPage ) {
nbPage++;
infiniteLoadArticle( nbPage );
postsCount = postsCount + incPost;
} else if ( nbTotalPage <= nbPage ) {
return false;
}
}
});
}
});
EDIT/SOLVE
So, after hours of searching, I decided to do it another way : I decided to use the "posts_per_page" attribute to count posts and to know when I have to display an advertisement. I just had to refactor a few functions and methods.
Do session variables work outside of the Ajax Calls? on page refresh etc.
If they do not then it may be to do with the fact that wordpress can treat session variables very weirdly.
I think its for security but if in your php.ini if 'register_globals' is on it unregisters all of the php globals.
Reference: WP_unregister_GLOBALS
In which case I believe things like https://wordpress.org/plugins/wp-session-manager/ fill in the blanks for this, or you could turn off register_globals in your php.ini (although I dont understand the repercussions of doing that sorry