How to store multidimensional arrays from a custom panel field in yaml

Hey there,

I am currently developing a custom panel field that has several inputs for every day of the week to give the user the opporturnity to enter opening or visiting hours.

The form itself looks good so far in the panel, but the data is not stored in the content folder. I implemented the text input fields with array name notation (eg. hours[Sun][from], hours[Sun][to], hours[Mon][from] etc). When I debug the app until the call to $site->update(), everything looks fine to me.

Is Kirby capable of storing this array data? If yes, do I need to do something special?

Best,
benzin

How are you trying to store the data? Could you post your code, pls.?

I do not trigger it anywhere myself. I only extended the BaseField class, generate the input elements and implemented a validate stub.

class HoursField extends BaseField
{
    static public $assets = [
        'css' => ['hours.css']
    ];

    protected $dayNames = [
        'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'
    ];

    protected $days = 7;

    protected $rows = 2;

    protected $fields = [];

    public function fields() {
        for ($r = 0; $r < $this->rows; $r++) {
            for ($d = 0; $d < $this->days; $d++) {
                $inputFrom = new Brick('input');
                $inputFrom->attr('name', "hours[$d][$r][from]");
                $inputFrom->addClass('input');
                $this->fields[$r][$d]['from'] = $inputFrom;

                $inputTo = new Brick('input');
                $inputTo->attr('name', "hours[$d][$r][to]");
                $inputTo->addClass('input');
                $this->fields[$r][$d]['to'] = $inputTo;
            }
        }
        return $this->fields;
    }

    public function input() {
        return tpl::load(__DIR__ . DS . 'template.php', ['field' => $this]);
    }

    public function validate() {
        // TODO: implement validate function
        return true;
    }
}

If you want to store structured data, you would have to yaml encode your data. You might want to check out the structure field.

Thanks for your help!

First, I do not want to use the core structure field for several reasons :wink:
Where should the encoding be done? Is it done in the field class or in a custom field controller?

The Panel calls the result method of your field. It should return a string with the value you want to store. So in your case, you would get the data from the request and convert it to YAML.

Another thing: You probably shouldn’t hard-code the name of the input (“hours”), otherwise you can’t use multiple fields of the same type. The recommended way is to use $this->name() instead.

1 Like

Thanks a lot @lukasbestle. That explained a lot. I missed the line with the call to $field->result(). I will work on from here myself and see how much further I get :wink:

Thanks for your hint regarding the name!

Funny you should ask this— just had to figure out the same problem for my Map field.

Here is my implementation.

Whatever other field you’ve extended should implement the method already, so calling parent::result() ought to grab your data out of the POST request, which in our cases will be the multi-dimensional PHP object.

The Toolkit provides the YAML encoding functionality you need.

Also! Be sure to implement the value method to make sure your data is decoded when loaded into the panel.

Good luck! :v:️

1 Like