You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP:在foreach循环中检查产品借阅日期范围/可用性

实现图书馆产品借阅系统:表格展示与可用性标记方案

嘿,我来帮你梳理下怎么搞定这个需求,分几个关键步骤推进,都是实际开发中常用的思路:

第一步:从数据库拉取基础产品数据

首先得把符合基础条件的产品(比如未下架、属于当前馆的产品)和它们的有效借阅记录一起查出来——毕竟要判断可用性,得知道每个产品已经被借走的时间段对吧?

以MySQL为例,给你个参考查询语句:

SELECT 
    p.product_id,
    p.product_name,
    p.category,
    br.start_date AS borrowed_start,
    br.end_date AS borrowed_end
FROM products p
LEFT JOIN borrow_records br 
    ON p.product_id = br.product_id 
    AND br.status = 'active' -- 只关联还没归还的有效借阅
WHERE p.is_active = 1 -- 基础筛选:只取启用的产品

用LEFT JOIN是为了把那些从没被借过的产品也包含进来,这类产品的借阅日期字段会是NULL,默认就是可用的。

第二步:判断产品可用性的核心逻辑

用户输入的是MM/DD/YYYY格式的日期范围,首先得把所有日期转成统一可比较的格式(比如前端用Date对象,后端用对应语言的日期类型),然后判断用户要借的时间段和产品已被占用的时间段有没有重叠——只要有重叠,产品就不可用。

给你写个通俗易懂的伪代码逻辑:

function checkAvailability(userStart, userEnd, borrowedRecords) {
    // 先把用户输入的日期转成可比较的Date对象
    const userStartDate = new Date(userStart);
    const userEndDate = new Date(userEnd);

    // 没有任何借阅记录?直接返回可用
    if (!borrowedRecords || borrowedRecords.length === 0) return true;

    // 遍历每条借阅记录,检查是否重叠
    for (const record of borrowedRecords) {
        const borrowStart = new Date(record.borrowed_start);
        const borrowEnd = new Date(record.borrowed_end);

        // 重叠判断规则:用户的起始日期 ≤ 借阅结束日期,且用户的结束日期 ≥ 借阅起始日期
        if (userStartDate <= borrowEnd && userEndDate >= borrowStart) {
            return false; // 有重叠,不可用
        }
    }
    return true; // 没重叠,可用
}

提醒下:一定要提前做用户输入的日期格式校验,比如用户输了个无效日期,得给个友好提示,别直接进判断逻辑。

第三步:表格渲染与状态可视化

拿到处理好的产品列表(带可用性状态)后,前端渲染表格的时候,用视觉差异区分状态,比如可用的标绿打勾,不可用的标红打叉,用户一眼就能看明白。

给你个React的示例代码(其他框架思路类似):

import React from 'react';

function BorrowTable({ products, userSelectedStart, userSelectedEnd }) {
    // 提前把每个产品的可用性算好
    const processedProducts = products.map(product => ({
        ...product,
        isAvailable: checkAvailability(userSelectedStart, userSelectedEnd, product.borrowedRecords)
    }));

    return (
        <table style={{ borderCollapse: 'collapse', width: '100%', marginTop: '1rem' }}>
            <thead>
                <tr style={{ backgroundColor: '#f5f5f5' }}>
                    <th style={{ border: '1px solid #ddd', padding: '8px' }}>产品ID</th>
                    <th style={{ border: '1px solid #ddd', padding: '8px' }}>产品名称</th>
                    <th style={{ border: '1px solid #ddd', padding: '8px' }}>分类</th>
                    <th style={{ border: '1px solid #ddd', padding: '8px' }}>状态</th>
                </tr>
            </thead>
            <tbody>
                {processedProducts.map(prod => (
                    <tr 
                        key={prod.product_id} 
                        style={{ 
                            backgroundColor: prod.isAvailable ? '#e8f8f5' : '#fff5f5',
                            textAlign: 'center'
                        }}
                    >
                        <td style={{ border: '1px solid #ddd', padding: '8px' }}>{prod.product_id}</td>
                        <td style={{ border: '1px solid #ddd', padding: '8px' }}>{prod.product_name}</td>
                        <td style={{ border: '1px solid #ddd', padding: '8px' }}>{prod.category}</td>
                        <td style={{ border: '1px solid #ddd', padding: '8px' }}>
                            {prod.isAvailable ? (
                                <span style={{ color: '#27ae60', fontWeight: 'bold' }}>✅ 可用</span>
                            ) : (
                                <span style={{ color: '#e74c3c', fontWeight: 'bold' }}>❌ 不可用</span>
                            )}
                        </td>
                    </tr>
                ))}
            </tbody>
        </table>
    );
}

// 复用可用性判断函数
function checkAvailability(userStart, userEnd, borrowedRecords) {
    const userStartDate = new Date(userStart);
    const userEndDate = new Date(userEnd);
    if (!borrowedRecords || borrowedRecords.length === 0) return true;
    for (const record of borrowedRecords) {
        const borrowStart = new Date(record.borrowed_start);
        const borrowEnd = new Date(record.borrowed_end);
        if (userStartDate <= borrowEnd && userEndDate >= borrowStart) {
            return false;
        }
    }
    return true;
}

export default BorrowTable;

几个额外的坑要注意

  • 日期格式统一:用户输入的MM/DD/YYYY格式要先转成ISO标准格式(YYYY-MM-DD)再和数据库的日期对比,避免跨时区或者格式转换错误。
  • 性能优化:如果产品数量特别多,尽量把可用性判断逻辑放在后端做(比如用SQL的日期函数直接计算),减少前端的计算压力,同时给数据库的product_id、start_date、end_date加索引,提升查询速度。
  • 边界场景处理:比如用户选的起始日期刚好等于某个产品的归还日期,这种情况算不算可用?得根据你的业务规则调整判断逻辑——如果允许“无缝衔接”,那这种情况应该算可用,把判断条件改成userStartDate < borrowEnd && userEndDate > borrowStart就行。

内容的提问来源于stack exchange,提问作者user982124

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:20:21