Yii2 Randomized ActiveForm Widget Package
1. Directory & files structure

Assuming namespace is app\widgets\RandomizedForm:

widgets/
└── RandomizedForm/
    ├── RandomizedActiveForm.php
    ├── RandomizedActiveField.php
    ├── Randomizer.php
    ├── README.md
    └── assets/
        └── randomizer.js  (optional client JS)

2. The Core Randomizer service (Randomizer.php)

<?php

namespace app\widgets\RandomizedForm;

use Yii;

/**
 * Core service that generates randomized field names,
 * stores them in session,
 * maps POST data back,
 * and checks honeypot fields.
 */
class Randomizer
{
    protected $sessionKey;

    protected $fieldMap = [];

    public function __construct($sessionKey = 'randomizedActiveFormFieldMap')
    {
        $this->sessionKey = $sessionKey;
    }

    /**
     * Generate random string identifiers for given field list
     * and store in session.
     */
    public function generate(array $fields)
    {
        $map = [];
        foreach ($fields as $field) {
            $map[$field] = $this->generateRandomString();
        }
        $this->fieldMap = $map;
        Yii::$app->session->set($this->sessionKey, $map);

        return $map;
    }

    /**
     * Retrieve the map from session or return empty array
     */
    public function getMap()
    {
        if (empty($this->fieldMap)) {
            $this->fieldMap = Yii::$app->session->get($this->sessionKey, []);
        }
        return $this->fieldMap;
    }

    /**
     * Reverse-map submitted POST data keys to logical attribute names.
     *
     * @param array $postData Raw POST data from request.
     * @return array mapped data in logical keys.
     */
    public function mapPostData(array $postData)
    {
        $map = $this->getMap();
        $reverseMap = array_flip($map);

        $mapped = [];
        foreach ($postData as $k => $v) {
            if (isset($reverseMap[$k])) {
                $mapped[$reverseMap[$k]] = $v;
            }
        }
        return $mapped;
    }

    /**
     * Check whether any honeypot fields are filled.
     *
     * @param array $mappedData Logical-keyed data array.
     * @param array $honeypotFields List of logical honeypot fields.
     * @return bool True if any honeypot filled, else false.
     */
    public function honeypotFilled(array $mappedData, array $honeypotFields)
    {
        foreach ($honeypotFields as $hp) {
            if (!empty($mappedData[$hp])) {
                return true;
            }
        }
        return false;
    }

    protected function generateRandomString($length = 10)
    {
        return substr(str_shuffle(str_repeat('abcdefghijklmnopqrstuvwxyz0123456789', $length)), 0, $length);
    }
}

3. The RandomizedActiveForm widget (RandomizedActiveForm.php)

<?php

namespace app\widgets\RandomizedForm;

use Yii;
use yii\widgets\ActiveForm;

/**
 * RandomizedActiveForm overrides Yii2 ActiveForm to randomize all field names,
 * store the mapping in session, and pass to fields.
 */
class RandomizedActiveForm extends ActiveForm
{
    /** @var Randomizer */
    protected $randomizer;

    /** @var array Map of logical attribute => randomized name */
    public $fieldNameMap = [];

    /** @var array List of honeypot logical attribute names */
    public $honeypotFields = [];

    /** @var string The session key to use */
    public $sessionKey = 'randomizedActiveFormFieldMap';

    public $model;

    public function init()
    {
        parent::init();

        if (!$this->model) {
            throw new \InvalidArgumentException('RandomizedActiveForm requires you to set the "model" property.');
        }

        $this->randomizer = new Randomizer($this->sessionKey);

        // Combine model attributes and honeypots
        $attributes = array_keys($this->model->attributes);
        $logicalFields = array_merge($attributes, $this->honeypotFields);

        // Use existing map from session or generate new
        $this->fieldNameMap = $this->randomizer->getMap();

        if (empty($this->fieldNameMap)) {
            $this->fieldNameMap = $this->randomizer->generate($logicalFields);
        }
    }

    /**
     * Override field() to pass randomized map to fields
     */
    public function field($model, $attribute, $options = [])
    {
        $options['fieldNameMap'] = $this->fieldNameMap;
        $field = parent::field($model, $attribute, $options);
        // You could catch the field instance here if needed
        return $field;
    }

    /**
     * Get the Randomizer instance, for convenience
     */
    public function getRandomizer()
    {
        return $this->randomizer;
    }
}

4. The RandomizedActiveField widget (RandomizedActiveField.php)

<?php

namespace app\widgets\RandomizedForm;

use yii\widgets\ActiveField;

/**
 * RandomizedActiveField overrides Yii2 ActiveField to render inputs with randomized 'name' attributes
 * using the fieldNameMap populated by RandomizedActiveForm.
 */
class RandomizedActiveField extends ActiveField
{
    /** @var array randomized map of attribute => randomized name */
    public $fieldNameMap = [];

    /**
     * Override input() to replace name attribute with randomized one before rendering
     */
    public function input($type, $options = [])
    {
        if ($this->fieldNameMap && isset($this->fieldNameMap[$this->attribute])) {
            $options['name'] = $this->fieldNameMap[$this->attribute];
        }
        return parent::input($type, $options);
    }

    /**
     * Also override textInput, passwordInput etc. to be safe
     */
    public function textInput($options = [])
    {
        return $this->input('text', $options);
    }

    public function passwordInput($options = [])
    {
        return $this->input('password', $options);
    }

    public function hiddenInput($options = [])
    {
        return $this->input('hidden', $options);
    }

    // Add more overrides if you use other input types (emailInput etc.)
}

5. Optional: Client JavaScript to dynamically update placeholders (optional)

File: assets/randomizer.js

// Optional: dynamically fill placeholders or labels if you want
// This step is optional and up to your UX preferences

document.addEventListener('DOMContentLoaded', function() {
    if (!window._randomizedFieldMap || !window._placeholders) {
        return;
    }

    const map = window._randomizedFieldMap;
    const placeholders = window._placeholders;

    Object.keys(map).forEach(function(logicalName) {
        var randomized = map[logicalName];
        var el = document.querySelector('[name="' + randomized + '"]');
        if (el && placeholders[logicalName]) {
            el.setAttribute('placeholder', placeholders[logicalName]);
        }
    });
});



6. Usage example in the view

<?php
use app\widgets\RandomizedForm\RandomizedActiveForm;
use app\widgets\RandomizedForm\RandomizedActiveField;

/* @var $model \app\models\RegisterForm */

$form = RandomizedActiveForm::begin([
    'id' => 'register-form',
    'fieldClass' => RandomizedActiveField::class,
    'model' => $model,
    'honeypotFields' => ['honeypot1', 'honeypot2'],
    'enableClientValidation' => true,
]);

// Normal fields — randomized automatically
echo $form->field($model, 'email')->input('email');
echo $form->field($model, 'password')->passwordInput();
echo $form->field($model, 'username')->textInput();

// Honeypot fields, rendered visually hidden
foreach ($form->honeypotFields as $hp) {
    echo $form->field($model, $hp)->textInput([
        'style' => 'position:absolute; left:-9999px;',
        'tabindex' => '-1',
        'autocomplete' => 'off',
        'aria-hidden' => 'true',
    ]);
}

?>

<div class="form-group">
    <button type="submit" class="btn btn-primary">Register</button>
</div>

<?php RandomizedActiveForm::end(); ?>

<script>
    // Pass data to JS for optional dynamic placeholder filling
    window._randomizedFieldMap = <?= \yii\helpers\Json::encode($form->fieldNameMap) ?>;
    window._placeholders = {
        email: 'Email Address',
        password: 'Password',
        username: 'Username',
        // honeypots don't need placeholders
    };
</script>
<?php 
// Register your optional randomizer.js asset if you create it
// $this->registerJsFile('@web/js/randomizer.js', ['depends' => ['yii\web\YiiAsset']]);
?>

7. Server-side controller example

public function actionRegister()
{
    $request = Yii::$app->request;

    $randomizer = new \app\widgets\RandomizedForm\Randomizer();

    $honeypots = ['honeypot1', 'honeypot2'];

    if ($request->isPost) {
        $post = $request->post();

        $mappedData = $randomizer->mapPostData($post);

        // Honeypot check
        if ($randomizer->honeypotFilled($mappedData, $honeypots)) {
            Yii::$app->session->setFlash('error', 'Bot activity detected.');
            return $this->refresh();
        }

        $model = new \app\models\RegisterForm();
        if ($model->load($mappedData, '') && $model->validate()) {
            // Registration logic
            Yii::$app->session->remove('randomizedActiveFormFieldMap');
            return $this->redirect(['site/success']);
        }

        // Show errors below
        return $this->render('register', ['model' => $model]);
    }

    // GET: render form fresh with empty model
    $model = new \app\models\RegisterForm();
    return $this->render('register', ['model' => $model]);
}

Summary

    Widget works as drop-in replacement for ActiveForm and ActiveField.
    Randomizes all field names every page load, stores map in session.
    Controller uses Randomizer service to decode POST keys and validate honeypots.
    Honeypots blend in thanks to randomization and offscreen CSS hiding.
    Optional JS support for dynamic placeholders.
    Easy to adopt for any form by just changing ActiveForm type and adding honeypot field names.

If you'd like, I can:

    Package this as a GitHub repository with proper composer.json, tests, readme.
    Provide installation instructions.
    Help integrate it with your existing project.

Just let me know!


I want to add logging for bots I was using this in the controller

	public function actionContact(string $subject = null): Response|string
	{
		$request = \Yii::$app->request;
		if (($request->isPost) && ($model->load($request->post()) && $model->validate()))
		{
			// Perform the post-validation action.
			if ($model->process())
			{
				/**
				* HoneyPot
				* The 'honeyPot' field is a honeypot, designed to trap bots by 
				* mimicking a legitimate field.
				*/
				if ($this->_honeyPot && $model->emaill)
				{
					LogHelper::logBotAction('Honeypot. Potential bot detected', [
						'ip' => $this->_userIp,
						'userAgent' => $this->_userAgent,
					]);