Reads, relates, updates, and audits Fluent Forms forms, submissions, entry details, and submission meta from third-party plugins. Covers fluentFormApi, FormFieldsParser, Submission and SubmissionMeta models, form-scoped queries, response JSON versus normalized detail rows, pagination, capabilities, deletion hooks, and Free versus Pro tables. Use when building entry reports, exports, dashboards, REST endpoints, submission metadata, user-facing entry views, or code touching fluentform_submissio...
Scanned 9/5/2026
Install to Claude Code
npx -y skills add Lonsdale201/wp-agent-skills --skill fluentform-entries-data --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Fluentform Entries Data?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/lonsdale201-fluentform-entries-data)More formats (shields.io, HTML) on the badges page.
---
name: fluentform-entries-data
description: >-
Reads, relates, updates, and audits Fluent Forms forms, submissions, entry
details, and submission meta from third-party plugins. Covers fluentFormApi,
FormFieldsParser, Submission and SubmissionMeta models, form-scoped queries,
response JSON versus normalized detail rows, pagination, capabilities,
deletion hooks, and Free versus Pro tables. Use when building entry reports,
exports, dashboards, REST endpoints, submission metadata, user-facing entry
views, or code touching fluentform_submissions, fluentform_entry_details,
fluentform_submission_meta, fluentFormApi('submissions'), or entryInstance().
metadata:
wp-skills-author: "Soczó Kristóf"
wp-skills-contact: "mailto:lonsdale201@hotmail.com"
wp-skills-plugin: "fluentform"
wp-skills-plugin-version-tested: "6.2.7"
wp-skills-wp-version-tested: "7.0.2"
wp-skills-php-min: "7.4"
wp-skills-last-updated: "2026-07-20"
---
# Fluent Forms entries and data model
Use Fluent Forms' API/model layer after enforcing your own authorization. Keep
the canonical response snapshot, query projection, and addon metadata separate.
Read [data-contract.md](references/data-contract.md) before writing entry data,
exposing it over REST, joining nested fields, or supporting Pro drafts/payments.
## Availability contract
| Data/API | Availability in 6.2.7 |
|---|---|
| forms, submissions, entry details, form/submission meta | Free |
| `fluentFormApi()`, `FormFieldsParser`, `Submission`, `SubmissionMeta` | Free |
| draft/partial submissions | Pro |
| order items, transactions, payment subscriptions and coupons | Payment/Pro feature dependent |
The PHP helpers perform data access, not request authorization. A successful
`fluentFormApi()` call does not prove the current user may see the result.
## Read one form's entries
```php
use FluentForm\App\Modules\Acl\Acl;
$formId = absint($requestedFormId);
if (!$formId || !function_exists('fluentFormApi')) {
return new WP_Error('acme_unavailable', __('Fluent Forms is unavailable.', 'acme-addon'));
}
if (!Acl::hasPermission('fluentform_entries_viewer', $formId)) {
return new WP_Error('acme_forbidden', __('You cannot view these entries.', 'acme-addon'), [
'status' => 403,
]);
}
$form = fluentFormApi('forms')->find($formId);
if (!$form) {
return new WP_Error('acme_not_found', __('Form not found.', 'acme-addon'), [
'status' => 404,
]);
}
$page = max(1, absint($requestedPage));
$perPage = min(100, max(1, absint($requestedPerPage)));
$result = fluentFormApi('forms')->entryInstance($form)->entries([
'page' => $page,
'per_page' => $perPage,
'entry_type' => 'all',
'sort_type' => 'DESC',
'search' => sanitize_text_field((string) $requestedSearch),
]);
```
Use the form-scoped `entryInstance()` for a known form. The global
`fluentFormApi('submissions')` methods are useful for trusted internal reports,
but callers must constrain form IDs, user IDs, status, and page size themselves.
## Read a single form-scoped entry
```php
$entryResult = fluentFormApi('forms')
->entryInstance($form)
->entry(absint($entryId), false);
if (!$entryResult) {
return new WP_Error('acme_entry_not_found', __('Entry not found.', 'acme-addon'), [
'status' => 404,
]);
}
$entry = $entryResult['submission'];
$response = is_array($entry->response) ? $entry->response : [];
```
Do not fetch by entry ID globally and authorize with a different form ID. Scope
the database lookup and permission decision to the same normalized form ID.
## Resolve field definitions and labels
```php
use FluentForm\App\Modules\Form\FormFieldsParser;
$inputs = FormFieldsParser::getEntryInputs($form, ['admin_label', 'raw']);
$labels = FormFieldsParser::getAdminLabels($form, $inputs);
foreach ($response as $name => $value) {
$label = $labels[$name] ?? $name;
// Escape $label and $value for their actual output context.
}
```
`attributes.name`, not the visible label, connects the field definition to the
response. Labels and fields can change after old submissions were stored, so
always provide a fallback for historical/removed keys.
## Store addon state as submission meta
```php
use FluentForm\App\Helpers\Helper;
$entryId = absint($entryId);
$formId = absint($formId);
// First verify the entry belongs to $formId and the current operation is allowed.
Helper::setSubmissionMeta($entryId, '_acme_delivery_state', [
'status' => 'queued',
'updated_at' => current_time('mysql'),
], $formId);
$state = Helper::getSubmissionMeta($entryId, '_acme_delivery_state', []);
```
Namespace meta keys. Store bounded operational data, not credentials or copied
entry payloads. `SubmissionMeta` serializes values and is not encrypted.
## Mutation policy
- Prefer submission-time filters when deriving a stored field value.
- For status changes and deletion, use `SubmissionService` so Fluent Forms hooks,
files, logs, details, queued actions, and payment-related cleanup are considered.
- If an existing response must be edited, treat `response` JSON and affected
`entry_details` rows as one consistency boundary. Validate against the current
form, preserve unknown historical keys deliberately, update the timestamp, and
emit the appropriate audit hook/log.
- Never update only `fluentform_entry_details`; normal entry rendering and feeds
read `fluentform_submissions.response`.
- Never expose generic model `where`/sort/column inputs directly to a request.
## Security and performance rules
- Use `Acl::hasPermission('fluentform_entries_viewer', $formId)` for Fluent Forms
admin semantics, plus any domain-specific ownership rule your endpoint needs.
Use `fluentform_manage_entries` for mutations.
- Add nonce verification to cookie-authenticated writes; a nonce does not replace
the capability/form-scope check.
- Return an explicit field allowlist. Entries can contain personal data, IP,
source URLs, hidden fields, payment fields, and addon-injected values.
- Bound `per_page`, validate statuses, and use a fixed sort allowlist.
- Avoid `LIKE` searches over the large `response` JSON column for unbounded public
queries. Use detail rows or an addon-owned indexed table for frequent reports.
- Do not use `SubmissionService::find()` for a read-only probe without noticing
that it can mark `unread` entries as `read` by default in 6.2.7.
- Do not use `FluentForm\App\Models\Entry` as the primary model; the live model is
`FluentForm\App\Models\Submission`, while `FluentForm\App\Api\Entry` is the
form-scoped API wrapper.
## Pro boundary
Pro partial entries live in `fluentform_draft_submissions` and have a different
ownership/hash lifecycle. Do not merge them into completed-submission queries by
ID alone. Pro/payment records link through `submission_id`, but payment access
requires `fluentform_view_payments` or `fluentform_manage_payments` and must use
verified payment status, not merely the presence of a row.
## Cross-references
- Use `fluentform-submission-lifecycle` for creation-time data and hooks.
- Use `fluentform-custom-fields` for field-name and nested-value contracts.
- Use `wp-rest-api` when entries are exposed through a custom REST endpoint.
## References
- Official database schema: <https://developers.fluentforms.com/database/>
- Official model guide: <https://developers.fluentforms.com/database/models/>
- Official query builder guide: <https://developers.fluentforms.com/database/query-builder/>
- Verified Free source paths:
- `fluentform/boot/globals.php`
- `fluentform/app/Api/Form.php`
- `fluentform/app/Api/Entry.php`
- `fluentform/app/Api/Submission.php`
- `fluentform/app/Models/Submission.php`
- `fluentform/app/Models/EntryDetails.php`
- `fluentform/app/Models/SubmissionMeta.php`
- `fluentform/app/Services/Submission/SubmissionService.php`
- Verified Pro source path:
- `fluentformpro/src/classes/StepFormEntries.php`
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!