Skip to content
Back to skills

Fluentform Entries Data

ASecurity

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...

  • 22 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 5, 2026
databasesrustphpsqlapidatabasesecurityperformance

Works with

  • api

Security analysis

A100/100

Pro scans all 3 files and shows the line behind each finding

Scanned September 5, 2026

npx -y skills add Lonsdale201/wp-agent-skills --skill fluentform-entries-data --agent claude-code

Installs 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 with every re-scan.

Security grade badge for Fluentform Entries Data
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/lonsdale201-fluentform-entries-data/badge)](https://www.skillsdirectory.com/skills/lonsdale201-fluentform-entries-data)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
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`

Files in this skill

  • SKILL.md7.8 KB
  • agents/openai.yaml299 B
  • references/data-contract.md5.9 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.