Vedremo come sfruttare i tipi di campi Jsonb di PostgreSQL in un'interfaccia générée di sonata.
Partiamo dal presupposto che voi maîbarate diéjài concetti di base di Symfony, Sonata e PostgreSql.
Tutto d’approccio créabbiamo una tabella molto semplice in PostgreSQL che conterrà un campo di tipo Jsonb.
CREATE SEQUENCE public.table1_id_seq;
CREATE TABLE public.table1 (
id integer DEFAULT nextval('public.table1_id_seq'::regclass) NOT NULL,
var1 character varying(250),
var2 jsonb
);
ALTER TABLE ONLY public.table1
ADD CONSTRAINT table1_pkey PRIMARY KEY (id);
Bisogna poi générer l’entità e la sua interfaccia di’amministratore
php bin/console doctrine:mapping:import "App\Entity" annotation --path=src/Entity
php bin/console make:entity --regenerate App
php bin/console make:sonata:admin App/Entity/Table1
Si nota il tipo di campo nella nostra entità
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Table1
*
* @ORM\Table(name="table1")
* @ORM\Entity
*/
class Table1
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="SEQUENCE")
* @ORM\SequenceGenerator(sequenceName="table1_id_seq", allocationSize=1, initialValue=1)
*/
private $id;
/**
* @var string|null
*
* @ORM\Column(name="var1", type="string", length=250, nullable=true)
*/
private $var1;
/**
* @var json|null
*
* @ORM\Column(name="var2", type="json", nullable=true)
*/
private $var2;
public function getId(): ?int
{
return $this->id;
}
public function getVar1(): ?string
{
return $this->var1;
}
public function setVar1(?string $var1): self
{
$this->var1 = $var1;
return $this;
}
public function getVar2(): ?array
{
return $this->var2;
}
public function setVar2(?array $var2): self
{
$this->var2 = $var2;
return $this;
}
}
E la nostra interfaccia di’admin générée nel suo formato più semplice
<?php
declare(strict_types=1);
namespace App\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;
final class Table1Admin extends AbstractAdmin
{
protected function configureDatagridFilters(DatagridMapper $datagridMapper): void
{
$datagridMapper
->add('id')
->add('var1')
->add('var2')
;
}
protected function configureListFields(ListMapper $listMapper): void
{
$listMapper
->add('id')
->add('var1')
->add('var2')
->add('_action', null, [
'actions' => [
'show' => [],
'edit' => [],
'delete' => [],
],
]);
}
protected function configureFormFields(FormMapper $formMapper): void
{
$formMapper
->add('id')
->add('var1')
->add('var2')
;
}
protected function configureShowFields(ShowMapper $showMapper): void
{
$showMapper
->add('id')
->add('var1')
->add('var2')
;
}
}
Il nostro obiettivo ora è di créper una nidificazione di modulo per gécreare i nostri dati in json.
Per questo useremo le collezioni di Symfony.
Iéi passaggi sono i seguenti, noi andiamo créper un modulo che sarà intégréal campo. Avrai un pulsante aggiungi/rimuovi per aggiungere elementiàla nostra collezione.
Collegheremo poi il nostro moduloàil nostro campo« var2 ».
Noi crécompili il nostro modulo nel rérepertorio Form di src.
<?php #src/Form/fieldvar2.php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type as FormType;
class fieldvar2 extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('var2_titre', FormType\TextType::class, [
'label' => 'Var2 titre',
])
->add('var2_valeur', FormType\TextType::class, [
'label' => 'var2 valeur',
]);
}
public function configureOptions(OptionsResolver $resolver)
{
}
}
?>
Bisogna poi collegare questo moduloàil nostro campo.
use Symfony\Component\Form\Extension\Core\Type as FormType;
use App\Form\fieldvar2;
final class Table1Admin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $formMapper): void
{
$formMapper
//->add('id') #on supprime le champs id puisqu'il est auto incrémenté
->add('var1')
->add('var2', FormType\CollectionType::class, [
'allow_add' => true,
'allow_delete' => true,
'entry_type' => 'App\\Form\\fieldvar2',
'label' => 'Var jsonb',
])
;
}
Adesso vedremo come potremmo avere un'annidamento di moduli nel nostro modulo. In sostanza degli« collezione annidata ».
E per questo sarà necessario utilizzare un componente Collection di Sonata perché c’è l'unico che funzionerà in nidificazioni multiple (in théorie, infinite).
Aggiungeremo la référenceàSonata\AdminBundle\Form\Type\CollectionType, créper un secondoèil mio modulo e il’implémentire nel nostro primo modulo.
<?php #src/Form/fieldvar2valeur.php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type as FormType;
class fieldvar2valeur extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('valeurs_multiples', FormType\TextType::class, [
'label' => 'Netsted 2 val',
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'allow_extra_fields' => true,
'allow_add' => true,
]);
}
}
?>
La nostra implementazioneéimplementazione della collezione di livello 2
<?php #src/Form/fieldvar2.php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type as FormType;
use App\Form\fieldvar2valeur;
use Sonata\AdminBundle\Form\Type\CollectionType;
class fieldvar2 extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('var2_titre', FormType\TextType::class, [
'label' => 'Var2 titre',
])
->add('var2_valeur', CollectionType::class, [
'allow_add' => true,
'allow_delete' => true,
'entry_type' => 'App\\Form\\fieldvar2valeur',
'label' => 'Data Nested 2',
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'allow_extra_fields' => true,
'allow_add' => true,
]);
}
}
?>
E non ci resta che’àmodificare la configurazione della nostra collezione per utilizzare il componente di SonataAdmin
<?php
declare(strict_types=1);
namespace App\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;
use App\Form\fieldvar2;
use Sonata\AdminBundle\Form\Type\CollectionType;
final class Table1Admin extends AbstractAdmin
{
protected function configureDatagridFilters(DatagridMapper $datagridMapper): void
{
$datagridMapper
->add('id')
->add('var1')
->add('var2')
;
}
protected function configureListFields(ListMapper $listMapper): void
{
$listMapper
->add('id')
->add('var1')
->add('var2')
->add('_action', null, [
'actions' => [
'show' => [],
'edit' => [],
'delete' => [],
],
]);
}
protected function configureFormFields(FormMapper $formMapper): void
{
$formMapper
//->add('id')
->add('var1')
->add('var2', CollectionType::class, [
'allow_add' => true,
'allow_delete' => true,
'entry_type' => 'App\\Form\\fieldvar2',
'label' => 'Var jsonb',
])
;
}
protected function configureShowFields(ShowMapper $showMapper): void
{
$showMapper
->add('id')
->add('var1')
->add('var2')
;
}
}
Il che dà questo
Adattare l’esempio alla versione installata
Gli esempi Symfony e Sonata rimangono legati alle versioni indicate nell’articolo. Symfony 4.x e Symfony 6.2 non sono più supportati: per un progetto attuale, utilizzate un ramo mantenuto e la documentazione corrispondente esattamente alle vostre dipendenze.
php bin/console about
composer show symfony/framework-bundle sonata-project/admin-bundle
Prima di riprendere il codice, controllate le firme, i servizi, le rotte e i template interessati. Aggiungete poi un test funzionale che copra le autorizzazioni, il codice HTTP e il risultato visibile.
Riferimento : versioni di Symfony supportate.