ZF2 и Doctrine 2: форма объекта перевода

Мне нужно создать форму ZF2 для переводимой сущности Doctrine (я использую https://github.com/Atlantic18/DoctrineExtensions Transurable Extension), которая должна содержать поля для всех переводимых свойств (столбцов) сущности на каждом доступном языке. Пока у меня есть следующее:

1) Статья субъекта

namespace TestModule\Entity;

use Doctrine\Common\Collections\ArrayCollection;

/**
 * @Doctrine\ORM\Mapping\Entity(repositoryClass="TestModule\Entity\ArticleRepository")
 * @Doctrine\ORM\Mapping\Table(name="test_module_articles")
 * @Gedmo\Mapping\Annotation\TranslationEntity(class="TestModule\Entity\ArticleTranslation")
 */
class Article
{
    /**
     * @var int Auto-Incremented Primary Key
     *
     * @Doctrine\ORM\Mapping\Id
     * @Doctrine\ORM\Mapping\Column(type="integer")
     * @Doctrine\ORM\Mapping\GeneratedValue
     */
    protected $id;

    /**
     * @Doctrine\ORM\Mapping\Column(type="string")
     * @Gedmo\Mapping\Annotation\Translatable
     */
    protected $name;

    /**
     * @Doctrine\ORM\Mapping\Column(type="text", length=65535)
     * @Gedmo\Mapping\Annotation\Translatable
     */
    protected $description;

    /**
     * @Gedmo\Mapping\Annotation\Locale
     * Used locale to override Translation listener`s locale
     * this is not a mapped field of entity metadata, just a simple property
     * and it is not necessary because globally locale can be set in listener
     */
    private $locale;

    /**
     * @Doctrine\ORM\Mapping\OneToMany(
     *   targetEntity="TestModule\Entity\ArticleTranslation",
     *   mappedBy="object",
     *   cascade={"persist", "remove"}
     * )
     */
    private $translations;


    public function __construct() 
    {
        $this->translations = new ArrayCollection();
    }

    public function getTranslations()
    {
        return $this->translations;
    }

    public function addTranslation(\TestModule\Entity\ArticleTranslation $t)
    {
        if (!$this->translations->contains($t)) {
            $this->translations[] = $t;
            $t->setObject($this);
        }
    }


    public function addTranslations($translations)
    {
        foreach ($translations as $translation) {
            $this->addTranslation($translation);
        }
    }

    public function removeTranslations($translations)
    {
        foreach ($translations as $translation) {
            $this->translations->removeElement($translation);
            $translation->setObject(null);
        }
    }


    public function setTranslatableLocale($locale)
    {
        $this->locale = $locale;
    }

}

2) Статья Переводчика

namespace TestModule\Entity;

use Gedmo\Translatable\Entity\MappedSuperclass\AbstractPersonalTranslation;
/**
 * @Doctrine\ORM\Mapping\Entity
 * @Doctrine\ORM\Mapping\Table(name="test_module_articles_translations",
 *     uniqueConstraints={@Doctrine\ORM\Mapping\UniqueConstraint(name="lookup_unique_idx", columns={
 *         "locale", "object_id", "field"
 *     })}
 * )
 */
class ArticleTranslation extends AbstractPersonalTranslation
{
    /**
     * Convinient constructor
     *
     * @param string $locale
     * @param string $field
     * @param string $value
     */
    public function __construct($locale, $field, $value)
    {
        $this->setLocale($locale);
        $this->setField($field);
        $this->setContent($value);
    }
    /**
     * @Doctrine\ORM\Mapping\ManyToOne(targetEntity="TestModule\Entity\Article", inversedBy="translations")
     * @Doctrine\ORM\Mapping\JoinColumn(name="object_id", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $object;
} 

3) Форма

namespace TestModule\Form;

use Zend\Form\Form;
use Doctrine\ORM\EntityManager;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
use TestModule\Form\ArticleTranslationsFieldset;
use TestModule\Entity\ArticleTranslation;

class ArticleForm extends Form
{
    protected $entityManager;

    public function __construct(EntityManager $entityManager,$name = null)
    {
        parent::__construct($name);

        $this->entityManager = $entityManager;

        $hydrator = new DoctrineHydrator($this->entityManager, 'TestModule\Entity\Article');


        $this->setAttribute('method', 'post')
            ->setHydrator($hydrator)
            //->setInputFilter($inputFilter)
        ;

        $this->add(array(
            'name'  => 'id',
            'type'  => 'Hidden',
        ));

        $articleFieldset = new ArticleTranslationsFieldset($entityManager);
        $fieldsetHydrator = new DoctrineHydrator($entityManager, 'TestModule\Entity\ArticleTranslation');
        $articleFieldset->setHydrator($fieldsetHydrator)->setObject(new ArticleTranslation('en','name',''));

        $this->add(array(
            'type' => 'Zend\Form\Element\Collection',
            'name' => 'translations',
            'allow_empty' => true,
             'options' => array(
                 'label' => '',
                 'count' => 0,
                 'allow_add' => true,
                 'allow_remove' => true,
                 'target_element' => $articleFieldset,

             ),
         ));


        $this->add(array(
            'name' => 'submit',
            'attributes' => array(
                'type' => 'submit',
                'value' => 'Submit'
            ),
        ));


    }
}

4) И набор полей переводов:

namespace TestModule\Form;

use Zend\Form\Fieldset;

class ArticleTranslationsFieldset extends Fieldset
{
    public function __construct()
    {

        parent::__construct('translations');

        $this->add(array(
            'name'  => 'locale',
            'type'  => 'Hidden',
        ));

        $this->add(array(
            'name'  => 'field',
            'type'  => 'Hidden',
        ));

        $this->add(array(
            'name' => 'content',
            'type' => 'Zend\Form\Element\Text',
            'options' => array(
                'label' => _(''),
            ),
            'attributes' => array(
                'type' => 'text',
            ),
        ));

    }

}

С помощью этой настройки я могу сохранить как имя, так и свойства описания для каждого языка, но не могу управлять типом поля содержимого - это текстовый элемент для имени и описания, и я не могу установить правильную метку поля. Я также не могу сгруппировать элементы по языку, чтобы форма, представленная пользователю, была хорошо организована.

Есть ли у вас другие предложения, как решить эту проблему?
То, что я хочу достичь, это что-то вроде этого:

1 ответ

Решение

Я не смог найти решение с помощью Расширения Переводимой Доктрины, которое я использовал в этом вопросе. Поэтому я ищу другой, и в итоге я использую расширение Prezent ( https://github.com/Prezent/doctrine-translatable).

С этим расширением сущность перевода содержит переводимые поля, что облегчает сопоставление сущности перевода с набором полей переводов. У каждого объекта перевода есть свойство локали, которое я сопоставляю со скрытым полем в наборе полей и использую его для представления формы желаемым способом.

Другие вопросы по тегам