API 平台 - 实体翻译,Doctrine Translatable
API Platform - Entity Translation, Doctrine Translatable
我正在尝试添加 KnpLabs Doctrine Behaviors - and precisely, the Translatable Behavior - 在我的 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 行为正常工作的基本"configuration"。
当我尝试更新数据库模式时出现问题:我收到此错误:
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 中,已经有一个 ID 和文档精确说明翻译实体应该只包含我们要翻译的字段...
无论如何,我已经为这个 ArtcleTranslation 实体添加了一个 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;
/**
* @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 文档:
一切看起来都很好!但是当我查看数据库时:
在文章 table 中:
- 无"local"字段
- 无"empty"字段
在 ArticleTranslation table 中:
- 无"translatable_id"字段
- 没有"currentLocal"
- 没有"defaultLocal"
我猜肯定是联动的,但是在swagger POST Tab中,型号也不一样
article_translation 型号
我只在两个实体上尝试了 /GET 和 /POST 方法,它们正在工作(我可以在数据库中看到它)但它们之间没有任何关系。
我希望我的 post 不会太长,但我尽量做到更具体!
提前致谢
我认为你做错了。您有一个实体 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){...}
}
如果现在一切正常,请告诉我。
我做了另一个答案,因为第一个问题是为了解决错误,而不是解释我如何将 Knp Labs Doctrine Translations 与 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
,当我们从 api
中获取一些 Article
时,它会自动从 ArticleTranslation
填充
2 - 现在我们要 add/edit 一些翻译:我们需要在 Article
里面填充 newTranslations
属性发送到 api:
"newTranslations": {
"en": {
"description": "Firstname"
},
"fr": {
"description": "Prénom"
}
}
现在我们正在接收 api 中的新翻译,但它没有保留,因为我们必须调用函数 mergeNewTranslations()
。此函数仅获取属性 $newTranslations
内的所有翻译并将其与 $translations
属性合并以保留它。
3 - 我创建了一个名为 TranslatableOverride
的新 trait
。我直接将它导入到 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
搭配起来很有魅力。
我没想过一次只翻译一个。目前,我用一大堆翻译来检索我的实体,这绝对是低效的。我想我会在我的覆盖 trait
中添加 getTranslations
的覆盖。
我正在尝试添加 KnpLabs Doctrine Behaviors - and precisely, the Translatable Behavior - 在我的 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 行为正常工作的基本"configuration"。
当我尝试更新数据库模式时出现问题:我收到此错误:
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 中,已经有一个 ID 和文档精确说明翻译实体应该只包含我们要翻译的字段...
无论如何,我已经为这个 ArtcleTranslation 实体添加了一个 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;
/**
* @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 文档:
一切看起来都很好!但是当我查看数据库时:
在文章 table 中:
- 无"local"字段
- 无"empty"字段
在 ArticleTranslation table 中:
- 无"translatable_id"字段
- 没有"currentLocal"
- 没有"defaultLocal"
我猜肯定是联动的,但是在swagger POST Tab中,型号也不一样
我只在两个实体上尝试了 /GET 和 /POST 方法,它们正在工作(我可以在数据库中看到它)但它们之间没有任何关系。
我希望我的 post 不会太长,但我尽量做到更具体!
提前致谢
我认为你做错了。您有一个实体 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){...}
}
如果现在一切正常,请告诉我。
我做了另一个答案,因为第一个问题是为了解决错误,而不是解释我如何将 Knp Labs Doctrine Translations 与 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
,当我们从 api
Article
时,它会自动从 ArticleTranslation
填充
2 - 现在我们要 add/edit 一些翻译:我们需要在 Article
里面填充 newTranslations
属性发送到 api:
"newTranslations": {
"en": {
"description": "Firstname"
},
"fr": {
"description": "Prénom"
}
}
现在我们正在接收 api 中的新翻译,但它没有保留,因为我们必须调用函数 mergeNewTranslations()
。此函数仅获取属性 $newTranslations
内的所有翻译并将其与 $translations
属性合并以保留它。
3 - 我创建了一个名为 TranslatableOverride
的新 trait
。我直接将它导入到 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
搭配起来很有魅力。
我没想过一次只翻译一个。目前,我用一大堆翻译来检索我的实体,这绝对是低效的。我想我会在我的覆盖 trait
中添加 getTranslations
的覆盖。