Download the PHP package rasuvaeff/yii3-recaptcha without Composer
On this page you can find all versions of the php package rasuvaeff/yii3-recaptcha. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Informations about the package yii3-recaptcha
rasuvaeff/yii3-recaptcha
Google reCAPTCHA v2 and v3 widgets, yiisoft/form-model fields, and a
server-side validator for Yii3.
Provides RecaptchaV2 / RecaptchaV3 widgets and RecaptchaV2Field /
RecaptchaV3Field form-model fields for rendering challenges, plus
RecaptchaV2Rule / RecaptchaV3Rule with their handlers for server-side
verification through the Yii validator pipeline. In a headless setup
(SPA/Next.js frontend + API backend) you skip the rendering half entirely and
use only the validator — see Headless / API-only. HTTP
calls go through any PSR-18 client.
Using an AI coding assistant? llms.txt contains a compact API reference you can share with the model. Contributors: see AGENTS.md.
Requirements
| Requirement | Version |
|---|---|
| PHP | ^8.3 |
| A PSR-18 HTTP client + PSR-17 factories | any implementation |
yiisoft/widget |
^2.2 |
yiisoft/html |
^4.0 |
yiisoft/validator |
^2.5 |
yiisoft/translator |
^3.0 |
yiisoft/request-provider |
^1.3 |
yiisoft/form + yiisoft/form-model |
^1.0 / ^1.1 (form fields) |
Installation
You also need a PSR-18 client and PSR-17 factories if your project doesn't already ship one:
DI configuration
The package ships config/di.php via config-plugin. Rule handlers are
constructed by the validator's container-backed handler resolver (the Yii3
default via yiisoft/config), which autowires the client, the client-IP
resolver and the optional translator — no extra DI config required.
Works out of the box; DI-injected when available. The rule handlers take their dependencies (client, IP resolver, translator) as optional constructor arguments and fall back to
RecaptchaRegistry, which the package's config-plugin bootstrap populates from the container. So they work with theyiisoft/validatordefaultSimpleRuleHandlerContainer(no-argnew) with no extra config. When a container-backed resolver builds them, the injected deps win and the registry is never consulted.The application must provide a PSR-18
ClientInterfaceand PSR-17 factories (theRecaptchaClientis built from them) and set the keys in params (see Dependency injection). Two optional pure-DI setups if you'd rather not rely on the static fallback:
Headless / API-only
For a SPA/Next.js frontend + Yii3 API backend the widgets and fields are not
used — the frontend renders reCAPTCHA (e.g. react-google-recaptcha) and calls
grecaptcha.execute(siteKey, { action }), then sends the token to the API. The
backend only verifies it. Put the token on a request DTO property and attach
the rule:
Map the incoming token (JSON body field or a header such as X-Recaptcha-Token)
to that property, then run your normal validation. Different endpoints use
different action names and thresholds. To make a graduated (allow / challenge /
deny) decision on the raw score instead of a pass/fail rule, verify imperatively:
Behind a proxy/CDN, bind a proxy-aware client-IP resolver — see Client IP behind a proxy.
Usage
reCAPTCHA v2
Field name mapping with Yii3 FormModel
Google's reCAPTCHA v2 widget always submits the response token as
g-recaptcha-response(with hyphens). PHP does not normalize hyphens in POST keys, soFormModelwill never receive the token if it expectsgRecaptchaResponsedirectly.Use
withResponseFieldName()to bind the token to your model property automatically — the widget renders a hidden input and the required JS copy callback:
reCAPTCHA v3
The v3 widget renders the API <script>, a hidden input for the token, and a
script that fills the token on page load (or, with withFormId(), intercepts the
form submit, runs grecaptcha.execute() with the configured action, writes the
token into the hidden input, then submits — "invisible submit"):
When the badge is hidden you must keep the reCAPTCHA legal notice visible — the widget renders it for you. All values are JSON-encoded with XSS-safe flags before being embedded in the inline script.
Form fields (form-model)
For server-rendered forms, RecaptchaV2Field / RecaptchaV3Field integrate with
yiisoft/form-model: they bind the token to a model property and delegate
rendering to the widgets (one rendering path, so widget and field stay in sync).
Content-Security-Policy
Both widgets emit inline <script> (and <style>). Under a strict CSP without
unsafe-inline, pass a nonce — it is applied to every emitted tag:
Client IP behind a proxy
When sendRemoteIp is enabled the client IP is resolved through
ClientIpResolverInterface. The default RemoteAddrClientIpResolver reads
REMOTE_ADDR (validated with FILTER_VALIDATE_IP) — correct only when you are
not behind a proxy/CDN, or when a trusted-hosts middleware has already normalised
REMOTE_ADDR. Behind an un-normalised proxy, bind your own resolver:
Retrying transient failures
RecaptchaClient takes any PSR-18 client, so you can wrap it with a retrying
decorator (e.g. rasuvaeff/retry's
Http\RetryingHttpClient) to survive transient network errors — retry only on
transport exceptions, since siteverify is a POST. No package change needed;
inject the decorated client where RecaptchaClient gets its PSR-18 client.
Dependency injection (Yii3)
Override params in your application config:
Translations
| Locale | File |
|---|---|
ru |
messages/ru/yii3-recaptcha.php |
To add more languages, create messages/<locale>/yii3-recaptcha.php:
Components
RecaptchaV2 (widget)
| Method | Description |
|---|---|
withSiteKey(string $siteKey): self |
Google site key (required). |
withId(string $id): self |
DOM id for the widget container. Default: auto-generated unique id (supports multiple widgets per page). |
withTheme(RecaptchaV2Theme $theme): self |
Light or Dark. Default: Light. |
withType(RecaptchaV2Type $type): self |
Image or Audio. Default: Image. |
withSize(RecaptchaV2Size $size): self |
Normal, Compact, or Invisible. Default: Normal. |
withJsApiUrl(string $url): self |
Override the script URL. |
withCallback(string $cb): self |
JS callback on success. |
withExpiredCallback(string $cb): self |
JS callback on expiry. |
withErrorCallback(string $cb): self |
JS callback on error. |
withNonce(string $nonce): self |
CSP nonce on every emitted <script>. |
render(): string |
Returns HTML. Throws MissingSiteKeyException if siteKey is not set. |
RecaptchaV3 (widget)
| Method | Description |
|---|---|
withSiteKey(string $siteKey): self |
Google site key (required). |
withAction(string $action): self |
Action name passed to grecaptcha.execute(). Default: submit. |
withFieldName(string $name): self |
Hidden input name (model attribute). Default: g-recaptcha-response. |
withFieldId(string $id): self |
Hidden input DOM id. Default: auto-generated unique id. |
withFormId(string $id): self |
Enable invisible-submit binding to this form id. Default: none (token filled on load). |
withBadge(RecaptchaV3Badge $badge): self |
Badge position: BottomRight (default), BottomLeft, or Hidden (+ legal notice). |
withJsApiUrl(string $url): self |
Override the script URL. |
withNonce(string $nonce): self |
CSP nonce on every emitted <script>/<style>. |
render(): string |
Returns HTML (script + hidden input + inline script). Throws MissingSiteKeyException if siteKey is not set. |
RecaptchaConfig
RecaptchaClient
verify() uses secretV2, verifyV3() uses secretV3 from config.
verifyWithSecret() uses a custom secret (for v2/v3 rules that override it).
The client never throws: on a transport/HTTP/JSON failure it returns a failed
VerificationResult tagged TRANSPORT_ERROR (fail-closed). In the validator
pipeline the handlers resolve clientIp through ClientIpResolverInterface — only
when the rule's sendRemoteIp and RecaptchaConfig::sendRemoteIp are both enabled.
VerificationResult
Fields, resolver, exceptions
| Type | Purpose |
|---|---|
Field\RecaptchaV2Field, Field\RecaptchaV3Field |
yiisoft/form-model fields (::field($model, $property)), delegate to the widgets. |
ClientIpResolverInterface + RemoteAddrClientIpResolver |
Pluggable client-IP resolution; default reads validated REMOTE_ADDR. |
RecaptchaRegistry |
Static fallback (configure(client, ipResolver?, translator?)) for no-arg handler construction; populated by the bootstrap. |
Exception\RecaptchaException |
Marker interface for all package exceptions. |
Exception\MissingSiteKeyException |
Thrown when a widget/field renders without a site key. |
Exception\MissingClientException |
Thrown when a handler has no client (neither injected nor registered). |
RecaptchaV2Rule / RecaptchaV2RuleHandler
| Parameter | Type | Default | Description |
|---|---|---|---|
message |
string |
'The CAPTCHA verification failed.' |
Error message. |
secret |
?string |
null |
Override secret. |
sendRemoteIp |
bool |
false |
Forward client IP. |
failOpenOnError |
bool |
false |
Pass validation when siteverify is unreachable (transport error). Default fails closed. |
skipOnEmpty |
bool\|callable\|null |
null |
Skip on empty. |
skipOnError |
bool |
false |
Skip on prior error. |
when |
?Closure |
null |
Conditional execution. |
RecaptchaV3Rule / RecaptchaV3RuleHandler
Same as v2, plus:
| Parameter | Type | Default | Description |
|---|---|---|---|
threshold |
float |
0.5 |
Minimum score in the 0.0..1.0 range. |
action |
?string |
null |
Expected action name. |
scoreTooLowMessage |
string |
'The CAPTCHA score is too low.' |
Score error. |
actionMismatchMessage |
string |
'The CAPTCHA action does not match.' |
Action error. |
Enums
| Enum | Values |
|---|---|
RecaptchaV2Theme |
Light, Dark |
RecaptchaV2Type |
Image, Audio |
RecaptchaV2Size |
Normal, Compact, Invisible |
Security
- The widget renders public site keys in HTML — this is intentional.
- Secrets are server-side only.
- Token verification goes over HTTPS.
- v3 score threshold and action validation prevent token reuse across contexts.
- Widget JS is built with
json_encodeusingJSON_HEX_TAG|JSON_HEX_APOS|JSON_HEX_QUOT|JSON_HEX_AMP, so callback names, actions, ids and other values cannot break out of the inline<script>(no raw string concatenation). sendRemoteIpis opt-in; the client IP comes fromClientIpResolverInterface. The default readsREMOTE_ADDR(validated withFILTER_VALIDATE_IP), not user input. Behind a proxy/CDN bind a proxy-aware resolver so the real client IP is used (see Client IP behind a proxy).- Fail-closed by default. If the siteverify endpoint is unreachable the client
returns a failed result (
TRANSPORT_ERROR) and the rule rejects — an outage cannot silently let bots through. Opt into fail-open per rule withfailOpenOnError: truewhen availability matters more than strictness. - Widgets accept a CSP
nonceviawithNonce()for strict Content-Security-Policy.
Examples
See examples/ for runnable scripts.
| Script | Shows | Needs server? |
|---|---|---|
widget-v2.php |
Rendering v2 widget | no |
widget-v3.php |
Rendering v3 widget | no |
Development
No PHP/Composer on the host — run in Docker via the composer:2 image:
make test-coverage and make mutation bootstrap pcov inside the Docker container
because the base composer:2 image does not ship with a coverage driver.
Or with Make:
CI runs composer build on PHP 8.3, 8.4, and 8.5.
License
BSD-3-Clause
All versions of yii3-recaptcha with dependencies
ext-filter Version *
psr/http-client Version ^1.0
psr/http-factory Version ^1.0
psr/http-message Version ^1.0 || ^2.0
yiisoft/form Version ^1.0
yiisoft/form-model Version ^1.1
yiisoft/html Version ^3.13 || ^4.0
yiisoft/request-provider Version ^1.3
yiisoft/translator Version ^3.0
yiisoft/validator Version ^2.5
yiisoft/widget Version ^2.2