{"id":5062,"date":"2026-04-24T12:38:50","date_gmt":"2026-04-24T10:38:50","guid":{"rendered":"https:\/\/cevento-plugin.com\/docs\/005-fieldbag\/"},"modified":"2026-04-24T12:38:50","modified_gmt":"2026-04-24T10:38:50","slug":"005-fieldbag","status":"publish","type":"docs","link":"https:\/\/cevento-plugin.com\/en\/docs\/005-fieldbag\/","title":{"rendered":"FieldBag Class"},"content":{"rendered":"\n<h2 id=\"purpose\">Purpose\n<\/h2><p><code>FieldBag<\/code> is the runtime wrapper in Cevento that holds a form definition, with optional single-submission payload data.<\/p>\n<p>It combines three responsibilities into one object:<\/p>\n<ol>\n<li>\n<p><strong>Field registry (object graph)<\/strong><\/p>\n<ul>\n<li>It instantiates all field objects for the submitted form (based on the form builder config).<\/li>\n<li>It holds those <code>Field<\/code> instances so you can query and operate on them consistently.<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>Submission data access (normalized + raw)<\/strong><\/p>\n<ul>\n<li>It stores the incoming request payload (<code>field_key =&gt; field_value<\/code>) as raw input.<\/li>\n<li>It provides a filtered\/normalized representation of that data for processing and persistence.<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>Validation + error aggregation<\/strong><\/p>\n<ul>\n<li>It triggers validation for each field after the submission.<\/li>\n<li>It collects <strong>field-specific<\/strong> and <strong>global<\/strong> errors in a structure the frontend can render.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>The result: validation hooks and business logic can work with <em>field objects<\/em> instead of dealing with raw <code>$_POST<\/code> arrays and form schema details.<\/p>\n<h2 id=\"usage-patterns\">Usage Patterns<\/h2>\n<h3>Field-level custom validation<\/h3>\n<p>Operate on <code>Field<\/code> objects instead of handling $_POST data directly:<\/p>\n<pre><code class=\"language-php\">add_action('cevento\/validate', function ($fieldBag, $event) {\n    $nameField = $fieldBag-&gt;getField('Name');   \/\/ label lookup\n    $nameValue = $nameField-&gt;getValue();\n\n    if (strlen($nameValue) addError('Name must be at least 3 characters long.');\n    }\n\n    $fieldBag-&gt;addGlobalError('A global error message can be placed here.');\n}, 10, 2);<\/code><\/pre>\n<h3>Query fields by type<\/h3>\n<p>Useful for repeatable groups like participants.<\/p>\n<pre><code class=\"language-php\">$participantGroups = $fieldBag-&gt;getFieldsByType('participants_group');\nforeach ($participantGroups as $groupField) {\n    $values = $groupField-&gt;getValue(); \/\/ usually array\n}<\/code><\/pre>\n<h3>Read normalized vs raw submission data<\/h3>\n<ul>\n<li><code>getDataRaw()<\/code> gives you <strong>exact<\/strong> stored submission data<\/li>\n<li><code>getData()<\/code> returns <strong>filtered\/normalized<\/strong> data:\n<ul>\n<li>performs field-specific sanitization<\/li>\n<li>removes honeypot field keys<\/li>\n<li>normalizes checkbox <code>'on'<\/code> into the configured value (<code>general.value<\/code>)<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Use <code>getData()<\/code> for business logic and persistence.<br>\nUse <code>getDataRaw()<\/code> for debugging or low-level inspection.<\/p>\n<h2 id=\"api-reference\">API Reference<\/h2>\n<h3>Static Factory<\/h3>\n<h4><code>FieldBag::fromEvent(array $event, array $data = []): FieldBag<\/code><\/h4>\n<p>Creates a <code>FieldBag<\/code> using an event&rsquo;s booking form configuration.<\/p>\n<p><strong>Parameters<\/strong><\/p>\n<ul>\n<li><code>$event<\/code>: the event array of the current context<\/li>\n<li><code>$data<\/code>: submission payload (optional, defaults to an empty array)<\/li>\n<\/ul>\n<p><strong>Returns<\/strong><\/p>\n<ul>\n<li><code>FieldBag<\/code> with all field instances created and optionally populated with submission data.<\/li>\n<\/ul>\n<h3>Field Lookup<\/h3>\n<h4><code>getField(string $key)<\/code><\/h4>\n<p>Returns a <code>Field<\/code> instance by:<\/p>\n<ul>\n<li><strong>field key<\/strong> if <code>$key<\/code> starts with <code>field_<\/code><\/li>\n<li>otherwise <strong>field label<\/strong> match<\/li>\n<\/ul>\n<p><strong>Returns<\/strong><\/p>\n<ul>\n<li><code>Field|null<\/code><\/li>\n<\/ul>\n<h4><code>hasField(string $fieldKey): bool<\/code><\/h4>\n<p>Checks whether a field key exists in the current bag.<\/p>\n<h4><code>getFields(): array<\/code><\/h4>\n<p>Returns all <strong>top-level fields<\/strong> that are currently registered.<\/p>\n<h4><code>getAllFields(): array<\/code><\/h4>\n<p>Returns every registered field instance, including nested\/child fields.<\/p>\n<h4><code>getFieldsByType(string $type): array<\/code><\/h4>\n<p>Returns all registered field of a specific field type.<\/p>\n<h3>Data Access<\/h3>\n<h4><code>getData(): array<\/code><\/h4>\n<p>Returns normalized submission data as associative array of <code>field_key =&gt; value<\/code> pairs:<\/p>\n<h4><code>getDataRaw(): array<\/code><\/h4>\n<p>Returns <code>$this-&gt;data<\/code> exactly as currently stored\/submitted.<\/p>\n<h3>Validation<\/h3>\n<h4><code>addGlobalError(string $message): void<\/code><\/h4>\n<p>Adds a global error message, typically rendered above the form.<\/p>\n<h4><code>hasErrors(): bool<\/code><\/h4>\n<p>Returns <code>true<\/code> if any field or global errors exist.<\/p>\n<p>Return type is effectively <code>bool<\/code>.<\/p>\n<h4><code>getErrors(): array<\/code><\/h4>\n<p>Returns the complete error payload:<\/p>\n<pre><code class=\"language-php\">[\n  'fields' =&gt; [ 'field_key' =&gt; ['msg1', 'msg2'], ... ],\n  'global' =&gt; ['msg1', 'msg2', ...]\n]<\/code><\/pre>\n<h2 id=\"built-in-helpers\">Built-in Helpers<\/h2>\n<h4><code>getTotalParticipants(): int<\/code><\/h4>\n<p>Counts total participants across all <code>participants_group<\/code> fields. If no participant group exists, returns <code>0<\/code><\/p>\n<h4><code>getParticipants(): array<\/code><\/h4>\n<p>Flattens participants across all <code>participants_group<\/code> fields into a single array.<\/p>\n<h2 id=\"behavioral-details-and-edge-cases\">Behavioral Details and Edge Cases<\/h2>\n<h3><code>getField()<\/code> can return <code>null<\/code><\/h3>\n<p>If no field matches the provided key or label, <code>getField()<\/code> returns <code>null<\/code>. Always check for null before using the returned value.<\/p>\n<h3>Checkbox normalization<\/h3>\n<p><code>getData()<\/code> treats checkbox submissions where value is <code>'on'<\/code> as &ldquo;checked&rdquo; and replaces <code>'on'<\/code> with the configured &ldquo;general.value&rdquo;. This makes downstream logic stable even if the browser submits <code>'on'<\/code>. If there is no value in the current submission, the checkbox is considered &ldquo;unchecked&rdquo; and <code>null<\/code> is beeing returned.<\/p>\n<h3>Parent\/child field handling<\/h3>\n<p><code>getFields()<\/code> filters out fields that have a parent state. This implies:<\/p>\n<ul>\n<li>validation iteration runs only on top-level fields<\/li>\n<li>child fields are validated indirectly by their parent field type<\/li>\n<\/ul>\n\n\n","protected":false},"featured_media":0,"parent":0,"template":"","meta":{"_acf_changed":false},"thema":[682],"class_list":["post-5062","docs","type-docs","status-publish","hentry","thema-development"],"acf":{"excerpt":"Everything about the Fieldbag class and how to utilize it for custom submission processing & validation.","toc":"<ol class=\"toc\">\n<li><a href=\"#purpose\"  uk-scroll=\"offset: 120\">Purpose<\/a><\/li>\n<li><a href=\"#usage-patterns\"  uk-scroll=\"offset: 120\">Usage Patterns<\/a><\/li>\n<li><a href=\"#api-reference\"  uk-scroll=\"offset: 120\">API Reference<\/a><\/li>\n<li><a href=\"#built-in-helpers\"  uk-scroll=\"offset: 120\">Built-in Helpers<\/a><\/li>\n<li><a href=\"#behavioral-details-and-edge-cases\"  uk-scroll=\"offset: 120\">Behavioral Details and Edge Cases<\/a><\/li>\n<\/ol>\n"},"_links":{"self":[{"href":"https:\/\/cevento-plugin.com\/en\/wp-json\/wp\/v2\/docs\/5062","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cevento-plugin.com\/en\/wp-json\/wp\/v2\/docs"}],"about":[{"href":"https:\/\/cevento-plugin.com\/en\/wp-json\/wp\/v2\/types\/docs"}],"wp:attachment":[{"href":"https:\/\/cevento-plugin.com\/en\/wp-json\/wp\/v2\/media?parent=5062"}],"wp:term":[{"taxonomy":"thema","embeddable":true,"href":"https:\/\/cevento-plugin.com\/en\/wp-json\/wp\/v2\/thema?post=5062"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}