Yii2. Как реализовать реферальную систему?

Добрый день.

Пытаюсь реализовать реферальную программу на сайте. Сейчас это работает только при заходе на главную страницу.

Просто проверяю необходимый GET параметр:
//SiteController actionIndex

$ref_name = Yii::$app->request->get('ref');
//Если есть параметр ref, то записываю куки
//И потом просто заново перенаправляю на главную страницу
$this->redirect(Yii::app()->getHomeUrl());


Но хочу сделать так, чтобы реферальная ссылка могла вести на любую страницу. Пытаюсь сделать следующее. Все необходимые контроллеры унаследовал от MainController, а в MainController создаю beforeAction:

//MainController

public function beforeAction($action)
{
    $ref_name = Yii::$app->request->get('ref');
    //Далее стандартные проверки на наличие такого рефа и запись куки
    //Но теперь надо перенаправить на запрашиваемую страницу
    //убрав при этом GET параметр "ref"
    return parent::beforeAction($action);
}

Необходимо, чтобы при заходе допустим на:
site.com/article?ref=123
пользователь в итоге попадал на:
site.com/article

Также возникает сложность со страницами, на которых уже есть другие параметры:
site.com/article/view?id=20&ref=123
Необходимо как то убрать параметр "ref", а остальные оставить:
site.com/article/view?id=20

Возможно у кого то есть наработки в этой теме. Или нет смысла заморачиваться со скрытием этих параметров? Заранее спасибо!
  • Вопрос задан
  • 386 просмотров
Решения вопроса 1
myks92
@myks92 Куратор тега Yii
Нашёл решение — пометь вопрос ответом!
А если вы забудете где-то наследоваться от этого контроллера? Можно вам решить и без наследования от основного контроллера. Вешайте обработчик на всё приложение используя before или after:

'as beforeAction' => function () {
//Тут ваши действия для анонимной функции
}


Если логики много используйте отдельный класс, например, поведения. Но поведения уберут в Yii3. Думайте об этом тоже)
'as beforeAction' => [
        'class' => app\modules\users\behaviors\LastVisitBehavior::class
    ],

Очищать URL от нужного параметра можно с
Url::current(['ref' => null]);

PS Мне кажется, что не надо делать реферальную ссылку на все экшены. Врядли пользователь будет менять ссылку. Да и зачем вам это учитывать. Дают рабочую ссылку на регистрацию. Там вы ищите нужный параметр. Запоминаете его и уже при регистрации всегда подставляете если есть. Но зачем вам рефералка в новостях, статьях и так далее. Не пойму целесообразность решения)

Обычно делают как то так:
/**
     * Страница сохранения реферера (пригласившего)
     *
     * @param int $id
     *
     * @return Response|string
     */
    public function actionReferral(int $id)
    {
        if (Yii::$app->user->isGuest) {
            ReferralHelper::setReferrerId($id);
        }
        return $this->redirect('site/registration');
    }


/**
     * Страница регистрации
     *
     * @return Response|string
     * @throws \yii\base\InvalidArgumentException
     * @throws \yii\db\Exception
     */
    public function actionRegistration()
    {
        if (!Yii::$app->user->isGuest) {
            return $this->goHome();
        }
        $userForm = new UserForm();
        if ($userForm->load(Yii::$app->request->post())) {
            $referrerId = ReferralHelper::getReferrerId();
            $referrer = $referrerId !== null ? $this->getUser((int)$referrerId) : null;
            $userForm->setReferrer($referrer);
            if ($userForm->save() && $userForm->login()) {
                $message = 'Спасибо за регистрацию.';
                if ($referrer !== null) {
                    $message .= ' Вас пригласил ' . $referrer;
                }
                Yii::$app->session->setFlash('success', $message);
                ReferralHelper::removeReferrer();
                return $this->goHome();
            }
            $this->addErrorForForm($userForm);
        }
        $userForm->password = '';
        return $this->render('registration', [
            'model' => $userForm,
        ]);
    }


class ReferralHelper
{
    const KEY_REFERRER_ID = 'referrer_id';
    public static function setReferrerId(int $referrerId)
    {
        \Yii::$app->getSession()->set(self::KEY_REFERRER_ID, $referrerId);
    }
    public static function getReferrerId()
    {
        return \Yii::$app->getSession()->get(self::KEY_REFERRER_ID, null);
    }
    public static function removeReferrer()
    {
        return \Yii::$app->getSession()->remove(self::KEY_REFERRER_ID);
    }
}


Взял из готового решения на Yii2. Код не совсем хороший, но рабочий.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы