1

我正在尝试在我的 API 平台项目中的一个实体上添加KnpLabs Doctrine Behaviors - 准确地说是可翻译行为。

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

    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 文档:

在此处输入图像描述

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

在文章表中:

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

在 ArticleTranslation 表中:

  • 没有“translatable_id”字段
  • 没有“当前本地”
  • 没有“默认本地”

我想它必须是链接的,但在大张旗鼓的 POST 选项卡中,模型也不同。

在此处输入图像描述 文章翻译模型

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

我希望我的帖子不会太长,但我试图更具体!

提前致谢

4

2 回答 2

2

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

概括 :

我们有一个实体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;
}

现在我们有了一个新属性translationsArticleTranslation当我们Articleapi

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

"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

于 2018-08-27T10:37:01.460 回答
0

我认为你做错了。Article您有一个应该是的实体,translatable并且您想翻译一些将是的字段translations

所以你应该做相反的事情,把 the use ORMBehaviors\Translatable\Translatableon theArticle和 the use ORMBehaviors\Translatable\Translationon theArticleTranslation

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

让我知道现在是否一切都好。

于 2018-07-06T08:45:46.860 回答