Skip to content

Instantly share code, notes, and snippets.

@timba64
Last active August 3, 2023 16:19
Show Gist options
  • Save timba64/dc754130da9fefa7d1a38d2b5c5470b8 to your computer and use it in GitHub Desktop.
Save timba64/dc754130da9fefa7d1a38d2b5c5470b8 to your computer and use it in GitHub Desktop.
Some troubles with EasyAdmin 3 and KnpLabs/DoctrineBehaviors/translatable in Symfony 5.3
a2lix_translation_form:
locale_provider: default
locales: [ru, en]
default_locale: ru
required_locales: [ru]
templating: "@A2lixTranslationForm/bootstrap_4_layout.html.twig"
<?php
namespace App\Entity;
use App\Repository\BrandRepository;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Contract\Entity\TranslatableInterface;
use Knp\DoctrineBehaviors\Model\Translatable\TranslatableTrait;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* @ORM\Entity(repositoryClass=BrandRepository::class)
* @Vich\Uploadable
* @ORM\HasLifecycleCallbacks()
*/
class Brand implements TranslatableInterface
{
use TranslatableTrait;
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="datetime_immutable")
*/
private $createdAt;
/**
* @ORM\Column(type="datetime_immutable")
*/
private $updatedAt;
/**
* @ORM\Column(type="boolean")
*/
private $published;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $brandPhoto;
/**
* @Vich\UploadableField(mapping="brand_images", fileNameProperty="brandPhoto")
* @var File|null
*/
private $brandPhotoFile;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $brandLogo;
/**
* @Vich\UploadableField(mapping="brand_images", fileNameProperty="brandLogo")
* @var File|null
*/
private $brandLogoFile;
/**
* @ORM\Column(type="smallint")
*/
private $priority;
public function __construct()
{
$this->createdAt = new \DateTimeImmutable();
$this->updatedAt = new \DateTimeImmutable();
}
public function getId(): ?int
{
return $this->id;
}
public function getCreatedAt(): ?\DateTimeImmutable
{
return $this->createdAt;
}
public function setCreatedAt(\DateTimeImmutable $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
/**
* @ORM\PrePersist
*/
public function setCreatedAtValue()
{
$this->createdAt = new \DateTimeImmutable();
}
public function getUpdatedAt(): ?\DateTimeImmutable
{
return $this->updatedAt;
}
public function setUpdatedAt(\DateTimeImmutable $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
/**
* @ORM\PreUpdate
*/
public function setUpdatedAtValue()
{
$this->updatedAt = new \DateTimeImmutable();
}
public function getPublished(): ?bool
{
return $this->published;
}
public function setPublished(bool $published): self
{
$this->published = $published;
return $this;
}
public function getBrandPhoto(): ?string
{
return $this->brandPhoto;
}
public function setBrandPhoto(?string $brandPhoto): self
{
$this->brandPhoto = $brandPhoto;
return $this;
}
public function setBrandPhotoFile(File $brandPhoto = null)
{
$this->brandPhotoFile = $brandPhoto;
// VERY IMPORTANT:
// It is required that at least one field changes if you are using Doctrine,
// otherwise the event listeners won't be called and the file is lost
if ($brandPhoto) {
// if 'updatedAt' is not defined in your entity, use another property
$this->updatedAt = new \DateTimeImmutable('now');
}
}
public function getBrandPhotoFile()
{
return $this->brandPhotoFile;
}
public function getBrandLogo(): ?string
{
return $this->brandLogo;
}
public function setBrandLogo(?string $brandLogo): self
{
$this->brandLogo = $brandLogo;
return $this;
}
public function setBrandLogoFile(File $brandLogo = null)
{
$this->brandLogoFile = $brandLogo;
// VERY IMPORTANT:
// It is required that at least one field changes if you are using Doctrine,
// otherwise the event listeners won't be called and the file is lost
if ($brandLogo) {
// if 'updatedAt' is not defined in your entity, use another property
$this->updatedAt = new \DateTimeImmutable('now');
}
}
public function getBrandLogoFile()
{
return $this->brandLogoFile;
}
public function getPriority(): ?int
{
return $this->priority;
}
public function setPriority(int $priority): self
{
$this->priority = $priority;
return $this;
}
public function __get($method)
{
$arguments=[];
return $this->proxyCurrentLocaleTranslation($method, $arguments);
}
}
<?php
namespace App\Controller\Admin;
use App\Entity\Brand;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
use EasyCorp\Bundle\EasyAdminBundle\Field\BooleanField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use App\Admin\Field\TranslationField;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use FOS\CKEditorBundle\Form\Type\CKEditorType;
use EasyCorp\Bundle\EasyAdminBundle\Field\Field;
use EasyCorp\Bundle\EasyAdminBundle\Field\ImageField;
use Vich\UploaderBundle\Form\Type\VichImageType;
class BrandCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return Brand::class;
}
public function configureCrud(Crud $crud): Crud
{
return $crud
//->renderContentMaximized()
//->renderSidebarMinimized()
// the Symfony Security permission needed to manage the entity
// (none by default, so you can manage all instances of the entity)
->setEntityPermission('ROLE_ADMIN')
->setFormThemes(
[
//'@A2lixTranslationForm/bootstrap_4_layout.html.twig',
'admin/a2lix_bootstrap_5_layout.html.twig',
'@EasyAdmin/crud/form_theme.html.twig',
'@FOSCKEditor/Form/ckeditor_widget.html.twig',
]
);
}
public function configureFields(string $pageName): iterable
{
$fieldsConfig = [
'title' => [
'field_type' => TextType::class,
'required' => true,
'label' => 'Заголовок',
],
'description' => [
'field_type' => CKEditorType::class,
'required' => true,
'label' => 'Текст',
],
];
return [
DateTimeField::new('createdAt')->setColumns(6),
BooleanField::new('published')->setColumns(6),
Field::new('brandPhotoFile')->onlyOnForms()->setFormType(VichImageType::class)->setColumns(6),
ImageField::new('brandLogo')->onlyOnIndex()->setBasePath('/upload/brand-images/'),
Field::new('brandLogoFile')->onlyOnForms()->setFormType(VichImageType::class)->setColumns(6),
Field::new('priority'),
TranslationField::new('translations', 'Переводы', $fieldsConfig)
->setRequired(true)
->hideOnIndex(),
];
}
}
<?php
namespace App\Entity;
use App\Repository\BrandTranslationRepository;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Contract\Entity\TranslationInterface;
use Knp\DoctrineBehaviors\Model\Translatable\TranslationTrait;
use Knp\DoctrineBehaviors\Contract\Entity\SluggableInterface;
use Knp\DoctrineBehaviors\Model\Sluggable\SluggableTrait;
/**
* @ORM\Entity(repositoryClass=BrandTranslationRepository::class)
*/
class BrandTranslation implements TranslationInterface, SluggableInterface
{
use TranslationTrait;
use SluggableTrait;
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $title;
/**
* @ORM\Column(type="text")
*/
private $description;
public function getId(): ?int
{
return $this->id;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(string $description): self
{
$this->description = $description;
return $this;
}
/**
* @return string[]
*/
public function getSluggableFields(): array
{
return ['title'];
}
}
<?php
namespace App\Controller\Admin;
use App\Entity\BrandTranslation;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
class BrandTranslationCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return BrandTranslation::class;
}
/*
public function configureFields(string $pageName): iterable
{
return [
IdField::new('id'),
TextField::new('title'),
TextEditorField::new('description'),
];
}
*/
}
easy_admin:
design:
form_theme:
- '@EasyAdmin/form/bootstrap_4.html.twig'
- '@FOSCKEditor/Form/ckeditor_widget.html.twig'
- '@A2lixTranslationForm/bootstrap_4_layout.html.twig'
- '@VichUploader/Form/fields.html.twig'
entities:
# List the entity class name you want to manage
Brand:
class: App\Entity\Brand
form:
fields:
- {property: 'brandPhotoFile', type: 'VichImageType'}
- {property: 'brandLogoFile', type: 'VichImageType'}
Style:
class: App\Entity\Style
<?php
namespace App\Admin\Field;
use A2lix\TranslationFormBundle\Form\Type\TranslationsType;
use EasyCorp\Bundle\EasyAdminBundle\Contracts\Field\FieldInterface;
use EasyCorp\Bundle\EasyAdminBundle\Field\FieldTrait;
final class TranslationField implements FieldInterface
{
use FieldTrait;
public static function new(string $propertyName, ?string $label = null, $fieldsConfig = []): self
{
return (new self())
->setProperty($propertyName)
->setLabel($label)
->setFormType(TranslationsType::class)
->setFormTypeOptions(
[
'default_locale' => '%locale%',
'fields' => $fieldsConfig,
]
);
}
}
@timba64
Copy link
Author

timba64 commented Nov 4, 2021

Finally I found a solution:
If I add magic method __get() in Brand.php

    public function __get($method)
    {
        $arguments=[];
        return $this->proxyCurrentLocaleTranslation($method, $arguments);
    }

everything works great

@e1sep0
Copy link

e1sep0 commented Nov 6, 2021

public function __get($name)
    {
        $method = 'get'. ucfirst($name);
        $arguments = [];
        return $this->proxyCurrentLocaleTranslation($method, $arguments);
    }

Можно и так

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