public function rule($rule, $fields, ...$params)
    {
        if (\is_callable($rule)
            && !(\is_string($rule) && $this->hasValidator($rule))
        ) {
            $name = $this->getUniqueRuleName($fields);
            $message = $params[0] ?? null;
            $this->addInstanceRule($name, $rule, $message);
            $rule = $name;
        }

        $errors = $this->getRules();
        if (!isset($errors[$rule])) {
            $ruleMethod = 'validate' . \ucfirst($rule);
            if (!\method_exists($this, $ruleMethod)) {
                throw new \InvalidArgumentException("Rule '" . $rule . "' has not been registered with " . __CLASS__ . "::addRule().");
            }
        }

        // Ensure rule has an accompanying message
        $messages = $this->getRuleMessages();
        $message = $messages[$rule] ?? self::ERROR_DEFAULT;

        // Ensure message contains field label
        if (\strpos($message, '{field}') === false) {
            $message = '{field} ' . $message;
        }

        $this->_validations[] = [
            'rule' => $rule,
            'fields' => (array) $fields,
            'params' => (array) $params,
            'message' => '{field} ' . $message,
            'skip' => self::SKIP_CONTINUE,
        ];

        return $this;
    }