3

I have a custom field where I'm defining AttributeType::Mixed in order to achieve the affect of saving multiple pieces of data for a single field. The data gets stored as JSON as expected. Quick example shown below:

public function defineContentAttribute()
{

    return AttributeType::Mixed;

}

I was wondering though, is it possible to define multiple columns for a single field? If so will the field then require its own table? Not sure where to begin with this one.

Thanks for any assistance.

  • Out of interest, what's the benefit to using multiple columns? You've essentially got all the space you want using a JSON object. For instance, the Table field type stores all its column and default row data in that settings object. Happy to assist - but just need a bit more background on what your use-case is. – crawf May 7 '15 at 13:07
  • I'm concerned about querying a JSON string. JSON is ok, and I've used it myself in my own applications outside of Craft, but it comes with overhead that you would not have using separate columns. Regardless, I solved this problem by making a custom field, setting the table attribute to false, saving it using a record after element save, then relating the data to the element to which it belongs. – Matt V May 7 '15 at 13:37
  • Yeah, fair enough, and can totally understand. Depending on what you're doing, querying those settings can be a pain through JSON. – crawf May 7 '15 at 13:40
  • Hey Matt - Wondering if you have any update on your question. I'm interested in the answer. – Jesse Schutt May 20 '15 at 12:40
  • I don't have a tremendous amount of time right now to go into detail but I'll give you the gist of it. Every field has a "onAfterElementSave" method. You can utilize this method to save a field however you'd like. Essentially What I did was; create a record, in the function "onAfterElementSave" I set up logic on how I wanted the field to save, after the record is saved I relate it to the element to which it belongs (You can relate the data however you'd like but if you want to use Craft relations your field will need to save it's own elements). I suggest you look at the category field code. – Matt V May 21 '15 at 14:20
3

If your custom field needs more than the default column to store it's data you can create your own custom table (or tables) and store your data however you need to.

This involves a few things:

  • Create a Record that defines your database table
  • Save the data to the custom table
  • Retrieve the data from the custom table

Create a Record that defines your database table

To create a Record, take a look at the Craft Records documentation. The Record defines the columns in your database table and that custom table will get created when you install your plugin, and removed when you uninstall your plugin. So, after you create your Record, go ahead and re-install your plugin to get the database table to appear in the database and ensure it's the schema you need.

Save the data to the custom table

Now that you have your custom table, you can save data to it. In your Fieldtype Class CustomPlugin_CustomFieldType.php you can do so using the onAfterElementSave() method.

public function onAfterElementSave()
{
  // $this->element will give you access access to the Element Model  
  // your field is associated with (For example, EntryModel, CategoryModel, etc).

  // $this->model will give you access access to the FieldModel 
  // your field is associated with.

  // craft()->request->post will give you access to the post data 
  // submitted on the request.

  // Once you have retrieved and modified the data you want to save,
  // you can go ahead and save it to your custom table 
}

Retrieve the data from the custom table

To populate your field, you'll retrieve your data from your custom tables in the getInputHtml() method. In the example below, I'm using calling the getCustomFieldValues() method from the service layer which would query the database and give me back the data I need to hand off to my template to display:

public function getInputHtml($name, $value)
{
    $values = craft()->customPlugin->getCustomFieldValues();

    return craft()->templates->render('customplugin/fields/input', array(
        'name'       => $name,
        'values'     => $values
    ));
}
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.