One to One relationship in SonataAdmin - symfony

i trying to make admin page for Product which has relationship 1:1 with image.
Product
/**
* #ORM\Entity
* #ORM\Table(name="products")
class Product
{
/**
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
* #ORM\Id
* #var int
*/
private $id = 0;
/**
* #ORM\OneToOne(targetEntity="Image", mappedBy="product")
*/
private $image;
/**
* #return Image
*/
public function getImage(): ?Image
{
return $this->image;
}
/**
* #param Image $image
*/
public function setImage(Image $image)
{
$this->image = $image;
return $this;
}
}
Image
/**
* #ORM\Entity
* #ORM\Table(name="images")
*/
class Image
{
/**
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
* #ORM\Id
* #var int
*/
private $id = 0;
/**
* #ORM\OneToOne(targetEntity="Product", inversedBy="image")
* #ORM\JoinColumn(name="product_id", referencedColumnName="id")
*/
private $product;
/**
* #return mixed
*/
public function getProduct()
{
return $this->product;
}
public function setProduct(Product $product)
{
$this->product = $product;
}
}
ProductAdmin
class ProductAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper->add('image', 'sonata_type_admin', array('label' => 'Okładka', 'by_reference' => false,));
}
ImageAdmin
class ImageAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('file', 'file', array('label' => 'Okładka', 'required' => false))
->add('path', 'text', array('label' => 'Scieżka do pliku', 'required' => false));
}
I setuped services correctly, but i can't edit product and after saving new one i geting error
unable to find the object with id : 0

Try to not initialize your $id
private $id = 0; // =====> this is a private $id;

You have several mistakes. Let's try to correct your code.
Just follow the tutorials and put right annotation for $id:
/**
* #var integer $id
*
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
Hope, that this is just a typo with "?Image":
/**
* #return Image
*/
public function getImage() : Image
{
return $this->image;
}
And finally.
/**
* Class ProductAdmin
*/
class ProductAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('image', 'sonata_type_model_list', [
'btn_add' => true, //Or you can specify a custom label
'btn_list' => 'list button!', //which will be translated
'btn_delete' => false, //or hide the button.
'btn_catalogue' => 'messages', //Custom translation domain for buttons
'label' => 'My image',
], [
'placeholder' => $this->trans('messages.no_images_message'),
'edit' => 'standard',
'inline' => 'standard',
'sortable' => 'id',
])
;
}
}

Related

Not exprexted behaviour on symfony datatransformer

I created a datatransformer to store dates on unixtime on the database but show it as datetime on the form
this is the transformer
class IntegerToTimestampTransformer implements DataTransformerInterface
{
public function transform($timestamp)
{
/**
* This if sentenceis because when eidt $timestamp is a timestamp(unix)
* but when create is a DateTime ¿¿???
*/
if($timestamp instanceof \DateTime){
return $timestamp;
}
return (new \DateTime())->setTimestamp($timestamp);
}
public function reverseTransform($datetime)
{
if ($datetime === null) {
return $datetime;
}
return $datetime->getTimestamp();
}
}
this is the entity
/**
* Popup
*
* #ORM\Table(name="popup")
* #ORM\Entity(repositoryClass="AppBundle\Repository\PopUpRepository")
*/
class Popup
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #Gedmo\Translatable()
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* #var string
*
* #Gedmo\Translatable()
* #ORM\Column(name="description", type="text")
*/
private $description;
/**
* #var int
*
* #ORM\Column(name="activation_date", type="integer", nullable=true)
*/
private $activationDate;
/**
* #var int
*
* #ORM\Column(name="deactivation_date", type="integer", nullable=true)
*/
private $deactivationDate;
/**
* #var boolean
*
* #ORM\Column(name="active", type="boolean")
*/
private $active;
/**
* #var Collection
*
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Role")
* #ORM\JoinTable(name="popup_role", joinColumns={#ORM\JoinColumn(name="popup_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="role_id", referencedColumnName="id")})
*/
private $roles;
public function __construct()
{
$this->roles = new ArrayCollection();
}
/**
* #return int
*/
public function getId(): int
{
return $this->id;
}
/**
* #param int $id
*/
public function setId(int $id): void
{
$this->id = $id;
}
/**
* #return string
*/
public function getTitle():? string
{
return $this->title;
}
/**
* #param string $title
*/
public function setTitle(string $title): void
{
$this->title = $title;
}
/**
* #return string
*/
public function getDescription(): ?string
{
return $this->description;
}
/**
* #param string $description
*/
public function setDescription(string $description): void
{
$this->description = $description;
}
/**
* #return int
*/
public function getActivationDate(): ?int
{
return $this->activationDate;
}
/**
* #param int $activationDate
*/
public function setActivationDate(int $activationDate): void
{
$this->activationDate = $activationDate;
}
/**
* #return int
*/
public function getDeactivationDate(): ?int
{
return $this->deactivationDate;
}
/**
* #param int $deactivationDate
*/
public function setDeactivationDate(int $deactivationDate): void
{
$this->deactivationDate = $deactivationDate;
}
/**
* #return bool
*/
public function isActive(): ?bool
{
return $this->active;
}
/**
* #param bool $active
*/
public function setActive(bool $active): void
{
$this->active = $active;
}
/**
* Add role
*
* #param Role $role
*
* #return Role
*/
public function addRole(Role $role)
{
$this->roles[] = $role;
return $this;
}
/**
* Remove role
*
* #param Role $role
*/
public function removeRole(Role $role)
{
$this->roles->removeElement($role);
}
/**
* Get role
*
* #return Collection
*/
public function getRoles()
{
return $this->roles;
}
}
and the formtype
class PopupType extends AbstractType
{
private $tranformer;
public function __construct(IntegerToTimestampTransformer $tranformer){
$this->tranformer = $tranformer;
}
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$date_array = [
'label_attr' => [
'class' => 'font-weight-bold'
],
'required' => false
];
if(!$options['edit']){
$date_array['data'] = new \DateTime();
}
$builder
->add('title', TextType::class, [
'label_attr' => [
'class' => 'font-weight-bold'
],
])
->add('description', TextareaType::class, [
'label_attr' => [
'class' => 'font-weight-bold'
],
'required' => false
])
->add('activation_date', DateTimeType::class, $date_array)
->add('deactivation_date', DateTimeType::class,$date_array)
->add('active', CheckboxType::class, [
'label_attr' => [
'class' => 'font-weight-bold'
],
'required' => false
])
->add('roles', EntityType::class, [
'class' => Role::class,
'expanded' => true,
'multiple' => true,
'required' => true,
'label_attr' => [
'class' => 'font-weight-bold'
],
])
;
$builder->get('activation_date')->addModelTransformer($this->tranformer);
$builder->get('deactivation_date')->addModelTransformer($this->tranformer);
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Popup::class,
'edit' => false
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'appbundle_popup';
}
}
I debugged and I checked that in the transform function when I try to create on the crud the parameter passed to transform is a Datetime the there is no need to transformate the data but when I try to edit the parameter passed to transform is a unixtime integer the the transformation is needed, I don't understant that behaviour.

Symfony : Get entity in radio_widget

With Symfony, I have a radio form from entity :
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('color', EntityType::class, [
'class' => Color::class,
'expanded' => true,
'label_attr' => [
'class' => 'radio-inline'
],
'label' => 'label.color',
....
But when I dump() in radio_widget, I don't have entity :
array:28 [▼
"value" => "1"
"attr" => []
"form" => FormView {#975 ▶}
"id" => "news_category_versions_0_color_1"
"name" => "1"
"full_name" => "news_category[versions][0][color]"
"disabled" => false
"label" => "Blue"
"label_format" => null
"multipart" => false
"block_prefixes" => array:4 [▶]
"unique_block_prefix" => "_news_category_versions_entry_color_entry"
"translation_domain" => false
"cache_key" => "_news_category_versions_entry_color_entry_radio"
"errors" => FormErrorIterator {#1186 ▶}
"valid" => true
"data" => false
"required" => true
"size" => null
"label_attr" => []
"compound" => false
"method" => "POST"
"action" => ""
"submitted" => false
"help_translation_domain" => null
"checked" => false
"parent_label_class" => "radio-inline"
"app" => AppVariable {#1216 ▶}
]
Can I get entity in radio_widget for customize it ? Each radio have a specific color in entity (blue, red, green, etc.).
Yes it is possible:
App\Entity\Color:
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Class Color
*
* #package AppBundle\Entity
*
* #ORM\Table()
* #ORM\HasLifecycleCallbacks()
* #ORM\Entity(repositoryClass="AppBundle\Entity\ColorRepository")
*/
class Color
{
/**
* #var int $id
* #ORM\Id()
* #ORM\Column()
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string $name
* #ORM\Column(type="string", length=255)
*/
protected $name;
/**
* #ORM\OneToMany(targetEntity="ColorProduct", mappedBy="color", cascade={"all"})
*/
protected $product;
/**
* Constructor
*/
public function __construct()
{
$this->product = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return string
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*
* #return Color
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Add product
*
* #param \AppBundle\Entity\ColorProduct $product
*
* #return Color
*/
public function addProduct(\AppBundle\Entity\ColorProduct $product)
{
$this->product[] = $product;
return $this;
}
/**
* Remove product
*
* #param \AppBundle\Entity\ColorProduct $product
*/
public function removeProduct(\AppBundle\Entity\ColorProduct $product)
{
$this->product->removeElement($product);
}
/**
* Get product
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getProduct()
{
return $this->product;
}
}
A relation with the color entity in ColorProductEntity
namespace AppBundle\Entity;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Table()
* #ORM\HasLifecycleCallbacks()
* #ORM\Entity(repositoryClass="AppBundle\Entity\ColorRepository")
*
*/
class ColorProduct
{
/**
* #var int $id
* #ORM\Id()
* #ORM\Column()
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="Color", inversedBy="product")
* #ORM\JoinColumn(name="color_id", referencedColumnName="id")
*/
protected $color;
/**
* Get id
*
* #return string
*/
public function getId()
{
return $this->id;
}
/**
* Set color
*
* #param \AppBundle\Entity\Color $color
*
* #return ColorProduct
*/
public function setColor(\AppBundle\Entity\Color $color = null)
{
$this->color = $color;
return $this;
}
/**
* Get color
*
* #return \AppBundle\Entity\Color
*/
public function getColor()
{
return $this->color;
}
}
The formType for colorProduct:
namespace AppBundle\Form;
use AppBundle\Entity\Color;
use AppBundle\Entity\ColorProduct;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ColorProductType extends AbstractType
{
public function buildForm( FormBuilderInterface $builder, array $options )
{
$builder->add('color', EntityType::class, array(
'class' => Color::class,
'choice_label' => 'name',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('c');
},
'expanded' => true,
'required' => true,
));
}
public function configureOptions( OptionsResolver $resolver )
{
$resolver->setDefaults(array(
'data_class' => ColorProduct::class
)
);
}
}
In controller:
/**
* #Route("/product/color", name="product_color")
* #param \Symfony\Component\HttpFoundation\Request $request
*
* #return \Symfony\Component\HttpFoundation\Response
*/
public function addColorProduct(Request $request) {
$colorType = new ColorProduct();
$form = $this->createForm(ColorProductType::class, $colorType);
$form->handleRequest($request);
if ($form->isSubmitted()) {
//.........
}
return $this->render('AppBundle:product:color.html.twig', array('form' => $form->createView()));
}
Twig template:
<h1>Color product</h1>
{{ form_start(form) }}
{{ form_row(form.color) }}
{{ form_end(form) }}
The result:

Symfony3 error with ManyToMany with attributes

We have an error when trying to create a relationship within 2 tables like this
Llamadas -||--|<- LlamadaDerivada ->|--||- PersonaDerivada
And we are trying to create an only one create form with the "LlamadaDerivada" into it.
Inside Llamada entity
<?php
namespace xxxxBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
class Llamada {
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="SEQUENCE")
* #ORM\SequenceGenerator(sequenceName="llamada_id_seq", allocationSize=1, initialValue=1)
*/
private $id;
/**
* #var string
* #Assert\Length(
* max = 50,
* maxMessage = "Your first name cannot be longer than {{ limit }} characters",
* )
* #ORM\Column(name="nombre", type="string", length=150, nullable=false)
*/
private $nombre;
/**
*
* #ORM\OneToMany(targetEntity="LlamadaDerivado", mappedBy="llamada")
*/
private $derivados;
function __construct() {
$this->derivados = new ArrayCollection();
}
function getId() {
return $this->id;
}
function getNombre() {
return $this->nombre;
}
function setId($id) {
$this->id = $id;
}
function setNombre($nombre) {
$this->nombre = $nombre;
}
function getDerivados(){
return $this->derivados;
}
function setDerivados($derivados){
$this->derivados = $derivados;
}
}
Then inside LlamadaDerivado Entity we have this
<?php
namespace xxxBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* LlamadaDerivado
*
* #ORM\Table(name="llamada_derivado")
* #ORM\Entity
*/
class LlamadaDerivado
{
/**
* #var \AgendaBundle\Entity\Llamada
*
* #ORM\ManyToOne(targetEntity="AgendaBundle\Entity\Llamada",inversedBy="derivados",cascade={"persist"})
* #ORM\Id
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="id_llamada", referencedColumnName="id")
* })
*/
private $llamada;
/**
* #var \AgendaBundle\Entity\PersonaDerivado
*
* #ORM\ManyToOne(targetEntity="AgendaBundle\Entity\PersonaDerivado",inversedBy="llamadas",cascade={"persist"})
* #ORM\Id
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="id_derivado", referencedColumnName="id")
* })
*/
private $derivado;
/**
* #var DateTime
*
* #ORM\Column(name="fecha_derivacion", type="date", nullable=false)
*/
private $fechaDerivacion;
function getLlamada(){
return $this->llamada;
}
function getDerivado(){
return $this->derivado;
}
function getFechaDerivacion() {
return $this->fechaDerivacion;
}
function setLlamada( $llamada) {
$this->llamada = $llamada;
}
function setDerivado( $derivado) {
$this->derivado = $derivado;
}
function setFechaDerivacion($fechaDerivacion) {
$this->fechaDerivacion = $fechaDerivacion;
}
}
And inside PersonaDerivado entity
<?php
namespace xxxBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* ReunionLugar
*
* #ORM\Table(name="persona_derivado")
* #ORM\Entity
*/
class PersonaDerivado
{
public function __construct() {
$this->llamadas = new ArrayCollection();
}
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="SEQUENCE")
* #ORM\SequenceGenerator(sequenceName="reunion_lugar_id_seq", allocationSize=1, initialValue=1)
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="nombre", type="string", length=150, nullable=false)
*/
private $nombre;
/**
* #ORM\OneToMany(targetEntity="LlamadaDerivado", mappedBy="derivado")
*/
private $llamadas;
function getId() {
return $this->id;
}
function getNombre() {
return $this->nombre;
}
function setId($id) {
$this->id = $id;
}
function setNombre($nombre) {
$this->nombre = $nombre;
}
function setLlamadas($llamadas) {
$this->llamadas = $llamadas;
}
}
And the LlamadaType is
class LlamadaDto extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$disabled = $options['disabled'];
$builder
->add('id', HiddenType::class)
->add('nombre', TextType::class, array(
'disabled' => $disabled,
'attr' => ['maxlength'=>'50']
))->add('apellido', TextType::class, array(
'disabled' => $disabled,
'attr' => ['maxlength'=>'50']
))->add('fecha', DateType::class, array(
'format' => 'dd/MM/yyyy',
'disabled' => $disabled,
'widget' => 'single_text',
'attr' => ['class' => 'datepicker']
))->add('hora', TimeType::class, array(
'disabled' => $disabled
))->add('motivo', TextareaType::class, array(
'disabled' => $disabled,
'attr' => ['maxlength'=>'400']
))->add('telefonoContacto', TextType::class, array(
'disabled' => $disabled,
'attr' => ['maxlength'=>'9']
))->add('derivados', EntityType::class, array(
'class' => 'AgendaBundle:PersonaDerivado',
'choice_label' => 'apellidoNombre',
'placeholder' => 'Seleccionar un derivado',
'multiple' => true,
));
}
public function configureOptions(OptionsResolver$resolver) {
$resolver->setDefaults(array('data_class' => Llamada::class));
}
}
Inside the controller we have this code
<?php
/**
* #Route("/Llamada/save",name="saveLlamada")
*/
public function saveLlamadaAction(Request $request) {
$llamadaService = $this->get('llamadaService');
$derivadoService = $this->get('derivadoService');
$form = $this->createForm(LlamadaDto::class);
$form->handleRequest($request);
$editar = TRUE;
$llamada = $form->getData();
$derivados = $request->request->get("llamada_dto")["derivados"];
$derivadosActuales = $derivadoService->getLlamadaDerivados($llamada->getId());
foreach ($derivados as $key1 => $d) {
foreach ($derivadosActuales as $key2 => $da) {
if($da->getDerivado()->getId()==$d){
array_splice($derivados, array_search($d, $derivados),1);
}
}
}
if ($llamadaService->saveLlamada($llamada)) {
$this->addFlash(
'exitoLlamada', 'Datos de llamada guardados exitosamente'
);
$derivadoService->saveDerivados($derivados,$llamada);
} else {
$this->addFlash(
'errorLlamada', 'Disculpe, hubo un error en el registro de la llamada'
);
}
return new RedirectResponse($this->generateUrl('listaLlamadas', array(), UrlGeneratorInterface::RELATIVE_PATH));
}
And the services called are this ones:
public function saveLlamada($llamada ){
try{
if($llamada->getId()){
$this->em->merge($llamada);
}else{
$this->em->persist($llamada);
}
$this->em->flush();
return TRUE;
} catch (Exception $ex){
return FALSE;
}
}
public function saveDerivados($derivados,$llamada){
foreach ($derivados as $key => $derivado) {
$llamadaDerivado = new LlamadaDerivado();
$personaLlamada = $this->getDerivado($derivado);
$llamadaDerivado->setLlamada($llamada);
$llamadaDerivado->setDerivado($personaLlamada);
$llamadaDerivado->setFechaDerivacion(new \DateTime('now', (new \DateTimeZone('America/Argentina/Ushuaia'))));
$this->em->persist($llamadaDerivado);
$this->em->flush();
}
}
This is the error that we are getting:
Uncaught PHP Exception Doctrine\ORM\ORMInvalidArgumentException: "Expected value of type "Doctrine\Common\Collections\Collection|array" for association field "xxxBundle\Entity\Llamada#$derivados", got "xxxBundle\Entity\PersonaDerivado" instead." at project\vendor\doctrine\orm\lib\Doctrine\ORM\ORMInvalidArgumentException.php line 206
We've been 1 week with this.
Many thanks in advance
You can try to use a CollectionType instead of EntityType in your formtype, although I have a piece of code in front of me that works just fine with EntityType and the multiple flag for a OneToMany relationship.
look at Llamada entity, $derivados is an array collection of LlamadaDerivado and in your LlamadaType you make it entityType of AgendaBundle:PersonaDerivado, that is why you got this error. Think to use Collection Type to add everytime all the object LlamadaDerivado to well respect the mapping.

How can I add thumbnail of an image in sonata admin listmapper

I don´t know how to preview a small image in my listmapper in admin class of an entity. I only see a link to the edit form of the picture, but I want to see a thumbnail of the picture.
This is my entity:
<?php
namespace ExampleBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Gedmo\Translatable\Translatable;
use Application\Sonata\MediaBundle\Entity\Media;
/**
* example
*
* #ORM\Table()
* #ORM\Entity
*/
class example
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
* #var \Application\Sonata\MediaBundle\Entity\Media
* #ORM\ManyToOne(targetEntity="Application\Sonata\MediaBundle\Entity\Media", cascade={"persist"}, fetch="LAZY")
*/
private $imagenEs;
/**
* #var string
* #var \Application\Sonata\MediaBundle\Entity\Media
* #ORM\ManyToOne(targetEntity="Application\Sonata\MediaBundle\Entity\Media", cascade={"persist"}, fetch="LAZY")
*/
private $imagenEn;
/**
* #var string
* #Gedmo\Translatable
* #ORM\Column(name="titulo", type="string", length=255)
*/
private $titulo;
/**
* #var string
*/
private $tituloEn;
/**
* #var string
* #Gedmo\Translatable
* #ORM\Column(name="texto", type="text")
*/
private $texto;
/**
* #var string
*/
private $textoEn;
/**
* #var boolean
*
* #ORM\Column(name="activo", type="boolean")
*/
private $activo;
/**
* #var integer
*
* #ORM\Column(name="ranking", type="integer")
*/
private $ranking;
/**
* #var string
* #Gedmo\Locale
*/
private $locale;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set imagen
*
* #param string $imagen
* #return BannerHome
*/
public function setImagenEs(Media $imagenEs)
{
$this->imagenEs = $imagenEs;
return $this;
}
/**
* Get imagen
*
* #return string
*/
public function getImagenEs()
{
return $this->imagenEs;
}
/**
* Set imagen
*
* #param string $imagen
* #return BannerHome
*/
public function setImagenEn(Media $imagenEn)
{
$this->imagenEn = $imagenEn;
return $this;
}
/**
* Get imagen
*
* #return string
*/
public function getImagenEn()
{
return $this->imagenEn;
}
/**
* Set titulo
*
* #param string $titulo
* #return BannerHome
*/
public function setTitulo($titulo)
{
$this->titulo = $titulo;
return $this;
}
/**
* Get titulo
*
* #return string
*/
public function getTitulo()
{
return $this->titulo;
}
/**
* Set titulo
*
* #param string $titulo
* #return BannerHome
*/
public function setTituloEn($tituloEn)
{
$this->tituloEn = $tituloEn;
return $this;
}
/**
* Get titulo
*
* #return string
*/
public function getTituloEn()
{
return $this->tituloEn;
}
/**
* Set texto
*
* #param string $texto
* #return BannerHome
*/
public function setTexto($texto)
{
$this->texto = $texto;
return $this;
}
/**
* Get texto
*
* #return string
*/
public function getTexto()
{
return $this->texto;
}
/**
* Set texto
*
* #param string $texto
* #return BannerHome
*/
public function setTextoEn($textoEn)
{
$this->textoEn = $textoEn;
return $this;
}
/**
* Get texto
*
* #return string
*/
public function getTextoEn()
{
return $this->textoEn;
}
/**
* Set activoBoolean
*
* #param string $activoBoolean
* #return BannerHome
*/
public function setActivo($activo)
{
$this->activo = $activo;
return $this;
}
/**
* Get activoBoolean
*
* #return string
*/
public function getActivo()
{
return $this->activo;
}
/**
* Set ranking
*
* #param integer $ranking
* #return BannerHome
*/
public function setRanking($ranking)
{
$this->ranking = $ranking;
return $this;
}
/**
* Get ranking
*
* #return integer
*/
public function getRanking()
{
return $this->ranking;
}
public function setTranslatableLocale($locale) {
$this->locale = $locale;
}
}?>
And this is my admin class
<?php
namespace ExampleBundle\Admin;
use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;
class PibeAdmin extends Admin
{
/**
* #param DatagridMapper $datagridMapper
*/
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('id')
->add('titulo')
->add('texto')
->add('activo')
->add('ranking')
;
}
/**
* #param ListMapper $listMapper
*/
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->add('id')
->add('titulo')
->add('imagenEs') /*With this I see a link to the image, and if I click this link I saw the edit form of the image, but I want a thumbnail*/
->add('activo')
->add('ranking')
->add('_action', 'actions', array(
'actions' => array(
'show' => array(),
'edit' => array(),
'delete' => array(),
)
))
;
}
/**
* #param FormMapper $formMapper
*/
protected function configureFormFields(FormMapper $formMapper)
{
$idioma=$this->getRequest()->getLocale();
if($idioma=='es'){
$formMapper
->add('imagenEs', 'sonata_type_model_list', array(
'required' => false,
'label'=>'Imagen Español'
), array(
'link_parameters' => array(
'context' => 'default',
'provider' => 'sonata.media.provider.image'
)
)
)
->add('imagenEn', 'sonata_type_model_list', array(
'required' => false,
'label'=>'Imagen Ingles',
), array(
'link_parameters' => array(
'context' => 'default',
'provider' => 'sonata.media.provider.image'
)
)
)
->add('titulo',null,array('label'=>'Titulo Español'))
->add('tituloEn','text',array('label'=>'Titulo Ingles','data'=>''))
->add('texto','textarea', array('attr' => array('class' => 'ckeditor'),'label'=>'Texto Español'))
->add('textoEn','textarea', array('attr' => array('class' => 'ckeditor'),'label'=>'Texto Ingles','data'=>''))
;
}else{
$formMapper
->add('imagenEn', 'sonata_type_model_list', array(
'required' => false,
'label'=>'Imagen Ingles'
), array(
'link_parameters' => array(
'context' => 'default',
'provider' => 'sonata.media.provider.image'
)
)
)
->add('imagenEs', 'sonata_type_model_list', array(
'required' => false,
'label'=>'Imagen Español'
), array(
'link_parameters' => array(
'context' => 'default',
'provider' => 'sonata.media.provider.image'
)
)
)
->add('tituloEn','text',array('label'=>'Titulo Ingles','data'=>''))
->add('titulo',null,array('label'=>'Titulo Español'))
->add('textoEn','textarea', array('attr' => array('class' => 'ckeditor'),'label'=>'Texto Ingles','data'=>''))
->add('texto','textarea', array('attr' => array('class' => 'ckeditor'),'label'=>'Texto Español'))
;
}
$formMapper
->add('activo')
->add('ranking')
;
$container = $this->getConfigurationPool()->getContainer();
$em = $container->get('doctrine.orm.entity_manager');
if($idioma=='es' && $this->getSubject()->getId()!=null){
//$titoriginal=$em->getRepository('HomeBundle:ImagenesHome')->find($this->getSubject()->getId());
// $titoriginal->setTranslatableLocale('en');
//$em->refresh($titoriginal);
//buscamos su traduccion en la tabal de traducciones.
$repository = $em->getRepository('Gedmo\Translatable\Entity\Translation');
$translations = $repository->findTranslations($this->getSubject());
//rellenamos el campo con la traduccion.
if(count($translations)>0){
$formMapper->get('tituloEn')->setData($translations['en']['titulo']);
$formMapper->get('textoEn')->setData($translations['en']['texto']);
};
}else if($idioma=='en' && $this->getSubject()->getId()!=null){
$titoriginal=$em->getRepository('PibeBundle:Pibe')->find($this->getSubject()->getId());
//cambiamos el locale a 'es' para coger el texto en español
$titoriginal->setTranslatableLocale('en');
$em->refresh($titoriginal);
//una vez que lo cogemos, volvemos a cambiar el locale a 'en'
$formMapper->get('tituloEn')->setData($titoriginal->getTitulo());
$formMapper->get('textoEn')->setData($titoriginal->getTexto());
$titoriginal->setTranslatableLocale('es');
$em->refresh($titoriginal);
}
}
/**
* #param ShowMapper $showMapper
*/
protected function configureShowFields(ShowMapper $showMapper)
{
$showMapper
->add('id')
->add('titulo')
->add('texto')
->add('activo')
->add('ranking')
;
}
public function prePersist($object) {
$container = $this->getConfigurationPool()->getContainer();
$entityManager = $container->get('doctrine.orm.entity_manager');
//insertar en español.
$object->setTitulo($object->getTitulo());
$object->setTexto($object->getTexto());
$object->setTranslatableLocale('es');
$entityManager->persist($object);
$entityManager->flush();
//insertar en ingles.
$object->setTitulo($object->getTituloEn());
$object->setTexto($object->getTextoEn());
$object->setTranslatableLocale('en');
$entityManager->persist($object);
$entityManager->flush();
}
public function preUpdate($object) {
$container = $this->getConfigurationPool()->getContainer();
$entityManager = $container->get('doctrine.orm.entity_manager');
//insertar en español.
$object->setTitulo($object->getTitulo());
$object->setTexto($object->getTexto());
$object->setTranslatableLocale('es');
$entityManager->persist($object);
$entityManager->flush();
//insertar en ingles.
$object->setTitulo($object->getTituloEn());
$object->setTexto($object->getTextoEn());
$object->setTranslatableLocale('en');
$entityManager->persist($object);
$entityManager->flush();
}
}
Where it says "Imagen Es" I want the thumbnail of the image.
$listMapper
->add('thumb', null, array(
'template' => "ExampleBundle:Pibe:list_thumb.html.twig")
)
On list_thumb.html.twig
{% extends 'SonataAdminBundle:CRUD:base_list_field.html.twig' %}
{% block field %}
{# {{ dump() }} you can dump all variables here #}
{# {{ value }} will return the value of getImagenEs() #}
<img class="img-responsive" alt="{{ object.name }}" src="{{ asset('path/to/uploadfolder/' ~ object.filepath) }}" /> {# or you can use a twig filter with your own logic #}
{% endblock field %}
I believe this is a more up 2 date answer :
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('title')
->add('image', 'string', ['template' => 'SonataMediaBundle:MediaAdmin:list_image.html.twig'])
->add('updatedAt')
->add('_action', null, ['actions' =>
[
'edit' => [],
'delete' => []
], 'label' => 'Actions']);
}

sonata: Dealing with sonata_type_model (one-to-many)

1- I have an Entity:
EmployeeMedicalService
/**
* #ORM\Entity
* #ORM\Table(name="employee_medical_file")
*/
class EmployeeMedicalService extends BaseEntity
{
//
// Some
// Fields
//
/**
* #Assert\NotBlank
* #ORM\ManyToOne(targetEntity="PersonnelBundle\Entity\Lookup\Lookup")
* #ORM\JoinColumn(name="medical_service_id", referencedColumnName="id")
*/
private $medicalService;
//
// getters
// & setters
//
2- Another Entity:
Lookup
/**
* #ORM\Entity
* #ORM\Table(name="lookup")
* #UniqueEntity(fields="name")
*/
class Lookup extends BaseEntity
{
// const ...
const TYPE_MEDICAL_SERVICE = 'medical_service';
// more constants ...
public function __construct($type)
{
$this->type = $type;
}
//
// Some Fields
//
/**
* #var string
* --stuff--
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="type", type="string", length=50)
* #Assert\NotBlank
*/
private $type;
//getters
// &setters
Now in the
EmployeeMedicalServiceAdmin
protected function configureFormFields(\Sonata\AdminBundle\Form\FormMapper $formMapper)
{
$msquery = $this->getModelManager()
->getEntityManager('PersonnelBundle:Lookup\Lookup')
->createQueryBuilder();
$msquery->select('l')->from('PersonnelBundle:Lookup\Lookup', 'l')->where('l.type = :type')
->orderBy('l.name', 'ASC')
->setParameter('type', 'medical_service');
$formMapper
->add(..)
->add('medicalService', 'sonata_type_model', array(
'label' => 'personnel.employee.medical_service.form.medical_service',
'property' => 'name',
'placeholder' => '',
'required' => false,
'query' => $msquery,
))
->add(..)
;
}
** My Problem: **
I need the form for add new lookup(medical service) from inside the EmployeeMedicalService Admin Form to be preloaded with the field Type value set to 'medical_service' When I attempt to add a new Medical Service from inside the EmployeeMedicalService Admin Form or else a new lookup is added without the value if Type set to NULL
This is the
LookupAdmin
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('name', 'text', array(
'label' => 'personnel.lookup.form.name'
))
->add('type', 'hidden', array(
'label' => 'personnel.lookup.form.type',
))
;
}
If you inspect ajax request for the popup form you will notice extra query parameters, such as pcode. You could check if this parameter exists and equals EmployeeMedicalServiceAdmin admin class code then set lookup type to medical_service.
UPDATE
Add this king of logic in the getNewInstance() method:
public function getNewInstance()
{
$type = isset($_GET['pcode']) ? 'medical_service' : '';
$instance = new \PersonnelBundle\Entity\Employee\EmployeeMedicalService($type);
return $object;
}

Resources