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 或其他方式解决