mothership-ec/cog-mothership-refer-a-friend

此包已被废弃且不再维护。未建议替代包。

Mothership的“推荐好友”功能模块

1.0.0 2015-12-09 11:13 UTC

This package is not auto-updated.

Last update: 2021-03-22 11:07:22 UTC


README

Message\Mothership\ReferAFriend 模块允许用户推荐非用户到网站,并可能因此获得奖励。

推荐

Referral 对象表示用户将某人推荐到网站的实例。用户可以推荐任意多的人,但任何电子邮件地址只能推荐一次。如果用户尝试推荐已经推荐过的人,他们将收到错误消息。他们也可以仅推荐非用户。

推荐由以下信息组成

  • 推荐者 - 进行推荐的用户
  • 被推荐电子邮件地址 - 被推荐人的电子邮件地址
  • 被推荐人姓名 - 被推荐人的姓名
  • 奖励配置 - 成功推荐后将授予的奖励的配置
  • 状态 - 推荐的状态(待定完成错误过期
  • 创建时间 - 推荐的时间

奖励

奖励类型

奖励可以有多种类型。此模块仅包含一种奖励类型:no_reward。此类型作为简单的推荐,但推荐者在推荐标记为完成时不会获得任何东西。它在用户注册并登录网站时标记为完成。

奖励配置

每种奖励类型都可以通过一组 实体 进行配置,这些实体存储在 Config 类中。可以存储在配置中的实体有三种类型

  • 触发器
  • 约束
  • 奖励选项

这些类型中的每一个都有一个关联的集合,它扩展了 Message\Cog\ValueObject\Collection 类,并且所有实体都在其关联集合的实例中注册到服务容器中。

Message\Mothership\ReferAFriend\Reward\Type\TypeInterface 有三个方法:validTriggers()validConstraints()validRewardOptions(),用于确定哪些实体适用于特定奖励类型。这些返回一个一维数组,包含这些实体的名称(由实体的 getName() 方法返回)。

触发器

触发器确定必须触发哪些事件,才能将推荐标记为可能完成。

它们必须实现 Message\Mothership\ReferAFriend\Reward\Config\Trigger\TriggerInterface

推荐对象有一个 hasTriggered() 方法,可以快速确定它是否已触发。它以事件名称作为参数。

为了使触发器有效,必须有一个事件监听器监听加载奖励的事件。然后可以使用电子邮件地址加载推荐,例如:

public function createReward(SomeEvent $event)
{
    $referrals = $this->get('refer.referral.loader')->getByEmail($event->getEmail());

    // Return if no referrals were loaded
    if (empty($referrals)) {
        return;
    }

    foreach ($referrals as $referral) {
        // Continue if trigger does not apply to event
        if (false === $referral->hasTriggered('event.name')) {
            continue;
        }

        // code to create reward
    }
}

注意:推荐加载器返回一个数组。除了getByID()外,所有在加载器上的方法都返回推荐数组。这是为了让控制器在调用加载器时知道应该期待什么,并且为将来做准备,以防模块被修改为允许向一个地址发送多个推荐。

触发器必须通过扩展服务容器中的refer.reward.config.triggers服务来添加,并通过集合上的add()方法添加。

$services['refer.reward.config.triggers'] = $services->extend('refer.reward.config.triggers', function($triggers, $c) {
    $triggers->add(new My\New\Trigger);

    return $triggers;
});

约束条件

约束条件确定了一个规则,必须满足这个规则才能将推荐标记为完成并生成奖励。这以简单的键/值对形式存储在数据库中。

它们必须实现Message\Mothership\ReferAFriend\Reward\Config\Constraint\ConstraintInterface接口。约束必须与一个Symfony表单类型相关联。这是通过在约束上使用getFormType()方法来返回的。应该放在此表单字段上的任何选项都应该通过在约束上使用getFormOptions()方法作为数组返回。

约束还有一个isValid()方法,它以推荐作为其第一个参数,以及一个Message\Cog\Event\Event实例,该实例被触发以验证推荐,作为其第二个参数。

因此,为了扩展上面的例子,我们可以通过遍历其约束来检查推荐的合法性。

public function createReward(SomeEvent $event)
{
    $referrals = $this->get('refer.referral.loader')->getByEmail($event->getEmail());

    // Return if no referrals were loaded
    if (empty($referrals)) {
        return;
    }

    foreach ($referrals as $referral) {
        // Continue if trigger does not apply to event
        if (false === $referral->hasTriggered('event.name')) {
            continue;
        }

        // Default to $valid being true, loop through constraints and validate
        $valid = true;
        foreach ($referral->getRewardConfig()->getConstraints() as $constraint) {
            // Break out of loop if referral is not valid, and set $valid to false
            if (false === $constraint->isValid($$referral, $event)) {
                $valid = false;
                break;
            }
        }

        // Move on to next referral if invalid
        if (false === $valid) {
            continue;
        }

        // code to create reward
    }
}

注意:虽然ReferralInterface有一个hasTriggered()方法来快速访问触发器并检查是否已触发,但没有isValid()方法。这是因为可能存在某些情况下,你可能希望忽略某种情况下的约束。

必须通过扩展服务容器中的refer.reward.config.constraints服务来添加约束,并在集合上调用add()方法。

$services['refer.reward.config.constraints'] = $services->extend('refer.reward.config.constraints', function($constraints, $c) {
    $constraints->add(new My\New\Constraint);

    return $constraints;
});

奖励选项

奖励选项用于配置在推荐成功完成时将生成的任何奖励。它们必须实现Message\Mothership\ReferAFriend\Reward\Config\RewardOption\RewardOptionInterface

与约束一样,它们以键/值对的形式存储,并且必须与一个Symfony表单类型相关联,这些通过使用getFormType()getFormOptions()方法定义。

必须通过扩展服务容器中的refer.reward.config.reward_options服务来添加奖励选项,并在集合上调用add()方法。

$services['refer.reward.config.reward_options'] = $services->extend('refer.reward.config.reward_options', function($rewardOptions, $c) {
    $rewardOptions->add(new My\New\RewardOption);

    return $rewardOptions;
});

代理

此模块在推荐和奖励配置上都使用了延迟加载,因此存在Message\Mothership\ReferAFriend\Referral\ReferralProxyMessage\Mothership\ReferAFriend\Reward\Config\ConfigProxy的类。这些类持有其实体的加载器以及它们可能需要的任何ID,而不是实体本身。它们扩展了getter以调用加载器,从数据库加载实体并将它们设置为自己,在需要时。一旦加载过一次,它们将从此请求的内存中检索它们,而不是从数据库中检索。例如,在ConfigProxy中。

/**
 * {@inheritDoc}
 */
public function getConstraints()
{
    if (null === $this->_constraints) {
        $constraints = $this->_loaders->get('constraint')->load($this);

        if (!$constraints) {
            throw new \LogicException('Could not load constraints!');
        }

        foreach ($constraints as $constraint) {
            $this->addConstraint($constraint);
        }
    }

    return parent::getConstraints();
}