前言

我最近一直写了很多活动都需要做任务发奖励。但每次都有很多类似的任务以及奖励。于是乎就想有没有什么方法把任务抽象,只需要写一遍代码就可以了。经过了一番参考觉得以下方法可行

任务

/**
 * 任务接口
 *
 * @author suntianxiang <suntianxiang@kding.com>
 */
interface TaskInterface
{

    /**
     * 获取目标
     * 
     * @param array $params
     * @return TargetInterface[]
     */
    public function getTargets();

    /**
     * 获取进度
     * 
     * @return string 1/10
     */
    public function getProgress();
}

这是任务接口
getTargets()方法获取所有目标,再根据目标判断任务是否完成,目标里对应这不同的逻辑,如连续登录,点赞这些

目标

interface TargetInterface
{
    /**
     * 
     * @param mixed $user 用户信息
     * @return bool
     */
    public function checkCondition($user);
}

这是目标接口
通过横向实现此接口完成各种不同的目标,如 LoginTarget,LikeTarget...

例子

/**
 * 连续登录目标
 */
class ConsecutiveLoginTarget implements TargetInterface
{
    /**
     * @var int $days 连续登录天数
     */
    private $days;

    public function __construct($days)
    {
        $this->days = $days;
    }

    public function checkCondition($user)
    {
        return count($user['consecutive_login_times']) >= $this->days;
    }
}

class ActivityTask implements TaskInterface
{
    
    public function getTargets()
    {
        // 实际中这可能是从库中解析出来的
        return [
            new ConsecutiveLoginTarget()
        ];
    }
    
    public function getProgress()
    {
        return '0/1';
    }
}

任务配置表

任务配置表sql

CREATE TABLE `tb_task_configs` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '任务id',
  `name` varchar(30) NOT NULL COMMENT '任务名称',
  `type` tinyint(1) NOT NULL COMMENT '任务类型 1 一次性任务 2 每日任务',
  `targets` varchar(255) NOT NULL COMMENT '任务目标 string "|" 分割不同目标 ":"后接构造参数 ","分割参数 如 LoginTarget:1|OrderTarget:1,2',
  `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1 启用 0 禁用',
  `is_del` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0 未删 1 已删',
  `create_time` int(11) NOT NULL DEFAULT '0',
  `update_time` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='任务配置表';

结语

通过合理的抽象能减少很多重复的代码.像还有 任务奖励,前置任务这些笔者并没有实现,读者可以根据自己需要扩展。


suntianxiang
46 声望2 粉丝

php,前端,分享知识