Из коробки в Yii2 используется капча из букв английского алфавита. Выглядит она вот так:

капча из букв английского алфавита

Цифровая капча

Вместо капчи по умолчанию можно использовать цифровую капчу, которая безусловно будет удобней для ваших пользователей. Выглядеть она будет так:

цифровая капча

Для этого переопределим метод generateVerifyCode() класса CaptchaAction. Именно этот метод отвечает за то, из каких символов будет состоять капча в Yii2.

Создадим файл NumericCaptcha.php в frontend\components. Код файла будет следующим:

<?php

namespace frontend\components;

use yii\captcha\CaptchaAction as DefaultCaptchaAction;

class NumericCaptcha extends DefaultCaptchaAction
{
  protected function generateVerifyCode()
  {
    //Длина
    $length = 5;
    //Цифры, которые используются при генерации
    $digits = '0123456789';
    $code = '';
    for($i = 0; $i < $length; $i++) {
        $code .= $digits[mt_rand(0, 9)];
    }
    return $code;
  }
}

Теперь, нужно прописать путь до новой капчи в контроллере:

<?php

namespace frontend\controllers;

use yii\web\Controller;
use frontend\components\NumericCaptcha;

class SiteController extends Controller
{ 
  public function actions()
  {
    return [            
      'captcha' => [
        'class' => NumericCaptcha::className(),
        'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
      ],
    ];
  }    
}

В форме:

public string $verifyCode = '';

В файле вида:

<?= $form->field($model, 'verifyCode')->widget(Captcha::class, [
  'template' => '<div class="row"><div class="col-lg-4">{image}</div><div class="col-lg-8">{input}</div></div>',
])->hint('Нажмите на картинку, чтобы обновить')->label('Код с изображения: <span class="field_required">*</span>') ?>

В роутах:

'captchaAction' => '/site/captcha',
'site/captcha/<refresh:\d+>' => 'site/captcha',
'site/captcha/<v:\w+>' => 'site/captcha',

Теперь, при генерации будут использоваться цифры.

Математическая капча

Стоит заметить, что сегодня роботы могут распознавать текст с картинок, и поэтому стоит улучшить защиту. Хорошим выходом может быть простая математическая задача, которую решит реальный человек.

Выглядеть такая капча будет так:

Математическая капча

Создадим файл MathCaptcha.php в frontend\components. Код файла будет следующим:

class MathCaptcha extends CaptchaAction
{
  public $minLength = 0;
  public $maxLength = 100;
  //public $foreColor = 0x24292f;// цвет цифр

  /**
   * @return string
   */
  protected function generateVerifyCode(): string
  {
    return mt_rand((int)$this->minLength, (int)$this->maxLength);
  }

  /**
   * @param int $code
   * @return string
   * @throws InvalidConfigException
   */
  protected function renderImage($code): string
  {
    $code = (int) $code;

    return parent::renderImage($this->getText($code));
  }

  /**
   * @param int $code
   * @return string
   */
  protected function getText(int $code): string
  {
    $rand = mt_rand(min(1, $code - 1), max(1, $code - 1));
    $operation = mt_rand(0, 1);
    if ($operation === 1) return $code - $rand . '+' . $rand;
    else return $code + $rand . '-' . $rand;
  }
}

Путь до новой капчи в контроллере:

'captcha' => [
  'class' => MathCaptcha::class,
  'fixedVerifyCode' => YII_ENV_TEST ? '42' : null,
],

В файле вида:

<?= $form->field($model, 'verifyCode')->widget(Captcha::class, [
  'template' => '<div class="row"><div class="col-lg-4">{image}</div><div class="col-lg-8">{input}</div></div>',
])->hint('Нажмите на картинку, чтобы обновить')->label('Решите пример: <span class="field_required">*</span>') ?>