【问题标题】:php how to set a value for not found rows in arrayphp如何为数组中未找到的行设置值
【发布时间】:2021-08-11 00:42:48
【问题描述】:

我是 Php 7 的新手,我正在尝试编写一个函数来检查数据库中产品是否在某个月份有 qte(从日期字段中提取),但如果产品日期没有有这个月,所以所有数据都必须添加到数组中,但 qte 必须设置为零到那个月的值,我只得到了月份中现有 qte 的结果,但是产品做的月份的结果没有任何 qte 不在我的最终数组中

这是我尝试过的:

   public function getProductsStatsByMonths() {
    $today =  date("Y-m-d"); 
    $date_arr = explode("-", $today);  
    $year = $date_arr[0];
    $month = $date_arr[1];
    $day = $date_arr[2];
 
    $prods = array();
    $months = array(
    1 ,
    2 ,
    3 ,
    4 ,
    5 ,
    6 ,
    7 ,
    8 ,
    9 ,
    10 ,
    11 ,
    12
 );

    foreach ($months as $month){
        $stmt = $this->conn->prepare("SELECT sum(qte) as total,ligne, produit,date,heure,qte FROM production where YEAR(date) = ? and MONTH(date) = ? group by LOWER(ligne) ");
        $stmt->execute([$year,$month]);

        while( $row = $stmt->fetch(pdo::FETCH_ASSOC)){
            array_push($prods, new ProductionByMonth(0,$row["ligne"],$row["produit"],$row["date"],$row["heure"],$row["qte"],$month,$year));
        }
    }

    echo json_encode($prods);
   
   }

我得到的结果:

[
    {
        "id": 0,
        "ligne": "Biscuit",
        "produit": "Major",
        "date": "2021-08-10",
        "heure": "10:00",
        "qte": "130",
        "month": 8,
        "year": "2021"
    },
    {
        "id": 0,
        "ligne": "Eau",
        "produit": "Safia 1.5",
        "date": "2021-08-10",
        "heure": "14:00",
        "qte": "200",
        "month": 8,
        "year": "2021"
    },
    {
        "id": 0,
        "ligne": "Lait",
        "produit": "Vitalait 1/2",
        "date": "2021-08-10",
        "heure": "8:00",
        "qte": "80",
        "month": 8,
        "year": "2021"
    },
    {
        "id": 0,
        "ligne": "Salami",
        "produit": "Mazraa",
        "date": "2021-08-10",
        "heure": "8:00",
        "qte": "100",
        "month": 8,
        "year": "2021"
    },
    {
        "id": 0,
        "ligne": "Yaourt",
        "produit": "Delice",
        "date": "2021-08-10",
        "heure": "12:00",
        "qte": "150",
        "month": 8,
        "year": "2021"
    }
]

例如,此行包含此产品,该产品在第 8 个月有一个 qte:

{
            "id": 0,
            "ligne": "Biscuit",
            "produit": "Major",
            "date": "2021-08-10",
            "heure": "10:00",
            "qte": "130",
            "month": 8,
            "year": "2021"
        },

我的目标是在剩下的几个月里为同一产品添加额外的行,但将它们的 qte 设置为“0”

我的目标是确保我的数组最后还包含没有 qte (quantity) 的月份,并且 qte 的值必须设置为零,并且数据必须像所有存在的数据一样显示,除了字段qte的值

【问题讨论】:

    标签: php


    【解决方案1】:

    这里描述了适用于此类问题的一般方法。

    1. 从数据库数据中获取唯一产品。
    2. 创建包含所有所需日期的日历。
    3. 在 PHP 中对来自 1 和 2 的数据集执行相当于数据库“交叉连接”的操作,并将生成的所有组合的 qte 设置为 0。
    4. 用非零数量覆盖数据库中实际存在的那些组合的 qte。

    “组合”是指产品和日期。因此,如果您创建一个包含 2021 年 12 个月并有 5 个产品的日历,那么第 3 步将生成 60 个组合。

    另外,如果$day 没有在代码中的任何地方使用,则无需创建它。

    编辑 - 这是代码:

    // this is modified sample data
    // changes made:
    // set date values to first day of each month
    // added "productId" with fabricated values since "id" was 0 for everything in original data and therefore not useful
    // added another entry for productID = 12 with a different date
    $prods = '[
        {
            "id": 0,
            "ligne": "Biscuit",
            "produit": "Major",
            "date": "2021-08-01",
            "heure": "10:00",
            "qte": "130",
            "month": 8,
            "year": "2021",
            "productId": 12
        },
        {
            "id": 0,
            "ligne": "Biscuit",
            "produit": "Major",
            "date": "2021-09-01",
            "heure": "12:00",
            "qte": "158",
            "month": 9,
            "year": "2021",
            "productId": 12
        },
        {
            "id": 0,
            "ligne": "Eau",
            "produit": "Safia 1.5",
            "date": "2021-08-01",
            "heure": "14:00",
            "qte": "200",
            "month": 8,
            "year": "2021",
            "productId": 16
        },
        {
            "id": 0,
            "ligne": "Lait",
            "produit": "Vitalait 1/2",
            "date": "2021-08-01",
            "heure": "8:00",
            "qte": "80",
            "month": 8,
            "year": "2021",
            "productId": 38
        },
        {
            "id": 0,
            "ligne": "Salami",
            "produit": "Mazraa",
            "date": "2021-08-01",
            "heure": "8:00",
            "qte": "100",
            "month": 8,
            "year": "2021",
            "productId": 27
        },
        {
            "id": 0,
            "ligne": "Yaourt",
            "produit": "Delice",
            "date": "2021-08-01",
            "heure": "12:00",
            "qte": "150",
            "month": 8,
            "year": "2021",
            "productId": 22
        }
    ]';
    
    // create an associative array of products - assign a unique value as key (this will be useful in a later step)
    $products = [];
    foreach (json_decode($prods, true) as $product) {
        $key = $product['productId'] . '_' . $product['date'];
        $products[$key] = $product;
    }
    
    // get unique product IDs from database data
    $productIds = [];
    foreach ($products as $product) {
        $productIds[] = $product['productId'];
    }
    $uniqueProductIds = array_unique($productIds);
    
    // create a calendar of all possible dates needed (just did a year's worth in this example)
    $year = date("Y");
    $buckets = [];
    for ($month = 1; $month <= 12; $month++) {
        $buckets[] = date($year . '-' . str_pad($month, 2, '0', STR_PAD_LEFT) . '-01');
    }
    
    // do cross join equivalent to create all combinations of bucket and unique product ID (in this example: 12 buckets x 5 unique products IDs = 60 combinations)
    $cartesianProduct = [];
    foreach ($buckets as $bucket) {
        foreach ($uniqueProductIds as $uniqueProductId) {
            $data = [];
            $data['date'] = $bucket;
            $data['id'] = $uniqueProductId;
            $data['qte'] = 0;
            $key = $uniqueProductId . '_' . $bucket;
            $cartesianProduct[$key] = $data;
        }
    }
    
    // overwrite combination data (in $cartesianProduct) with data from database (in $products) - this is where $key in $products and in $cartesianProduct is critical
    $result = array_merge($cartesianProduct, $products);
    
    // look at results    
    echo '<pre>' . print_r($result, 1) . '</pre>';
    

    【讨论】:

    • 你好,谢谢你的回答,但我没看懂一半
    • 创建一个包含所有所需日期的日历。在 PHP 中对来自 1 和 2 的数据集执行等效的数据库“交叉连接”,并将生成的所有组合的 qte 设置为 0。
    • 交叉连接是什么意思?
    • 交叉连接是指笛卡尔积。见stackoverflow.com/questions/21738966/…
    • @Roadtoengineering 我添加了代码,以便您了解它是如何工作的。要查看任何中间数据集,只需模仿最后一行代码。例如,要查看 $buckets 中的内容,请添加以下代码行:echo '&lt;pre&gt;' . print_r($buckets, 1) . '&lt;/pre&gt;'; 以在浏览器中显示其内容。
    猜你喜欢
    • 2012-08-19
    • 2017-10-26
    • 2011-07-23
    • 2012-12-31
    • 1970-01-01
    • 2019-02-25
    • 2014-08-20
    • 1970-01-01
    • 2013-11-06
    相关资源
    最近更新 更多