如何显示实体的子类别?

I have two entities: Supplier and Category joined ManyToMany.

Next, I have a form builder class where I add EntityType::class.

Category structure:

id, categoryName, parentId - where parentIds value can be:
0 - head category
1 - subcategory
etc

I need to display (in twig template) categories with structure:

Category1
    Subcategory1
    Subcategory2
Category2
    Subcategory3
    Subcategory4

etc. where Category are some kind of header and subcategory are checkboxes.

Please somebody give me a tip how to do this.

Building on what we discussed in the comments, the following worked in my test environment:

InSupplierType::buildForm:

->add('categories', EntityType::class, [
    'class' => Category::class,
    'choice_label' => 'name',
    'group_by' => 'parent',
    'multiple' => true,
    'expanded' => true
])

Though without form customization this would only render the checkboxes without headers. This is discussed here: https://github.com/symfony/symfony/issues/5489#issuecomment-194943922

Implementing the fix by MaxE17677 the view would look something like this:

{% extends 'base.html.twig' %}

{% form_theme form _self %}

{# @see: https://github.com/symfony/symfony/issues/5489#issuecomment-194943922 #}
{%- block choice_widget_expanded -%}
     <div {{ block('widget_container_attributes') }}>
        {% for name, choices in form.vars.choices %}
            {% if choices is iterable  %}
                <label class="choice_category">
                    <strong>
                        {{ choice_translation_domain is same as(false) ? name : name|trans({}, choice_translation_domain) }}
                    </strong>
                </label>
                <div>
                    {% for key,choice in choices %}
                        {{ form_widget(form[key]) }}
                        {{ form_label(form[key]) }}
                    {% endfor %}
                </div>
            {% else %}
                {{- form_widget(form[name]) -}}
                {{- form_label(form[name], null, {translation_domain: choice_translation_domain}) -}}
            {% endif %}
        {% endfor %}
{%- endblock choice_widget_expanded -%}

{% block body %}
    <div class="container">
        {{ form_start(form) }}
            {{ form_row(form.categories) }}
        {{ form_end(form) }}
    </div>
{% endblock %}

Preview:

Preview


The crucial thing is that you use group_by feature of the ChoiceType. To get this to work with your current entities you might need to also use the query_builder setting of EntityType. Something like:

// ...
'query_builder' => function (EntityRepository $er) {
    return $er
        ->createQueryBuilder('c')
        ->where('c.parentId = 1')
    ;
},

along with:

// ...
'group_by' => function ($category) {
  // *pseudo-code*
  return $category->getParent()->getName();
}