Skip to content

Instantly share code, notes, and snippets.

@mdzzohrabi
Last active February 14, 2024 17:02
Show Gist options
  • Save mdzzohrabi/784034549f2217badf96e844df2792e5 to your computer and use it in GitHub Desktop.
Save mdzzohrabi/784034549f2217badf96e844df2792e5 to your computer and use it in GitHub Desktop.
Symfony Entity Tree ( Hierarchy ) Form Type
<?php
/**
* (c) Masoud Zohrabi <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Mdzzohrabi\Form;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\ChoiceList\View\ChoiceView;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* Class EntityTreeType
* @package Mdzzohrabi\Form
*/
class EntityTreeType extends AbstractType {
public function buildView( FormView $view , FormInterface $form , array $options ) {
$choices = [];
foreach ( $view->vars['choices'] as $choice ) {
if ( $choice->data->getParent() === null )
$choices[ $choice->value ] = $choice->data;
}
$choices = $this->buildTreeChoices( $choices );
$view->vars['choices'] = $choices;
}
/**
* @param object[] $choices
* @param int $level
* @return array
*/
protected function buildTreeChoices( $choices , $level = 0 ) {
$result = array();
foreach ( $choices as $choice ){
$result[ $choice->getId() ] = new ChoiceView(
$choice,
(string)$choice->getId(),
str_repeat( '--' , $level ) . ' ' . $choice->getName(),
[]
);
if ( !$choice->getChilds()->isEmpty() )
$result = array_merge(
$result,
$this->buildTreeChoices( $choice->getChilds() , $level + 1 )
);
}
return $result;
}
public function getParent() {
return EntityType::class;
}
}
@arvodia
Copy link

arvodia commented Mar 6, 2021

FIX BUG

$result = array_merge(
        $result,
        [new ChoiceView(
                $choice,
                (string)$choice->getId(),
                str_repeat($options['prefix'], $level) . ' ' . $choice->getName(),
                []
            )]
        );
if (!$choice->$children_method_name()->isEmpty())
    $result = array_merge(
        $result,
        $this->buildTreeChoices($choice->$children_method_name(), $options, $level + 1)
    );

@josequinta-pixelarus
Copy link

Hello!
Thank you for share this code!

It works fine when "multiple" and "expanded" are false, but:

'multiple' => true,
'expanded' => true,

Choices generated by this class are overridden by original EntityType class, losing hierarchy and order.
How can we do?
Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment