Я пытаюсь добавить Поведение доктрины KnpLabs - а точнее, Переводимое поведение - на одну из сущностей в моем проекте платформы API.
Вот что я сделал до сих пор:
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
use ApiPlatform\Core\Annotation\ApiResource;
/**
* @ORM\Entity(repositoryClass = "App\Repository\ArticleRepository")
* @ApiResource
*/
class Article
{
use ORMBehaviors\Translatable\Translation,
ORMBehaviors\Timestampable\Timestampable
;
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type = "integer")
*/
protected $id;
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
}
А вот перевод сущности:
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
use ApiPlatform\Core\Annotation\ApiResource;
use App\Traits as CustomTraits;
/**
* @ORM\Entity(repositoryClass = "App\Repository\ArticleTranslationRepository")
* @ApiResource
*/
class ArticleTranslation
{
use ORMBehaviors\Translatable\Translatable;
/**
* @var string
*
* @ORM\Column(name = "someFieldToTranslate", type = "string", length=255, nullable=true)
*/
private $someFieldToTranslate;
public function getSomeFieldToTranslate(){...}
public function setSomeFieldToTranslate($someFieldToTranslate){...}
}
Вот базовая «конфигурация» для работы Translatable Behavior в соответствии с документом.
Проблемы начинаются, когда я пытаюсь обновить схему БД: я получил эту ошибку:
No identifier/primary key specified for Entity "App\Entity\ArticleTranslation". Every Entity must have an identifier/primary key in . (which is being imported from "/Sites/bookshop-api/config/routes/api_platform.yaml"). Make sure there is a
loader supporting the "api_platform" type.
Однако в Translatable Traits уже есть идентификатор и документация, в которой указано, что объект перевода должен иметь только поля, которые мы хотим перевести ...
В любом случае, я присвоил этому объекту ArtcleTranslation идентификатор, чтобы избавиться от ошибки:
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
use ApiPlatform\Core\Annotation\ApiResource;
use App\Traits as CustomTraits;
/**
* @ORM\Entity(repositoryClass = "App\Repository\ArticleTranslationRepository")
* @ApiResource
*/
class ArticleTranslation
{
use ORMBehaviors\Translatable\Translatable;
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type = "integer")
*/
protected $id;
/**
* @var string
*
* @ORM\Column(name = "content", type = "string", length=255, nullable=true)
*/
private $content;
public function getContent(){...}
public function setContent($someContent){...}
}
Отсюда никаких ошибок при обновлении схемы БД. Идеально ! Теперь я могу взглянуть на документацию Swagger:
Все выглядит нормально! Но когда я взгляну на БД:
В таблице статей:
В таблице перевода статьи:
Я думаю, это должно быть связано, но на вкладке POST swagger модель тоже другая.
Я пробовал только методы / GET и / POST для обоих объектов, они работают (я вижу это в БД), но между ними нет связи.
Надеюсь, мой пост не слишком длинный, но я постарался быть более конкретным!
заранее спасибо
@Tahir все еще не нашел решения ..
В моем случае подписчик не был зарегистрирован в списке пакетов. Нам необходимо зарегистрировать пакет подписчиков, как указано в документация. После исправления я получил все столбцы в db. Хотя я застрял в том, как я могу отправлять / получать переводы с использованием конечных точек по умолчанию.





Я думаю, ты ошибся. У вас есть объект Article, который должен быть translatable, и вы хотите перевести некоторые поля, которые будут translations?
Таким образом, вы должны сделать наоборот: поставить use ORMBehaviors\Translatable\Translatable на Article и use ORMBehaviors\Translatable\Translation на ArticleTranslation.
Исправление для вашей сущности Article:
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
use ApiPlatform\Core\Annotation\ApiResource;
/**
* @ORM\Entity(repositoryClass = "App\Repository\ArticleRepository")
* @ApiResource
*/
class Article
{
use ORMBehaviors\Translatable\Translatable,
ORMBehaviors\Timestampable\Timestampable
;
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type = "integer")
*/
protected $id;
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
}
и исправление для вашего объекта ArticleTranslation:
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
use ApiPlatform\Core\Annotation\ApiResource;
use App\Traits as CustomTraits;
/**
* @ORM\Entity(repositoryClass = "App\Repository\ArticleTranslationRepository")
* @ApiResource
*/
class ArticleTranslation
{
use ORMBehaviors\Translatable\Translation;
/**
* @var string
*
* @ORM\Column(name = "someFieldToTranslate", type = "string", length=255, nullable=true)
*/
private $someFieldToTranslate;
public function getSomeFieldToTranslate(){...}
public function setSomeFieldToTranslate($someFieldToTranslate){...}
}
Дай мне знать, если сейчас все в порядке.
Спасибо за ответ! Я сейчас в другом проекте, но я посмотрю как можно скорее! Кстати, вы могли использовать knplabsBehaviour с платформой Api?
Да, это работает. У меня просто беда на POST и PUT. Я думаю, что поле newTranslations не обрабатывается API-платформой. Но я найду решение / трюк.
Вы нашли решение с помощью POST / PUT? Есть ли другой способ интегрировать перевод сущностей в ApiPlatform? Я ищу решение, в котором объект (например, статья) в GET предоставит либо контент с возможностью выбора перевода с помощью ключа локали, либо путем передачи языкового стандарта и в ответ получит контент на языке, указанном локалью. Не нашел пока лучшего решения :(
Я дал новый полный ответ.
Я ответил еще раз, поскольку первый вопрос заключался в устранении ошибки, а не в объяснении того, как я интегрировал переводы доктрины Knp Labs с платформой Api.
Резюме :
У нас есть объект Article, некоторые поля которого переведены внутри ArticleTranslation. Мы хотим получить объект через Api platform с его переводами, и мы хотим добавить или обновить переводы через api.
Что я сделал :
Объект 1 -Article имеет use ORMBehaviors\Translatable\Translatable. Если мы заглянем внутрь этого trait, у него есть 2 атрибута: $translations и $newTranslations. Нам нужно раскрыть эти атрибуты внутри объекта Article:
class Article {
use ORMBehaviors\Translatable\Translatable;
protected $translations;
protected $newTranslations;
}
Теперь у нас есть новый атрибут translations, который автоматически заполняется из ArticleTranslation, когда мы получаем немного Article из api.
2 - Теперь мы хотим добавить / отредактировать некоторые переводы: нам нужно заполнить атрибут newTranslations внутри Article, когда мы отправляем в api:
"newTranslations": {
"en": {
"description": "Firstname"
},
"fr": {
"description": "Prénom"
}
}
Теперь мы получаем новые переводы в api, но они не сохраняются, потому что мы должны вызвать функцию mergeNewTranslations(). Эта функция просто берет все переводы внутри атрибута $newTranslations и объединяет их с атрибутом $translations, чтобы сохранить его.
3 - Я создал новый trait, который назвал TranslatableOverride. Я импортировал его прямо на свой объект рядом с ORMBehaviors\Translatable\Translation:
trait TranslatableOverride
{
/**
* Set collection of new translations.
*
* @return ArrayCollection
*/
public function setNewTranslations($newTranslations)
{
if ($newTranslations) {
foreach ($newTranslations as $locale => $translations) {
foreach ($translations as $key => $value) {
$tr = $this->translate($locale);
$setter = 'set' . ucfirst($key);
if (method_exists($tr, $setter)) {
$tr->{$setter}($value);
}
}
}
$this->mergeNewTranslations();
}
}
}
Не уверен, что это красиво, но с api-platform работает как шарм.
Я не думал о том, чтобы получать только один перевод за раз. На данный момент я извлекаю свои объекты с целой кучей переводов, что определенно неэффективно. Думаю, я добавлю переопределение для getTranslations в свой переопределение trait.
Спасибо @ Maël за то, что нашли время ответить на этот пост, я попробую ваше решение, когда смогу!
Вы смогли найти решение? Я столкнулся с той же проблемой. Спасибо за любую помощь