API平台 - 实体翻译,学说可翻译

时间:2018-03-12 15:17:34

标签: doctrine-extensions api-platform.com

我试图在我的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和文档准确,翻译实体应该只有我们想要翻译的字段......

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

enter image description here

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

在文章表中:

  • no" local"字段
  • 不"空"字段

在ArticleTranslation表中:

  • no" translatable_id"字段
  • no" currentLocal"
  • no" defaultLocal"

我想它必须链接,但在招摇的POST标签中,模型也是不同的。

enter image description here           article_translation模型

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

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

提前致谢

2 个答案:

答案 0 :(得分:1)

我做了另一个回答,因为第一个问题是解决一个错误,而不是解释我如何将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-现在,我们想添加/编辑一些翻译:在发送到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添加覆盖。

答案 1 :(得分:0)

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

让我知道现在一切都还好吗。