Vamos a crear una interfaz de administración 1N, con dos entidades. La primera, Uno, y la segunda, Muchos, y configurar un panel de administración para la tabla Uno, que puede afectar a varios elementos de la tabla Muchos. Para darle más interés, añadiremos algunos parámetros adicionales, como campos de marca de tiempo para fechas de sincronización con un SI, y campos primarios que no se llaman ID y no se autoincrementan.
En nuestro caso, tenemos una sincronización con un SI que requiere un campo de marca de tiempo.
Solo crea un campo de tipo datetime
Agrega la anotación de opción {'default': 'CURRENT_TIMESTAMP'}
La siguiente anotación creará un campo Timestamps con el valor predeterminado establecido en CURRENT_TIMESTAMP.
* @ORM\Column(type="datetime", nullable=false, options={"default": "CURRENT_TIMESTAMP"})
* @ORM\Version
Para nombrar la tabla correctamente y crear índices, simplemente añade la siguiente anotación en la cabeza de la clase
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\Table;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Index;
/**
* @ORM\Entity(repositoryClass="App\Repository\WcoconRepository")
* @Table(name="table_name",indexes={@Index(name="PRIMARY", columns={"champs1", "champs2"})})
*/
Para usar un campo diferente al predeterminado 'id', simplemente añade la siguiente anotación:
/**
* @ORM\Column(type="integer")
* @ORM\Id()
*/
private $numero_dossier;
Una vez realizada la relación, es necesario especificar el id que se utilizará en el mapeo. De lo contrario, habrá un error como:
Nombre de columna id
referenciado para relación de App\Entity\Many hacia App\Entity\Uno no existe.
Así que en la entidad 'Muchos', necesitas añadir la relación con el id de la entidad 'Uno'
/**
* @ORM\ManyToOne(targetEntity="App\Entity\One", inversedBy="Ones")
* @ORM\JoinColumn(nullable=false, name="many_id", referencedColumnName="one_id")
*/
private $many_id;
Último punto importante; Para evitar que el objeto tenga un nombre como 'App\Entity\Uno:sdfsdfgsdgmlkpoufsdlkjfsdg' durante la edición, es mejor sobrescribir el método __toString(), para mostrar el nombre del objeto.
En la entidad, simplemente incluye un método:
public function __toString()
{
return "Nom object ".$this->getName();
}
Una vez hecho esto, solo procede con la migración:
php bin/console make:migration
php bin/console doctrine:migrations:migrate
Si es necesario, para regenerar el repositorio a partir de las entidades disponibles simplemente lanza el siguiente comando:
php bin/console make:entity --regenerate
Las entidades no serán modificadas.
Para probar las relaciones entre entidades, puedes ejecutar el siguiente comando:
php bin/console doctrine:schema:validate
En esta etapa, todo lo que nos queda por hacer es configurar las interfaces de gestión en el admin, y podemos comenzar a desarrollar la autenticación de front-end.
El primer paso de la interfaz de administración es crear la clase en src/Admin/TableAdmin.php
namespace App\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Sonata\AdminBundle\Form\Type\ModelAutocompleteType;
use Sonata\AdminBundle\Form\Type\ModelType;
use Sonata\AdminBundle\Form\Type\ModelListType;
use Sonata\Form\Type\CollectionType;
class OneAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper->tab('General');
$formMapper->with('Parametres', ['class' => 'col-md-4']);
$formMapper->add('name', TextType::class, ['required' => false, 'label'=>'Site internet','attr' => ['placeholder' => '']]);
$formMapper->end()
$formMapper->with('Parametres', ['class' => 'col-md-8']);
$formMapper->add('nomduchampsArrayCollection', EntityType::class, [
'class' => 'App\Entity\Many',
'choice_label' => 'nom_du_champs_autre_table',
'label' => 'champs liste',
'multiple' => true,
//'expanded' => true,
]);
$formMapper->end()
$formMapper->end('General');
}
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper->add('name');
}
protected function configureListFields(ListMapper $listMapper)
{
$listMapper->addIdentifier('name', null, ['label' => 'Nom']);
}
public function prePersist($object)
{
$this->preUpdate($object);
}
public function preUpdate($object)
{
$mapping=$object->getManys()->getMapping();
$currentManys=$this->createQuery()->getQueryBuilder()->getQuery()->getEntityManager()->getRepository($mapping["targetEntity"])
->findBy([$mapping["mappedBy"]=>$this->id($object)]);
$object->setMany($object->getManys(),$currentManys);
}
public function setMany($collections,$currentManys)
{
foreach ($currentCollections as $w)
{
if(!$collections->contains($w)){
$w->setCollectionID(null);
}
}
$this->collections= new ArrayCollection();
foreach ($collections as $collection) {
$this->addCollections($collections);
}
}
}
En la entidad One.php, necesitamos añadir nuestro nuevo método para manejar modificaciones
public function setMany($manys,$current)
{
foreach ($current as $w) {
if(!$manys->contains($w)){
$w->setManyField(null);
}
}
$this->manys = new ArrayCollection();
foreach ($manys as $m) {
$this->addMany($m);
}
}
Luego registrar el servicio en config/services.yaml
admin.MaTable:
class: App\Admin\MaTableAdmin
arguments: [~, App\Entity\MaTable, ~]
tags:
- { name: sonata.admin, manager_type: orm, label: "Table MaTable" }
public: true