<p>Nope – a single field can only have a single column in the <code>craft_content</code> table.</p>

<p>If you need your <a href="https://craftcms.com/docs/plugins/field-types" rel="nofollow noreferrer">FieldType</a> to save complex data, you have two options:</p>

<p>The easiest approach – by far – is to simply have Craft serialize the data before it's saved to the <code>craft_content</code> table. Simply return <code>AttributeType::Mixed</code> from your FieldType class' <a href="https://craftcms.com/docs/plugins/field-types#customizing-the-database-column-type" rel="nofollow noreferrer"><code>defineContentAttribute()</code></a> method:</p>

<pre><code>public function defineContentAttribute()
{
    return AttributeType::Mixed;
}
</code></pre>

<p>With the above, your FieldType's <em>value</em> will be an array. This means that when you save the data, you'll need to use the array syntax for the input fields' <code>name</code> attributes; e.g. if you had two "sub fields" called <code>foo</code> and <code>bar</code>, your input fields should look like this:</p>

<pre><code>&lt;input type="text" name="myFieldHandle[foo]" /&gt;
&lt;input type="text" name="myFieldHandle[bar]" /&gt;
</code></pre>

<p>To output the sub fields in a template, you'd do something like this:</p>

<pre><code>{{ entry.myFieldHandle.foo }}
{{ entry.myFieldHandle.bar }}
</code></pre>

<p>The <em>other</em> approach for saving complex values is to have your FieldType use a custom database table. Explaining this in any great detail is impossible without knowing a lot more about your particular use case and a good overview is already given in <a href="https://craftcms.stackexchange.com/a/11000/1098">Ben Parizek's great answer to a similar question</a> – but here's the gist of it:</p>

<p>First, you'll need to create a <a href="https://craftcms.com/docs/plugins/records" rel="nofollow noreferrer">Record</a> class, containing your custom FieldType's columns (sub fields) and their attribute types. Whenever your plugin is installed, Craft will create custom database tables based on your plugin's Records (which means that if your plugin is already installed, you'll need to uninstall and install it again to actually have Craft create the tables – if this is a publicly available plugin you should probably write a <a href="https://craftcms.com/docs/plugins/migrations" rel="nofollow noreferrer">Migration</a> to ensure the table is created whereever the plugin is already installed).</p>

<p>Note that your custom table should probably have <a href="https://craftcms.com/docs/plugins/records#defining-relations" rel="nofollow noreferrer">foreign keys</a> for the element and field ID's, to create the necessary relations between the field data, the field and the actual element (e.g. entry).</p>

<p>To actually <em>save</em> the data to your custom table, you'll need to add a <code>onAfterElementSave</code> hook to your FieldType class. This hook is run whenever an element with a field using your custom FieldType is saved. The field and element ID's (and the actual data to save), is available via the FieldType's <code>model</code> and <code>element</code> properties, respectively:</p>

<pre><code>public function onAfterElementSave()
{

    $element = $this-&gt;element; // The element being saved
    $elementId = $this-&gt;element-&gt;id; // The ID for the element being saved
    $fieldModel = $this-&gt;model; // The field's model
    $fieldHandle = $field-&gt;model-&gt;handle; // The field's handle
    $data = $this-&gt;element-&gt;getContent()-&gt;getAttribute($fieldHandle); // The data you want to save

    ...

    // Some custom logic to save the data

}
</code></pre>

<p>To save the data via the <code>onAfterElementSave</code> hook, you'll most likely need to use the <a href="https://craftcms.com/docs/plugins/database" rel="nofollow noreferrer"><code>DbCommand</code></a> class to build a custom query.</p>

<p>In order to populuate your field (i.e. pull the data) for use in templates and the <code>getInputHtml()</code> method, you'll also need to write a custom query. A good place to do this is in your FieldType's <a href="https://craftcms.com/docs/plugins/field-types#modifying-your-fieldtypes-stored-data-for-use" rel="nofollow noreferrer"><code>prepValue()</code></a> method, i.e. something like this:</p>

<pre><code>public function prepValue($value) {
    $value = null;
    $fieldId = $this-&gt;model-&gt;id;
    if ($this-&gt;element-&gt;id) {
        // Then element has been saved before and there might be existing data – try to pull it
        $value = craft()-&gt;db-&gt;createCommand()
            -&gt;select('foo, bar')
            -&gt;from('yourcustomdatabasetable')
            -&gt;where([
                'fieldId' =&gt; $this-&gt;model-&gt;id,
                'elementId' =&gt; $this-&gt;element-&gt;id,
            ])
            -&gt;queryAll();
    }
    return $value;
}
</code></pre>

<p>Finally, to save some overhead its a good idea to return <code>false</code> from your FieldType class' <code>defineContentAttribute</code> method (this basically tells Craft to not save anything to the <code>craft_content</code> table):</p>

<pre><code>public function defineContentAttribute()
{
    return false;
}
</code></pre>

<p>Note that there are other aspects to consider as well, such as offloading the business logic in saving and retrieving the data to a <a href="https://craftcms.com/docs/plugins/services" rel="nofollow noreferrer">service layer</a> (a good idea), and using <a href="https://craftcms.com/docs/plugins/models" rel="nofollow noreferrer">Models</a> to pass data between records, the service layer and your templates (a <em>very</em> good idea), but it's a bit out of scope for an SE answer like this. In any case, I hope the above will get you up and running. In any case, if you simply need to two text fields, I'd go with the first approach – it's way easier.</p>

CC BY-SA 3.0
2016-11-21T16:45:38.137Z
Thank so much @Mats. That's given me all the information I need. I'll need to run some DB queries on data from 1 of the fields. I'll dive in to a Model. Knowing the correct methods will be a time save as well :)
Elliot Lewis
CC BY-SA 3.0
2016-11-20T10:13:24.220Z
2017-04-20T04:41:44.367Z
2017-04-20T04:41:44.367Z
Mats Mikkel Rummelhoff
<p>I can have many 'settings' fields for a fieldType and they're saved as a serialized string in the database.</p>

<p>Is it possible to have more than one field for the fieldType itself? It looks like there's only one column in <code>craft_content</code>. So I'm not sure you can.</p>

<p>Is the preferred way to create your own table and store multiple field data there? And would that be using <code>prepValueFromPost()</code>?</p>

CC BY-SA 3.0
2016-11-19T20:59:48.180Z
You can create multiple fieldTypes in one plugin, each with there own settings.
a-am
CC BY-SA 3.0
2016-11-20T02:11:30.397Z
I don't want to define 2 fieldTypes. I need 1 fieldType with 2 fields, in this case 2 text fields.
Elliot Lewis
<plugin-development><plugins><fieldtypes><custom-fieldtype><custom-field>
More than one field for a fieldtype plugin
# More than one field for a fieldtype plugin

(Asked by: username_0 on 2016-11-18)

I can have many 'settings' fields for a fieldType and they're saved as a serialized string in the database.

Is it possible to have more than one field for the fieldType itself? It looks like there's only one column in `craft_content`. So I'm not sure you can.

Is the preferred way to create your own table and store multiple field data there? And would that be using `prepValueFromPost()`?

**Tags:** plugin-development, plugins, fieldtypes, custom-fieldtype, custom-field

> **Comments:**
> **username_1**: You can create multiple fieldTypes in one plugin, each with there own settings.  
> **username_0**: I don't want to define 2 fieldTypes. I need 1 fieldType with 2 fields, in this case 2 text fields.  

---

## 1 answers

### Answer by username_2 on 2016-11-20. Score: 3 | Accepted answer

Nope – a single field can only have a single column in the craft_content table.
If you need your FieldType to save complex data, you have two options:
The easiest approach – by far – is to simply have Craft serialize the data before it's saved to the craft_content table. Simply return AttributeType::Mixed from your FieldType class' defineContentAttribute() method:
public function defineContentAttribute()
{
    return AttributeType::Mixed;
}

With the above, your FieldType's value will be an array. This means that when you save the data, you'll need to use the array syntax for the input fields' name attributes; e.g. if you had two "sub fields" called foo and bar, your input fields should look like this:



To output the sub fields in a template, you'd do something like this:
{{ entry.myFieldHandle.foo }}
{{ entry.myFieldHandle.bar }}

The other approach for saving complex values is to have your FieldType use a custom database table. Explaining this in any great detail is impossible without knowing a lot more about your particular use case and a good overview is already given in Ben Parizek's great answer to a similar question – but here's the gist of it:
First, you'll need to create a Record class, containing your custom FieldType's columns (sub fields) and their attribute types. Whenever your plugin is installed, Craft will create custom database tables based on your plugin's Records (which means that if your plugin is already installed, you'll need to uninstall and install it again to actually have Craft create the tables – if this is a publicly available plugin you should probably write a Migration to ensure the table is created whereever the plugin is already installed).
Note that your custom table should probably have foreign keys for the element and field ID's, to create the necessary relations between the field data, the field and the actual element (e.g. entry).
To actually save the data to your custom table, you'll need to add a onAfterElementSave hook to your FieldType class. This hook is run whenever an element with a field using your custom FieldType is saved. The field and element ID's (and the actual data to save), is available via the FieldType's model and element properties, respectively:
public function onAfterElementSave()
{

    $element = $this->element; // The element being saved
    $elementId = $this->element->id; // The ID for the element being saved
    $fieldModel = $this->model; // The field's model
    $fieldHandle = $field->model->handle; // The field's handle
    $data = $this->element->getContent()->getAttribute($fieldHandle); // The data you want to save

    ...

    // Some custom logic to save the data

}

To save the data via the onAfterElementSave hook, you'll most likely need to use the DbCommand class to build a custom query.
In order to populuate your field (i.e. pull the data) for use in templates and the getInputHtml() method, you'll also need to write a custom query. A good place to do this is in your FieldType's prepValue() method, i.e. something like this:
public function prepValue($value) {
    $value = null;
    $fieldId = $this->model->id;
    if ($this->element->id) {
        // Then element has been saved before and there might be existing data – try to pull it
        $value = craft()->db->createCommand()
            ->select('foo, bar')
            ->from('yourcustomdatabasetable')
            ->where([
                'fieldId' => $this->model->id,
                'elementId' => $this->element->id,
            ])
            ->queryAll();
    }
    return $value;
}

Finally, to save some overhead its a good idea to return false from your FieldType class' defineContentAttribute method (this basically tells Craft to not save anything to the craft_content table):
public function defineContentAttribute()
{
    return false;
}

Note that there are other aspects to consider as well, such as offloading the business logic in saving and retrieving the data to a service layer (a good idea), and using Models to pass data between records, the service layer and your templates (a very good idea), but it's a bit out of scope for an SE answer like this. In any case, I hope the above will get you up and running. In any case, if you simply need to two text fields, I'd go with the first approach – it's way easier.

> **Comments:**
> **username_0**: Thank so much @Mats. That's given me all the information I need. I'll need to run some DB queries on data from 1 of the fields. I'll dive in to a Model. Knowing the correct methods will be a time save as well :)  

---

