【问题标题】:PHP / MySQL price matrix form validationPHP / MySQL价格矩阵表单验证
【发布时间】:2012-05-10 19:05:13
【问题描述】:

我确定解决方案相当简单,但我的大脑今天似乎并没有处于正确的状态。我有一个 MySQL 表来存储我的产品定价矩阵。

ID     PRODUCT     MINIMUM     PRICE
1      1           2           15
2      1           4           12
3      1           6           10

简单解释一下,对于 id 为 1 的产品,如果客户的购物篮中至少有 2 件商品,那么每件商品的价格将降至 15 英镑。如果用户随后将另外 2 件产品放入他们的购物篮中,则每件的价格将降至 12 英镑。

问题:我需要一种在每次添加新价格层时验证新价格层的方法。因此,如果有人想添加一个新层:

ID     PRODUCT     MINIMUM     PRICE
4      1           3           16

这是不允许的,因为在这种情况下,如果用户选择购买三件而不是两件,每件商品的价格都会上涨。因此,我需要确保输入的价格随着数据库中已有值的数量增加而减少。

$query = 'select id,minimum,price from `cat.tier_price` where product = %d order by minimum asc;';
$query = sprintf($query, (int)$identity);
if(!$return = $db->query($query)){
    echo 'MySQL error!';
}else{
    $quantity = $_POST['quantity'];
    $price = $_POST['quantity'];

    if($return->num_row){
        while($tier = $return->fetch_object){

        }
    }
}

如果我说得不够清楚,请说。任何帮助将不胜感激。

【问题讨论】:

  • [用于验证最小值。 3] 获取低于 3 的现有最小值(此处:2)并检查给定价格是否小于与此处最小值相关的价格。 2 (=15)

标签: php mysql validation mysqli


【解决方案1】:

这可以通过一个简单的函数来完成:

function validateTier($productId, $minimum, $price) {
    // check if the new tier is not higher price for higher minimum
    $query = 'SELECT 1 AS exists FROM `cat.tier_price` WHERE `product` = {$productId} AND `minimum` < {$minimum} AND `price` > {$price} ORDER BY `minimum` DESC LIMIT 1';
    $res = mysql_query($query);
    $result = mysql_fetch_assoc($res);

    if(isset($result['exists']) && $result['exists']) {
        // check if the new tier is not lower price for lower minimum
        $query = 'SELECT 1 AS exists FROM `cat.tier_price` WHERE `product` = {$productId} AND `minimum` > {$minimum} AND `price` < {$price} ORDER BY `minimum` ASC LIMIT 1';
        $res2 = mysql_query($query);
        $result2 = mysql_fetch_assoc($res2);

        if(isset($result2['exists']) && $result2['exists']) return true;
    }

    return false;
}

然后,每当需要添加新层时,您都会调用此函数。该函数试图准确地选择一条记录,其中最小值低于插入的记录,而价格高于插入的记录。如果此查询成功,它将返回 1(视为 true),这意味着可能会插入新的撕裂。否则将返回 FALSE,表示新层不正确。

但我认为这也应该起到作用(而且更简单):

function validateTier($productId, $minimum, $price) {
    // check if the new tier is not higher price for higher minimum
    $query = 'SELECT 1 AS exists FROM `cat.tier_price` WHERE `product` = {$productId} AND ((`minimum` < {$minimum} AND `price` > {$price}) OR (`minimum` > {$minimum} AND `price` < {$price})) LIMIT 1';
    $res = mysql_query($query);
    $result = mysql_fetch_assoc($res);

    if(isset($result['exists']) && $result['exists']) return true;

    return false;
}

请告诉我这是否也有效。

【讨论】:

  • 为此干杯,这适用于“3,16”。但是,如果我尝试“3,11”,这也不应该被允许价格低于至少 4 种产品的价格?抱歉我没有在上面提到这是我的错误。
  • @Adam 我编辑了函数,现在它不应该允许低于最低价格的更低价格...
  • 感谢大家,我从未见过如此精彩的问题回答。我的大脑现在有点暖和了,非常感谢。
【解决方案2】:

对于此类数据验证,您可能应该使用trigger,它会在操作完成之前对无效数据引发错误(例如,通过调用不存在的过程);因此,MySQL 将中止任何插入无效数据的尝试:

DELIMITER ;;

CREATE TRIGGER foo BEFORE INSERT ON tier_price FOR EACH ROW
  IF (
    SELECT COUNT(*)
    FROM   tier_price
    WHERE  product = NEW.product
       AND (
              (minimum > NEW.minimum AND price > NEW.price)
           OR (minimum < NEW.minimum AND price < NEW.price)
       )
  ) > 0 THEN
    CALL raise_error;
  END IF;;

DELIMITER ;

如果tier_price 中的记录也可能会更新,您可能也需要类似的触发器BEFORE UPDATE

【讨论】:

  • 这是一个有趣的方法,我以前没有考虑过使用。我目前收到错误:不允许从触发器返回结果集
  • @Adam:这会教我尝试过度优化。请参阅上面的回滚版本。
  • 感谢大家,我从未见过如此精彩的问题回答。我的大脑现在有点暖和了,非常感谢。
【解决方案3】:

我会反过来做。它将处理给定 product_id 的 price_matrix 表中没有条目的情况。

    set @product_id := 1;
    set @minimum :=3;
    set @price :=16;

    select count(*) as count from price_matrix where product_id = @product_id and 
    (
        ( minimum > @minimum and price > @price )
        or 
        ( minimum < @minimum and price < @price ) 
    )

   If count > 0:
       This entry is not permitted
   else :
       Permitted

【讨论】:

  • 感谢大家,我从未见过如此精彩的问题回答。我的大脑现在有点暖和了,非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-25
  • 1970-01-01
相关资源
最近更新 更多