为购物车内的foreach()提供的参数无效,

时间:2018-04-02 05:29:19

标签: php

enter image description here 我试图在我的购物车阵列中获得超过1个项目,但我遇到了一个问题

使用post方法

插入1个项目后,这是我的数据库

enter image description here 项目在db中定义为文本

尝试插入第二个产品后,项目结果将被覆盖。

点击添加到购物车后我的开发者工具输出

enter image description here

添加

我正在使用我的模态> https://pastebin.com/HKSRTG4L中的添加到购物车按钮,该按钮通过ajax提交并解析为add-cart.php

我添加到购物车功能的位置:https://pastebin.com/guv0rB6x

enter image description here

这是我的cart.php代码:

<?php
include_once $_SERVER['DOCUMENT_ROOT']."/EcomApp/konfiguracija.php";
require_once $_SERVER['DOCUMENT_ROOT'].'/EcomApp/config.php';

include 'include/head.php';
include 'include/izbornik.php';


if($cart_id != ''){
  $cartQ = $veza->prepare("SELECT * FROM cart WHERE id = '$cart_id';");
  $cartQ->execute();
  $result= $cartQ->fetch(PDO::FETCH_ASSOC);
  $items = json_decode($result['items'],true);var_dump($items) ;
  $i = 1;
  $sub_total = 0;
  $item_count = 0;

}

?>

<div class="col-md-12">

  <div class="row">
<h2 class ="text-center">Your Shopping Cart </h2><hr>
<?php if($cart_id =='') :?>



  <div class="bg-danger">
   <p class="text-center text-danger">
     Your shopping cart is empty!
 </p>
  </div>
<?php else: ?>
<table class="table" >
<thead><th>#</th><th>Item</th><th>Price</th><th>Quantity</th><th>Size</th><th>Sub Total</th></thead>
<tbody>

  <?php
  foreach ($items as $item){
        $product_id =$item['id'];
        $productQ = $veza ->prepare("SELECT * FROM products WHERE id = '$product_id'");
        $productQ ->execute();
        $product= $productQ->fetch(PDO::FETCH_ASSOC);
        $sArray = explode (',',$product['sizes']);
        foreach($sArray as $sizeString){
          $s = explode(':',$sizeString);
          if($s[0] ==$item['size']){
            $available = $s[1];
          }
        }
            ?>
            <tr>
            <td><?=$i;?></td>
            <td><?=$product['title'];?></td>
            <td><?=$product['price'];?></td>
            <td><?=$item['quantity'];?></td>
            <td><?=$item['size'];?></td>
            <td><?=$item['quantity'] * $product['price'];?></td>
            </t>
      <?php } ?>

</tbody>
</table>
<?php endif; ?>
  </div>

<?php include 'include/footer.php';?>

我肯定93%确定问题出在数组合并,因为目前插件会用新结果覆盖行而不添加到数组。

      <?php

require_once $_SERVER['DOCUMENT_ROOT'].'/EcomApp/konfiguracija.php';
require_once $_SERVER['DOCUMENT_ROOT'].'/EcomApp/config.php';
$product_id = sanitize($_POST['product_id']);
$size = sanitize($_POST['size']);
$available = sanitize($_POST['available']);
$quantity = sanitize($_POST['quantity']);
$item = array();
$item[]= array(
  'id'        => $product_id,
  'size'      => $size,
  'quantity'  => $quantity,
);

$domain = ($_SERVER['HTTP_HOST'] != 'localhost')?'.'.$_SERVER['HTTP_HOST']:false;
$query = $veza->prepare("SELECT * FROM products WHERE id = '$product_id'");
$query ->execute();
$product = $query->fetch(PDO::FETCH_ASSOC);
$_SESSION['success_launch'] = $product['title']. 'was added to your cart.';

//check does cookie cart exist
if($cart_id != ''){
  $cartQ= $veza->prepare("SELECT * FROM cart WHERE id = '$cart_id'");
  $cart = $cartQ->fetch(PDO::FETCH_ASSOC);
  $previous_items = json_decode($cart['items'],true);
  $item_match = 0;
  $new_items = array();
  foreach ($prevous_items as $pitem){
     if($item[0]['id']==$pitem['id'] && $item[0]['size'] == $pitem['size']){
       $pitem ['quantity']= $pitem['quantity']+$item[0]['quantity'];
       if ($pitem['quantity']>$available){
         $pitem['quantity'] = $available;

       }
       $item_match = 1;
     }
     $new_items[] = $pitem;
  }
  if($item_match != 1){
    $new_items = array_merge($item,(array)$previous_items);
  }
  $items_json = json_encode($new_items);
  $cart_expire = date("Y-m-d H:i:s", strtotime("+30 days"));
  $something=$veza->prepare("UPDATE cart SET items = '$items_json',expire_date= '$cart_expire'WHERE id ='$cart_id'");
  $something ->execute();
  setcookie(CART_COOKIE,'',1,'/',$domain,false);
  setcookie(CART_COOKIE,$cart_id,CART_COOKIE_EXPIRE,'/',$domain,false);

}else {

插入

//add cart inside database
  $items_json = json_encode($item);
  $cart_expire = date("Y-m-d H:i:s",strtotime("+30 days"));
  $smth=$veza->prepare("INSERT INTO cart (items,expire_date) VALUES ('$items_json','$cart_expire')");

  $smth->execute();
  $cart_id = $veza->lastInsertId();

  setcookie(CART_COOKIE,$cart_id,CART_COOKIE_EXPIRE,'/',$domain,false);

}
  var_dump($cart_id);

?>

添加到购物车功能https://pastebin.com/guv0rB6x

function add_to_cart(){
  jQuery('#modal_errors').html("");
  var size = jQuery('#size').val();
  var quantity = jQuery('#quantity').val();
  var available = jQuery('#available').val();
  var error = '';
  var data = jQuery("#add_product_form").serialize();
  if(size == '' || quantity == '' || quantity == 0){
    error += '<p class= "bg-danger text-center">You must choose a size and quantity</p>';
    jQuery('#modal_errors').html(error);
    return;
  }else if (quantity>available){
    error += '<p class= "bg-danger text-center">There are only '+available+' available.</p>';
    jQuery('#modal_errors').html(error);
     return;
  }else{
    jQuery.ajax({
               url: '/EcomApp/admin/parsers/add_cart.php',
               method : 'post',
               data : data,
               success : function(){
                 location.reload();
               },
               error : function(){alert("Something went wrong");}

    });
  }
}

konfiguracija.php 第65行有一个(未定义的偏移量:1)

  

$ user_data ['last'] = $ fn 1;

但我认为它没有直接连接到功能

try{
    $veza = new PDO("mysql:host=" . $host . ";dbname=" . $dbname,$dbuser,$dbpass);
    $veza->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $veza->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8';");
    $veza->exec("SET NAMES 'utf8';");
}catch(PDOException $e){

    switch($e->getCode()){
        case 1049:
            header("location: " . $eone . "error/wrongDBname.html");
            exit;
            break;
        default:
            header("location: " . $eone . "error/error.php?code=" . $e->getCode());
            exit;
            break;
    }


}
require_once $_SERVER['DOCUMENT_ROOT'].'/EcomApp/config.php';
require_once BASEURL.'helpers/helpers.php';
session_start();

//
$cart_id = '';
 if(isset($_COOKIE[CART_COOKIE])){
     $cart_id = sanitize($_COOKIE[CART_COOKIE]);
 }

if(isset($_SESSION['SDUser'])){
    $user_id =$_SESSION['SDUser'];
    $query = $veza->prepare("SELECT* FROM korisnik WHERE id ='$user_id'");
    $query->execute();
    $user_data = $query->fetch(PDO::FETCH_ASSOC);
    $fn = explode(' ', $user_data['full_name']);
    $user_data['first'] = $fn[0];
    $user_data['last'] = $fn[1];
     // print_r($user_data);

}

if(isset($_SESSION['success_launch'])){
    echo '<h1><p class="text-success">'.$_SESSION['success_launch'].'</p></h1>';
    unset($_SESSION['success_launch']);
}

if(isset($_SESSION['error_launch'])){
    echo '<div class="success"><p class="text-success">'.$_SESSION['error_launch'].'</p></div>';
    unset($_SESSION['error_launch']);
}

3 个答案:

答案 0 :(得分:0)

在add_cart.php中:

$previous_items = json_decode($cart['items'],true);
$item_match = 0;
$new_items = array();
foreach ($prevous_items as $pitem){

请注意,$previous_items$prevous_items不同。

这就是你获得原因的原因:

  

注意:未定义的变量:prevous_items in   第29行/opt/lampp/htdocs/EcomApp/admin/parsers/add_cart.php

你没有采纳我以前的建议,让你的生活更轻松。

显然工作代码还不够。始终验证并快速失败(http://www.practical-programming.org/ppl/docs/articles/fail_fast_principle/fail_fast_principle.html):

if(!$cart_id){
  $cartQ = $veza->prepare("SELECT * FROM cart WHERE id = ?");
  $cartQ->execute([(int)$cart_id]);
  $result= $cartQ->fetch(PDO::FETCH_ASSOC);
  if (!isset($result['items'])) {
      throw new \RuntimeException("The items were not found.");
  }
  $items = json_decode($result['items'],true);
  if (!$items) {
      throw new \RuntimeException("Invalid items format.");
  }
  $i = 1;
  $sub_total = 0;
  $item_count = 0;
}

如上所述,做这样的事情:

<?php

$validKeys = ['product_id', 'size', 'available', 'quantity'];
foreach ($validKeys as $key) {
    if (!isset($_POST[$key])) {
        throw new RuntimeException("Parameter $key is missing.");
    }
}

require_once $_SERVER['DOCUMENT_ROOT'].'/EcomApp/konfiguracija.php';
require_once $_SERVER['DOCUMENT_ROOT'].'/EcomApp/config.php';

$product_id = sanitize($_POST['product_id']);
$size = sanitize($_POST['size']);
$available = sanitize($_POST['available']);
$quantity = sanitize($_POST['quantity']);

很可能你在客户端错过了某些东西(javascript或HTML表单),例如,你可能拼写错误&#34; product_id&#34;。

<强>增加:

https://pastebin.com/guv0rB6x

function add_to_cart(){
  jQuery('#modal_errors').html("");
  var size = jQuery('#size').val();
  var quantity = jQuery('#quantity').val();
  var available = jQuery('#available').val();
  var error = '';
  var data = jQuery("#add_product_form").serialize();
  if(size == '' || quantity == '' || quantity == 0){
    error += '<p class= "bg-danger text-center">You must choose a size and quantity</p>';
    jQuery('#modal_errors').html(error);
    return;
  }else if (quantity>available){
    error += '<p class= "bg-danger text-center">There are only '+available+' available.</p>';
    jQuery('#modal_errors').html(error);
     return;
  }else{
    jQuery.ajax({
               url: '/EcomApp/admin/parsers/add_cart.php',
               method : 'post',
               data : data,
               success : function(){
                 location.reload();
               },
               error : function(){alert("Something went wrong");}

    });
  }
}

您没有检查&#34; product_id&#34;字段是空的。

<强>增加:

替换:

  $previous_items = json_decode($cart['items'],true);
  $item_match = 0;
  $new_items = array();
  foreach ($prevous_items as $pitem){
     if($item[0]['id']==$pitem['id'] && $item[0]['size'] == $pitem['size']){
       $pitem ['quantity']= $pitem['quantity']+$item[0]['quantity'];
       if ($pitem['quantity']>$available){
         $pitem['quantity'] = $available;

       }
       $item_match = 1;
     }
     $new_items[] = $pitem;
  }
  if($item_match != 1){
    $new_items = array_merge($item,(array)$previous_items);
  }

有这样的事情:

$previous_items = json_decode($cart['items'], true);
if (!$previous_items) {
      $previous_items = array();
}
$items_by_unique = array();
foreach (array_merge($item, $previous_items) as $item) {
    if (!isset($item['id'], $item['size'], $item['quantity'])) {
      throw new RuntimeException('Found a invalid invalid data: ' . json_encode($item));
    }
    $unique = $item['id'] . '-' . $item['size'];
    if (isset($items_by_unique[$unique])) {
      $old_item = $items_by_unique[$unique];
      $item['quantity'] = $old_item['quantity'];
    }
    if ($item['quantity'] > $available) {
      $item['quantity'] = $available;
    }
    $items_by_unique[$unique] = $item;
}
$items_json = json_encode(array_values($items_by_unique));

答案 1 :(得分:0)

代码有很多问题很难找到错误,而且很难回答一个问题,这个问题总是在增加几个问题,好像我们正在免费提供调试服务......我们可能会在这里讨论几个小时和几天,就像工作一样,直到一切都得到纠正。在这种情况下,帮助和照顾我们的个人生活和工作将非常困难。

无论如何,我将列举一些使代码很难调试的问题。

大多数返回的值都没有经过验证,假设它们是预期的,而是在出现错误时立即失败。这意味着你可能只会注意到很多错误并寻找其来源,这可能是在另一个文件中。

例如,当你做这样的事情时:

$query = $veza->prepare("SELECT * FROM products WHERE id = '$product_id'");
$query->execute();
$product = $query->fetch(PDO::FETCH_ASSOC);

您应该始终检查$product是否至少不为空:

if (!$product) {
    throw new RuntimeException("The product #$product_id" was not found.");
}

此外,将变量放在SQL语句中可能非常危险。如果你正在使用准备好的陈述,你应该这样做:

$query = $veza->prepare("SELECT * FROM products WHERE id = ? LIMIT 1");
$query->execute([$product_id]);

代码没有利用可重用性。您可以实现类或函数并单独测试它们。

例如,你可以做这样的事情:

<?php

/**
 * Add a new item ...
 * 
 * If it's being requested more items then available ...
 *
 * @param array $newItem The new item that should be added.
 * @param array $items The list of items where the item should be added.
 * @param integer $available Available items.
 * @return void
 */
function add_item(array $newItem, array &$items, int $available=MAX_INT_MAX)
{
  throw_error_if_invalid_item($newItem);

  $unique = $newItem['id'] . '-' . $newItem['size'];
  if (isset($items_by_unique[$unique])) {
    add_item_quantity(
      $items_by_unique[$unique],
      $item['quantity'],
      $available
    );
  } else {
    $items[] = $newItem;
  }
}

/**
 * Add quantity ...
 *
 * @param array $item ...
 * @param integer $moreQuantity ...
 * @param integer $available ...
 * @return void
 */
function add_item_quantity(array &$item, int $moreQuantity, int $available=MAX_INT_MAX)
{
  $item['quantity'] += $moreQuantity;
  if ($item['quantity'] > $available) {
    $item['quantity'] = $available;
  }
}

/**
 * ...
 *
 * @param array $item ...
 * @return void
 */
function throw_error_if_invalid_item(array $item)
{
  if (!isset($item['id'], $item['size'], $item['quantity'])) {
    throw new RuntimeException(
      'Found a invalid invalid item data: ' . json_encode($item)
    );
  }
}

然后,您可以在隔离文件中进行单独测试:

<?php
$item = array(
  'id' => 10,
  'size' => 'm',
  'quantity' => 2,
);
add_item_quantity($item, 3, 10);
if ($item['quantity'] != 5) {
   echo "wrong! quantity = {$item['quantity']}\n";
} else {
  echo "correct!\n";
}

如果您将类或函数放在专用文件中,则可以将它们重用为库,使代码易于阅读,测试和安全:

<?php
throw_error_if_invalid_item($_POST);
$newItem = create_item($_POST);
$items = fetch_cart_items($cart_id);
add_item($newItem, $items, 10);
save_cart_items($items);
show_json_items($json);

使用类会更容易(例如:您不必担心丢失数组键)并且可以使用PHPUnit自动测试所有函数和方法。检查我是如何为一个简单的项目做的那样:

https://github.com/pedroac/nonce4php

您还可以使脚本出现任何错误或警告:

<?php
set_error_handler(
    function (int $errno , string $errstr, string $errfile, int $errline) {
        http_response_code(500);
        echo "ERROR #$errono:$errfile:$errline: $errstr";
        die();
    }
);

set_exception_handler(
    function (Throwable $exception) {
        http_response_code(500);
        echo $exception->getMessage();
        die();
    }
);

如果您按照good practices进行操作,发现错误会更容易,并让其他人帮助您。

答案 2 :(得分:0)

我通过将array_merge的第二个参数强制转换为数组来修复此问题:

$new_items = array_merge($item, (array)$previous_items);