ariby / update-status-by-time

此包已弃用且不再维护。未提供替代包。

此包可以帮助您选择与输入数据库列匹配的不同时间间隔的数据。

此包尚未发布版本,信息有限。


README

## 使用场景 此 package 之使用场景为,假设今有一 Table movies:

/*
|--------------------------------------------------------------------------
| movies
|--------------------------------------------------------------------------
|
| 記錄目前所有電影的資訊,欄位如下:
|
*/
|--------------------------------------------------------------------------
| id  |   name   |   status    |   startTime    |    endTime ...
|--------------------------------------------------------------------------
|  0  | 哈利波特  |    已下檔    |  2018-02-01    |   2018-02-01 ...
|--------------------------------------------------------------------------
|  1  | 與神同行  |    上映中    |  2018-04-01    |   2018-04-15 ...
|--------------------------------------------------------------------------
|  2  | 玩命關頭  |    上映中    |  2018-04-10    |   2018-04-30 ...
|--------------------------------------------------------------------------
|  3  | 全面啟動  |    未上映    |  2018-04-16    |   2018-05-30 ...
|--------------------------------------------------------------------------
|  4  | 明天過後  |    未上映    |  2018-06-01    |   2018-08-01 ...
|--------------------------------------------------------------------------
| ... |   ...    |    ...       |       ...     |    ...

假設今天日期是 2018-04-16,那麼我們會發現,在資料庫中
id=1 的與神同行的 "status" 應該被更新為"已下檔"
id=3 的明天過後的 "status" 應該被更新為"上映中"

這個 package 的功能就是為你找出那些 "應該被更新的 row id"
你可以依據不同的輸入來做限制,類似的使用有文章定時發佈與隱藏等...
再配合 Laravel 的排程使用,便可以使程式依自已所需要的頻率,"定期的自動更新維護 table 資訊"

安装

可以通过以下指令进行安装

composer require ariby/update-status-by-time

并在config/app.php加上Provider

'providers' => [
    ...
    Ariby\UpdateStatusByTime\UpdateStatusByTimeServiceProvider::class,
],    

然后在要使用的地方上方,加上下方代码做include

use Ariby\UpdateStatusByTime\UpdateStatusByTime;

使用方法

目前的 Method 一共有 3 个,以查询的时间来区分
分别是 checkBefore、checkBetween、checkAfter 且都必须传入四个参数,依次分别是:

$tableName => 欲查詢的table名稱,以上例就是"movies"

$tag => Array,欲做比對的欄位與其值,以movis為例:
[
    [
        ['status', '!=', '上映中'],
        ['status', '!=', '已下檔']
    ]
]
// 相當於 where 條件 `status != "上映中" && status != "已下檔"
// 每個第二層陣列會以 () 括狐包住,第三層陣列為其中的條件

$columnName => Array,存入table中的column欄位名稱,實際格式如下
['primaryKey' => "table中欲回傳的欄位名稱,如id",
'start_at'   => 'table中記錄判斷起始時間的欄位名稱',
'end_at'     => 'table中記錄判斷結束時間的欄位名稱'
]`

其中:
checkBefore 可不传入 end_at
checkAfter 可不传入 start_at
checkBetween 则 start_at 与 end_at 都必须传入

$function => 为一闭包函数,应接收一个数组参数,会包含查询结果,可执行用户想要做的事,比如更新字段

以下为以 movies 为使用案例的程序

checkBefore

UpdateStatusByTime::checkBefore(
    "movies",
	[
	    [
	        ['status', '!=', '未上映'],
	    ]
	], 
    [
        'primaryKey'=>'id',
        'start_at'=>'startTime'
    ],
    function($array){ ...do something what you want to do }
);

在 function 结束时,程序会自动将查询结果带入闭包函数执行,返回结果如下:

array(); // 以上表 movies 為例,無欄位應該做修改

用户应在闭包函数中做想做的事,如将 status 字段修改为「未上映」,以 Laravel ORM 为例

Movies::whereIn('id', $array)->update['status'=>'未上映'];

checkBetween

$result = UpdateStatusByTime::checkBetween(
    "movies",
	[
	    [
	        ['status', '!=', '上映中'],
	    ]
	], 
    [
        'primaryKey'=>'id',
        'start_at'=>'startTime',
        'end_at' => 'endTime'
    ],
    function($array){ ...do something what you want to do }
);

在 function 结束时,程序会自动将查询结果带入闭包函数执行
返回结果如:

array(3); // 以上表 movies 為例,id=3 之資料應該被修改

用户应在闭包函数中做想做的事,如将 status 字段修改为「上映中」,以 Laravel ORM 为例

Movies::whereIn('id', $array)->update['status'=>'上映中'];

checkAfter

$result = UpdateStatusByTime::checkAfter(
    "movies",
	[
	    [
	        ['status', '!=', '已下檔']
	    ]
	], 
    [
        'primaryKey'=>'id',
        'end_at' => 'endTime'
    ],
    function($array){ ...do something what you want to do }
);

在 function 结束时,程序会自动将查询结果带入闭包函数执行
返回结果如:

array(1); // 以上表 movies 為例,id=3 之資料應該做修改

用户应在闭包函数中做想做的事,如将 status 字段修改为「上映中」,以 Laravel ORM 为例

Movies::whereIn('id', $array)->update['status'=>'已下檔'];

返回格式

function 会自动执行闭包函数,并将查询结果的 id 数组以参数传入
当执行发生错误时,调用函数实际返回格式如下:

array(
    'ok'   => 'false',     // 回傳"true" or "false" 代表是否發生錯誤
    'msg'  => 'error msg', // 錯誤訊息,比如參數錯誤、table不存在..etc
    'data' => array()      // 查詢結果之id陣列
)

可以通过以下程序来判断是否发生错误

if( $returnArray['ok'] != 'true' ){
    // error
}else{
    // right
}

扩展案例

如果你的案例可能存在「没有预定结束时间」的情况(即 end_at === null),且你使用的是 Laravel 项目,可以在 Model 上加以下代码:

public function setPublishEndAtAttribute($publish_end_at){
    if(is_null($publish_end_at)){
        $this->attributes['publish_end_at'] = '9999-12-31 23:59:59';
    }else{
        $this->attributes['publish_end_at'] = $publish_end_at;
    }
}

public function getPublishEndAtAttribute($publish_end_at){
    if($publish_end_at == '9999-12-31 23:59:59'){
        return null;
    }else{
        return $publish_end_at;
    }
}

使用 Artisan 命令列做查询

待补充

配合 Laravel 排程使用

可以参考 Laravel 官方文件

以下是示例程序
App/console/kerner.php

// console/Kernel.php
    
    ...
    protected $commands = [
        \App\Console\Commands\UpdateMoviesStatus::class,
    ];
    ...
    protected function schedule(Schedule $schedule)
    {
        $schedule->command('update:movies')->everyMinute();
    }
    ...

// console/commands/updateMoviesStatus.php

App\Console\Commands建立updateMoviesStatus.php

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

use App\Models\Movies;
use Ariby\UpdateStatusByTime\UpdateStatusByTime;

class UpdateMoviesStatus extends Command
{
    // 命令名稱
    protected $signature = 'update:movies';

    // 說明文字
    protected $description = '[update] Movies status';

    public function __construct()
    {
        parent::__construct();
    }

    // Console 執行的程式
    public function handle()
    {
        /* before-檢查未上映的電影並更新 */
        UpdateStatusByTime::checkBefore(
            "movies",
            [
                [
                    ['status', '!=', '未上映']
                ]
            ], 
            [
                'primaryKey'=> 'id',
                'start_at'=> 'startTime'
            ], 
            function($array){
            if(!is_null($array))
                Movies::whereIn('id', $array)->update(['status' => '未上映', 'stage' => 'Before']);
            }
        );

        /* now-檢查上映中的電影並更新 */
        UpdateStatusByTime::checkBetween(
            "movies",
            [
                [
                    ['status', '!=', '上映中']
                ]
            ], 
            [
                'primaryKey'=>'id',
                'start_at'=>'startTime',
                'end_at'=>'endTime', 
            ],
            function($array){
            if(!is_null($array))
                Movies::whereIn('id', $array)->update(['status' => '上映中', 'stage' => 'Now']);
            }
        );

        /* after-檢查已下檔的電影並更新 */
        UpdateStatusByTime::checkAfter(
            [
                [
                    ['status', '!=', '已下檔']
                ]
            ], 
            [
                'primaryKey'=>'id',
                'end_at'=>'endTime'
            ],
            function($array){
            if(!is_null($array))
                Movies::whereIn('id', $array)->update(['status' => '已下檔', 'stage' => 'After']);
            }
        );
    }
}

然后执行php artisan schedule:run,便可使排程每分钟检查数据库中电影状态并更新

注意:如果你是 Windows,执行 php artisan schedule:run 可能会遇到 (Windows 运行 Laravel 排程的问题)

artisan" update:movies > "NUL" 2>&1

可以参考 https://github.com/laravel/framework/issues/7868 或其他方式解决