yanselmask/openable

此软件包旨在简化并自动化管理各种场所(如商店、餐厅、健身房或夜总会)的营业时间。

dev-main 2024-08-30 10:28 UTC

This package is auto-updated.

Last update: 2024-09-30 10:35:44 UTC


README

此软件包旨在简化并自动化管理各种场所(如商店、餐厅、健身房或夜总会)的营业时间。

安装和设置

您可以通过Composer安装此软件包

composer require yanselmask/openable

您可以使用以下命令发布迁移

php artisan vendor:publish --provider="Yanselmask\Openable\Providers\ServiceProvider" --tag="openable-migrations"

迁移发布后,您可以通过运行迁移来创建openables表

php artisan migrate

您可以选择使用以下命令发布配置文件

php artisan vendor:publish --provider="Yanselmask\Openable\Providers\ServiceProvider" --tag="openable-config"

这是已发布配置文件的内容

<?php

return [
    /*
  |--------------------------------------------------------------------------
  | Database Name
  |--------------------------------------------------------------------------
  |
  | Here you should specify the name of the database to which your application
  | will connect. This name identifies the database on your server and is
  | necessary for the application to perform read and write operations.
  |
  | Make sure the name exactly matches the database name you have created on
  | your database server, as any discrepancy could prevent the application from
  | connecting properly.
  |
  | Example:
  | 'database_name' => 'openables',
  |
  */
    'database_name' => 'openables'
];

使用方法

将可开放功能添加到您的资源模型

要将可开放功能添加到您的资源模型,只需像这样使用\Yanselmask\Openable\Traits\Openable特质

namespace App\Models;

use Yanselmask\Openable\Traits\Openable;
use Illuminate\Database\Eloquent\Model;

class Restaurant extends Model
{
    use Openable;
}

通过传入常规计划和一个异常列表创建一组营业时间

// Add the use at the top of each file where you want to use the OpeningHours class:
use App\Models\Restaurant;


$restaurant = Restaurant::find(1);
$restaurant->setShift(
[
    'monday'     => ['09:00-12:00', '13:00-18:00'],
    'tuesday'    => ['09:00-12:00', '13:00-18:00'],
    'wednesday'  => ['09:00-12:00'],
    'thursday'   => ['09:00-12:00', '13:00-18:00'],
    'friday'     => ['09:00-12:00', '13:00-20:00'],
    'saturday'   => ['09:00-12:00', '13:00-16:00'],
    'sunday'     => [],
    'exceptions' => [
        '2016-11-11' => ['09:00-12:00'],
        '2016-12-25' => [],
        '01-01'      => [],                // Recurring on each 1st of January
        '12-25'      => ['09:00-12:00'],   // Recurring on each 25th of December
    ]
]
);

可以查询一周中的某一天,将根据常规计划返回结果

// Open on Mondays:
$restaurant->isOpenOn('monday'); // true

// Closed on Sundays:
$restaurant->isOpenOn('sunday'); // false

也可以查询特定的日期和时间

// Closed because it's after hours:
$restaurant->isOpenAt(new DateTime('2016-09-26 19:00:00')); // false

// Closed because Christmas was set as an exception
$restaurant->isOpenOn('2016-12-25'); // false

// Checks if the business is closed on a specific day, at a specific time.
$restaurant->isClosedAt(new DateTime('2016-26-09 20:00'));
// Checks if the business is closed on a day in the regular schedule.
$restaurant->isClosedOn('sunday');

还可以返回一周或一天的营业时间数组

// OpeningHoursForDay object for the regular schedule
$restaurant->forDay('monday');

// OpeningHoursForDay[] for the regular schedule, keyed by day name
$restaurant->forWeek();

// Array of day with same schedule for the regular schedule, keyed by day name, days combined by working hours
$restaurant->forWeekCombined();

// OpeningHoursForDay object for a specific day
$restaurant->forDate(new DateTime('2016-12-25'));

// OpeningHoursForDay[] of all exceptions, keyed by date
$restaurant->exceptions();

在构建时,您可以设置标志以跨天溢出时间。例如,夜总会周五和周六营业到凌晨3点

use App\Models\Nightclub;

$nightclub = Nightclub::find(1);

$nightclub->setShift([
    'overflow' => true,
    'friday'   => ['20:00-03:00'],
    'saturday' => ['20:00-03:00'],
]);

这允许API进一步检查前一天的数据以确定营业时间是否在指定的时间范围内开放。

您可以在定义中添加数据然后检索它们

$restaurant->setShift([
'monday' => [
        'data' => 'Typical Monday',
        '09:00-12:00',
        '13:00-18:00',
    ],
    'tuesday' => [
        '09:00-12:00',
        '13:00-18:00',
        [
            '19:00-21:00',
            'data' => 'Extra on Tuesday evening',
        ],
    ],
    'exceptions' => [
        '2016-12-25' => [
            'data' => 'Closed for Christmas',
        ],
    ],
]);
echo $restaurant->forDay('monday')->data; // Typical Monday
echo $restaurant->forDate(new DateTime('2016-12-25'))->data; // Closed for Christmas
echo $restaurant->forDay('tuesday')[2]->data; // Extra on Tuesday evening

在上面的示例中,数据是字符串,但它可以是任何类型的值。因此,您可以在数组中嵌入多个属性。

为了方便结构,数据-小时对可以是一个完全关联的数组,因此上面的示例严格等价于以下示例

$restaurant->setShift([
    'monday' => [
        'hours' => [
            '09:00-12:00',
            '13:00-18:00',
        ],
        'data' => 'Typical Monday',
    ],
    'tuesday' => [
        ['hours' => '09:00-12:00'],
        ['hours' => '13:00-18:00'],
        ['hours' => '19:00-21:00', 'data' => 'Extra on Tuesday evening'],
    ],
    // Open by night from Wednesday 22h to Thursday 7h:
    'wednesday' => ['22:00-24:00'], // use the special "24:00" to reach midnight included
    'thursday' => ['00:00-07:00'],
    'exceptions' => [
        '2016-12-25' => [
            'hours' => [],
            'data'  => 'Closed for Christmas',
        ],
    ],
]);

您可以使用分隔符to一次指定多个日期,对于一周或异常

$restaurant->setShift([
    'monday to friday' => ['09:00-19:00'],
    'saturday to sunday' => [],
    'exceptions' => [
        // Every year
        '12-24 to 12-26' => [
            'hours' => [],
            'data'  => 'Holidays',
        ],
        // Only happening in 2024
        '2024-06-25 to 2024-07-01' => [
            'hours' => [],
            'data'  => 'Closed for works',
        ],
    ],
]);

最后一种结构工具是过滤器,它允许您传递接受日期作为参数并返回给定日期设置的闭包(或可调用的函数/方法引用)。

$restaurant->setShift([
    'monday' => [
       '09:00-12:00',
    ],
    'filters' => [
        function ($date) {
            $year         = intval($date->format('Y'));
            $easterMonday = new DateTimeImmutable('2018-03-21 +'.(easter_days($year) + 1).'days');
            if ($date->format('m-d') === $easterMonday->format('m-d')) {
                return []; // Closed on Easter Monday
                // Any valid exception-array can be returned here (range of hours, with or without data)
            }
            // Else the filter does not apply to the given date
        },
    ],
]);

如果调用在“exceptions”属性中找到,它将自动添加到过滤器中,因此您可以在异常数组中混合过滤器和异常。第一个返回非空值的过滤器将比下一个过滤器有优先权,并且过滤器数组比异常数组中的过滤器有优先权。

警告:我们将对所有过滤器进行循环,从需要检索营业时间的每个日期开始,无法对结果进行预测或缓存(可以是随机函数),因此您必须小心处理过滤器,过多的过滤器或过滤器中的长时间过程可能会对性能产生重大影响。

它还可以从给定的DateTime返回下一个开放或关闭的DateTime

// The next open datetime is tomorrow morning, because we’re closed on 25th of December.
$nextOpen = $restaurant->nextOpen(new DateTime('2016-12-25 10:00:00')); // 2016-12-26 09:00:00

// The next open datetime is this afternoon, after the lunch break.
$nextOpen = $restaurant->nextOpen(new DateTime('2016-12-24 11:00:00')); // 2016-12-24 13:00:00


// The next close datetime is at noon.
$nextClose = $restaurant->nextClose(new DateTime('2016-12-24 10:00:00')); // 2016-12-24 12:00:00

// The next close datetime is tomorrow at noon, because we’re closed on 25th of December.
$nextClose = $restaurant->nextClose(new DateTime('2016-12-25 15:00:00')); // 2016-12-26 12:00:00

如果没有指定时区,Openable将假定您始终传递已经匹配您计划的时区的DateTime对象。

如果将$timezone作为第二个参数或通过数组键'timezone'(它可以是一个DateTimeZone对象或一个string)传入,则传递的日期将在每个方法开始时转换为这个时区,然后如果该方法返回一个日期对象(例如nextOpennextClosepreviousOpenpreviousClosecurrentOpenRangeStartcurrentOpenRangeEnd),则在输出之前将其转换回原始时区,以便对象能够反映用户本地时间,而OpeningHours可以保持在其自己的业务时区。

或者,您也可以指定输入和输出时区(使用第二个和第三个参数)或使用数组。

$restaurant->setShift([
    'monday' => ['09:00-12:00', '13:00-18:00'],
    'timezone' => [
        'input' => 'America/New_York',
        'output' => 'Europe/Oslo',
    ],
]);

出于安全起见,如果创建OpeningHours对象时范围重叠,除非明确传递'overflow' => true,否则将抛出异常,在开时数组的定义中。您也可以明确合并它们。

$ranges = [
  'monday' => ['08:00-11:00', '10:00-12:00'],
];
$mergedRanges = $restaurant->op()->mergeOverlappingRanges($ranges); // Monday becomes ['08:00-12:00']

$restaurant->setShift($mergedRanges);
// Or use the following shortcut to create from ranges that possibly overlap:
$restaurant->op()->createAndMergeOverlappingRanges($ranges);

检查业务是否现在开放。

$restaurant->isOpen();

检查业务是否现在关闭。

$restaurant->isClosed();

安全性

如果您发现有关安全性的错误,请发送邮件至info@yanselmask.com,而不是使用问题跟踪器。

致谢

Buymeacoffe