【问题标题】:API Platform - Entity Translation, Doctrine TranslatableAPI 平台 - 实体翻译,Doctrine Translatable
【发布时间】:2018-03-12 15:17:33
【问题描述】:

我正在尝试在我的 API 平台项目中的一个实体上添加 KnpLabs Doctrine Behaviors - 准确地说是 Translatable Behavior

这是我到目前为止所做的:

    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){...}
     }

这是根据文档使可翻译行为工作的基本“配置”。

当我尝试更新数据库架构时出现问题:我收到此错误:

没有为实体“App\Entity\ArticleTranslation”指定标识符/主键。每个实体都必须有一个标识符/主键。 (从“/Sites/bookshop-api/config/routes/api_platform.yaml”导入)。确保有一个
支持“api_platform”类型的加载器。

然而,在 Translatable Traits 中,已经有一个 ID 和文档明确指出 Translation Entity 应该只包含我们想要翻译的字段...

无论如何,我已经为这个 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 文档:

一切看起来都很好!但是当我查看数据库时:

在文章表中:

  • 没有“本地”字段
  • 没有“空”字段

在文章翻译表中:

  • 没有“translatable_id”字段
  • 没有“currentLocal”
  • 没有“defaultLocal”

我猜它必须是链接的,但在招摇的 POST 选项卡中,模型也不同。

article_translation 模型

我只在这两个实体上尝试了 /GET 和 /POST 方法,它们都在工作(我可以在 DB 中看到它),但它们之间没有任何关系。

我希望我的帖子不会太长,但我尽量说得更具体!

提前致谢

【问题讨论】:

  • 您找到解决方案了吗?我面临同样的问题。感谢您的帮助
  • @Tahir 仍未找到解决方案..
  • 就我而言,订阅者未在捆绑列表中注册。我们需要按照documentation 中的说明注册订阅者捆绑包。修复此问题后,我得到了 db.xml 中的所有列。虽然我坚持如何使用默认端点发送/获取翻译。

标签: doctrine-extensions api-platform.com


【解决方案1】:

我做了另一个答案,因为第一个问题是解决一个错误,而不是解释我如何将 Knp Labs Doctrine Translations 与 Api Platform 集成。

总结:

我们有一个实体Article,它在ArticleTranslation 中翻译了一些字段。我们想通过 Api platform 检索实体及其翻译,并且我们想通过 api 添加或更新翻译。

我做了什么:

1 - Article 实体有一个 use ORMBehaviors\Translatable\Translatable。如果我们查看这个trait 的内部,它有两个属性:$translations$newTranslations。我们需要在Article 实体中公开这些属性:

class Article {
    use ORMBehaviors\Translatable\Translatable;

    protected $translations;
    protected $newTranslations;
}

现在我们有了一个新属性translations,当我们从api 获得一些Article 时,它会自动从ArticleTranslation 填充

2 - 现在我们要添加/编辑一些翻译:当我们发送到 api 时,我们需要在 Article 中填充 newTranslations 属性:

"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 的作用就像一个魅力。

我没想过一次只翻译一份。目前,我用一大堆翻译来检索我的实体,这绝对不是有效的。我想我会在我的覆盖trait 中为getTranslations 添加一个覆盖。

【讨论】:

  • 感谢@Maël 抽出时间来回答这个帖子,我会尽可能地尝试你的解决方案!
  • 嗨,当我尝试根据您的回答坚持 newTranslations 时,请不断收到"Could not denormalize object of type \"Knp\\DoctrineBehaviors\\Contract\\Entity\\TranslationInterface[]\", no supporting normalizer found."。你知道出了什么问题吗?
【解决方案2】:

我认为你做错了。你有一个实体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){...}
 }

如果一切正常,请告诉我。

【讨论】:

  • 感谢您的回复!我现在在另一个项目中,但我会尽快看看!顺便问一下,你能在 Api Platform 上使用knplabsBehaviour 吗?
  • 是的,它有效。我在POSTPUT 上遇到了麻烦。我认为 newTranslations 字段不是使用 api-platform 处理的。但我会找到解决方案/技巧。
  • 您找到 POST/PUT 的解决方案了吗?有没有其他方法可以在 ApiPlatform 中集成实体翻译?我正在寻找解决方案,其中 GET 上的实体(例如文章)将为内容提供通过语言环境键或通过语言环境选择翻译的可能性,并作为响应以语言环境指定的语言接收内容。还没有找到最好的解决方案:(
  • 我做了一个新的完整答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多