Skip to content

Conversation

@bastianallgeier
Copy link
Member

@bastianallgeier bastianallgeier commented Nov 20, 2025

Merge first

Description

In this PR, I'm trying to explore how well we can reflect the new Field classes with named arguments. Turns out: very well. But we need to define them all in the constructor. I'm torn here. It can be a lot of work and there are arguments that are super annoying to repeat (model, siblings, when, width, translate, etc.) But on the other hand it really gives a fantastic overview of all the capabilities of a field. It's somehow very close to the property table in our docs, which I like a lot. Maybe we can find a way to not have to pass at least Model and Siblings each time and only focus on the props that also turn up in our table?

We can now reflect such classes like this:

use Kirby\Form\Field\BlocksField;
use Kirby\Reflection\Field;

$blocks = new BlocksField();
$field = new Field($blocks);

$field->props();  

Here's the output for the blocks field …

[
    "autofocus" => [
      "name" => "autofocus",
      "type" => "bool",
      "default" => false,
      "description" => "Sets the focus on this field when the form loads. Only the first field with this label gets",
    ],
    "default" => [
      "name" => "default",
      "type" => "array",
      "default" => [],
      "description" => "Default value for the field, which will be used when a page/file/user is created",
    ],
    "disabled" => [
      "name" => "disabled",
      "type" => "bool",
      "default" => false,
      "description" => "If `true`, the field is no longer editable and will not be saved",
    ],
    "empty" => [
      "name" => "empty",
      "type" => "array|string|null",
      "default" => null,
      "description" => "Sets the text for the empty state box",
    ],
    "fieldsets" => [
      "name" => "fieldsets",
      "type" => "array|string|null",
      "default" => null,
      "description" => "Defines the allowed block types in the blocks field. See below.",
    ],
    "help" => [
      "name" => "help",
      "type" => "array|string|null",
      "default" => null,
      "description" => "Optional help text below the field",
    ],
    "group" => [
      "name" => "group",
      "type" => "?string",
      "default" => null,
      "description" => "Group name to identify all block fields that can share blocks via drag & drop",
    ],
    "label" => [
      "name" => "label",
      "type" => "array|string|null",
      "default" => null,
      "description" => "The field label can be set as string or associative array with translations",
    ],
    "name" => [
      "name" => "name",
      "type" => "?string",
      "default" => null,
      "description" => "",
    ],
    "max" => [
      "name" => "max",
      "type" => "?int",
      "default" => null,
      "description" => "Sets the maximum number of allowed items in the field",
    ],
    "min" => [
      "name" => "min",
      "type" => "?int",
      "default" => null,
      "description" => "Sets the minimum number of required items in the field",
    ],
    "pretty" => [
      "name" => "pretty",
      "type" => "bool",
      "default" => false,
      "description" => "Saves pretty printed JSON in text files",
    ],
    "required" => [
      "name" => "required",
      "type" => "bool",
      "default" => false,
      "description" => "If `true`, the field has to be filled in correctly to be saved.",
    ],
    "translate" => [
      "name" => "translate",
      "type" => "bool",
      "default" => true,
      "description" => "Should the field be translatable?",
    ],
    "when" => [
      "name" => "when",
      "type" => "array",
      "default" => [],
      "description" => "Conditions when the field will be shown",
    ],
    "width" => [
      "name" => "width",
      "type" => "?string",
      "default" => "1/1",
      "description" => "The width of the field in the field grid. Available widths: `1/1`, `1/2`, `1/3`, `1/4`, `2/3`, `3/4`",
    ],
  ]

@distantnative
Copy link
Member

distantnative commented Nov 20, 2025

@bastianallgeier do we want to put this in the core and not just getkirby.com?

One open todo in regard to the docs I see here is that we have named arguments that are not blueprint options (model, siblings) and how to differentiate them. Is hard coding them ok? Or limited if later field classes have their own arguments that shouldn't be blueprint options?

@bastianallgeier
Copy link
Member Author

bastianallgeier commented Nov 21, 2025

I still haven't given up on the dream that we can turn this into an editor at some point - and even if it is only for individual field options. I also think that we could heavily benefit from heaving this in the core when it comes to exporting JSON schemas for blueprints. The code that it takes is so small that I would not mind having it in there.

About the props. I've mentioned in the description that I'm really not happy about having model and siblings in the constructor. I think it would be really nice if field classes would not have to repeat them all the time. Maybe we could inject them after creation? This would mean though that we cannot rely on them in setters that are called in the constructor, which could be a bit nasty. But if we keep every property "lazy" it should be fine. Then the factory method could do something like this:

$field = new BlocksField(...$args);
$field->setModel($model);
$field->setSiblings($model);

For other props that should not be public, we could either think about using attributes in their docblocks or a dynamic ignore list. I'd suggest to start with a fixed list and as soon as we get into a dead end with that, we can work on a better solution.

@bastianallgeier bastianallgeier force-pushed the v6/refact/fields-named-args branch from f9e6fd7 to 14fb5c2 Compare November 21, 2025 09:51
@bastianallgeier bastianallgeier force-pushed the v6/feat/field-reflection branch 3 times, most recently from 7ddd9c1 to 258b6b6 Compare November 21, 2025 09:58
@distantnative distantnative force-pushed the v6/refact/fields-named-args branch 2 times, most recently from 5dd5edd to 48baca2 Compare November 21, 2025 18:04
@bastianallgeier bastianallgeier force-pushed the v6/feat/field-reflection branch from 258b6b6 to b9a63f3 Compare November 22, 2025 12:05
@bastianallgeier bastianallgeier force-pushed the v6/refact/fields-named-args branch 5 times, most recently from d341043 to df26bc3 Compare November 22, 2025 12:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants