15

我正在尝试使用 gedmo 学说扩展来翻译实体。

https://github.com/Atlantic18/DoctrineExtensions

我使用 yml 作为 orm 映射文件(自动生成实体)。

orm.yml:

CS\ContentBundle\Entity\Post:
  type:  entity
  table: posts
  repositoryClass: CS\ContentBundle\Entity\PostRepository
  gedmo:
    soft_deleteable:
      field_name: deleted_at
    translation:
      locale: locale
  fields:
    id:
      type: integer
      length: 11
      id: true
      generator:
        strategy: AUTO
    title:
      type: string
      length: 500
      gedmo:
        - translatable
    slug:
      type: string
      length: 500
      gedmo:
        translatable: {}
        slug:
          separator: -
          fields:
            - title

我可以毫无问题地翻译标题。但蛞蝓不起作用...

通常,在默认语言(tr)上,自动生成的 slug 无需我进行任何生成过程。

实体文件:

<?php

namespace CS\ContentBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Translatable\Translatable;
use Gedmo\Mapping\Annotation as Gedmo;
use APY\DataGridBundle\Grid\Mapping as GRID;

/**
 * Post
 * @Gedmo\SoftDeleteable(fieldName="deleted_at", timeAware=false)
 * @GRID\Source(columns="id,title,is_active,created_at,updated_at")
 */
class Post implements Translatable
{
    /**
     * @var integer
     */
    private $id;

    /**
     * @var string
     * @Gedmo\Translatable
     * @GRID\Column(title="Başlık", filterable=true)
     */
    private $title;

    /**
     * @var string
     * @Gedmo\Translatable
     */
    private $slug;

    /**
     * @Gedmo\Locale
     */
    private $locale;

    public function setLocale($locale)
    {
        $this->locale = $locale;
    }


    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set title
     *
     * @param string $title
     * @return Post
     */
    public function setTitle($title)
    {
        $this->title = $title;

        return $this;
    }

    /**
     * Get title
     *
     * @return string 
     */
    public function getTitle()
    {
        return $this->title;
    }

    /**
     * Set slug
     *
     * @param string $slug
     * @return Post
     */
    public function setSlug($slug)
    {
        $this->slug = $slug;

        return $this;
    }

    /**
     * Get slug
     *
     * @return string 
     */
    public function getSlug()
    {
        return $this->slug;
    }
}

文档中有一部分: https ://github.com/Atlantic18/DoctrineExtensions/blob/master/doc/sluggable.md#using-translationlistener-to-translate-our-slug

我不知道如何应用这些听众。

我应该怎么做才能自动翻译 slug?


编辑

我的学说和 stof_doctrine_extensions 的 config.yml:

doctrine:
    dbal:
        default_connection: default
        connections:
            default:
                driver:   "%database_driver%"
                host:     "%database_host%"
                port:     "%database_port%"
                dbname:   "%database_name%"
                user:     "%database_user%"
                password: "%database_password%"
                charset:  UTF8
                mapping_types:
                  enum: string
    orm:
        auto_generate_proxy_classes: "%kernel.debug%"
        auto_mapping: true
        metadata_cache_driver: redis
        query_cache_driver: redis
        filters:
            softdeleteable:
                class: Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter
                enabled: true
        mappings:
            StofDoctrineExtensionsBundle: ~
            gedmo_translatable:
                type: annotation
                prefix: Gedmo\Translatable\Entity
                dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity"
                alias: GedmoTranslatable # this one is optional and will default to the name set for the mapping
                is_bundle: false
            gedmo_tree:
                type: annotation
                prefix: Gedmo\Tree\Entity
                dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Tree/Entity"
                alias: GedmoTree # this one is optional and will default to the name set for the mapping
                is_bundle: false

stof_doctrine_extensions:
    default_locale: "%locale%"
    translation_fallback: true
    orm:
        default:
            tree: true
            sluggable: true
            translatable: true
            timestampable: true
            softdeleteable: true
4

4 回答 4

4

经过一番挣扎,我想我已经设法找到解决您问题的方法。让我们谈正事吧。

首先,我注意到您正在使用StofDoctrineExtensionsBundle,它是Gedmo Doctrine2 extensions的包装器。

它可能看起来更容易安装/使用,但从长远来看,它会使事情复杂化。例如,在这种情况下,为了解决您的问题,您必须修改侦听器,并且使用该捆绑包,我能想出的唯一解决方案是破解代码并手动更改服务的优先级。这导致第一个解决方案:

第一个解决方案:破解捆绑包(不是一个好的)

服务可以在

StofDoctrineExtensionsBundle/Resources/config/listeners.xml

您需要找到并修改 sluggable 服务并提高其优先级。这样,该服务将在可翻译服务之前执行。slug 将首先创建,并且可翻译的将很好地存储它。

修改(虽然我认为它可能有效,但没有尝试过):

<service id="stof_doctrine_extensions.listener.sluggable" class="%stof_doctrine_extensions.listener.sluggable.class%" public="false">
    <tag name="kernel.cache_warmer" priority="1" />
    <call method="setAnnotationReader">
        <argument type="service" id="annotation_reader" />
    </call>
</service>

但是,我不喜欢这种解决方案。老实说,我不喜欢包装纸。我将为您提供另一种我认为更令人满意的解决方案(并且我尝试过并且有效)。

第二种解决方案(也是最好的一种)

首先,摆脱 StofDoctrineExtensionsBundle。其次,安装 Gedmo Doctrine2 扩展(如何在此处进行)。

您会注意到,为了安装扩展,您必须在捆绑包中创建一个包含必要服务的文件。那很好。转到该文件并修改 sluggable 服务的优先级:

gedmo.listener.sluggable:
        class: Gedmo\Sluggable\SluggableListener
        tags:
            - { name: doctrine.event_subscriber, connection: default, priority: 1 }
        calls:
            - [ setAnnotationReader, [ @annotation_reader ] ]

现在它已经准备好了。

这些是我的实体 Post 的 yml 和 php(我认为它们与您的非常相似,但可能有所不同):

YML

DSG\AcmeBundle\Entity\Post:
    type:  entity
    table: posts
    gedmo:
        soft_deleteable:
            field_name: deleted_at
        translation:
            locale: locale
    fields:
        id:
            type: integer
            length: 11
            id: true
            generator:
                strategy: AUTO
        title:
            type: string
            length: 255
            gedmo:
                - translatable
        slug:
            type: string
            length: 255
            unique: true
            gedmo:
                translatable: {}
                slug:
                    separator: _
                    style: camel
                    fields:
                        - title

PHP

namespace DSG\AcmeBundle\Entity;

use Gedmo\Translatable\Translatable;

class Post implements Translatable
{
    /**
     * @var integer
     */
    private $id;

    /**
     * @var string
     */
    private $title;

    /**
     * @var string
     */
    private $slug;

    /**
     * @var string
     */
    private $locale;

    public function setTranslatableLocale($locale)
    {
        $this->locale = $locale;
    }


    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set title
     *
     * @param string $title
     * @return Post
     */
    public function setTitle($title)
    {
        $this->title = $title;

        return $this;
    }

    /**
     * Get title
     *
     * @return string
     */
    public function getTitle()
    {
        return $this->title;
    }

    /**
     * Set slug
     *
     * @param string $slug
     * @return Post
     */
    public function setSlug($slug)
    {
        $this->slug = $slug;

        return $this;
    }

    /**
     * Get slug
     *
     * @return string
     */
    public function getSlug()
    {
        return $this->slug;
    }
}

当您创建实体并将其存储在数据库中时,它将创建 slug 并将标题和 slug 存储在翻译表中(如果您更改语言环境)。

如果你试试:

$em = $this->getDoctrine()->getEntityManager();
$article = new Post();
$article->setTitle('the title');
$em->persist($article);
$em->flush();

$article = $this->getDoctrine()->getRepository('DSGMDayBundle:Post')->find(1);
$article->setTitle('my title in de');
$article->setTranslatableLocale('de_de'); // change locale
$em->persist($article);
$em->flush();

你会看到你的翻译表有两行,一行用于标题,另一行用于本地 de_de 的 slug。

希望它有所帮助和亲切的问候。

于 2014-12-30T21:33:32.603 回答
1

对我来说有些奇怪:您的 ORM 实体配置是在 2 个文件(yaml 和注释)中完成的?

听众看起来加载良好,顺序正确。也许它是orm.yml. 尝试在现场反转可翻译和可移动slug

CS\ContentBundle\Entity\Post:
  type:  entity
  table: posts
  repositoryClass: CS\ContentBundle\Entity\PostRepository
  gedmo:
    soft_deleteable:
      field_name: deleted_at
    translation:
      locale: locale
  fields:
    id:
      type: integer
      length: 11
      id: true
      generator:
        strategy: AUTO
    title:
      type: string
      length: 500
      gedmo:
        - translatable
    slug:
      type: string
      length: 500
      gedmo:
        slug:
          separator: -
          fields:
            - title
        translatable: {}
于 2014-12-24T14:57:22.097 回答
1

您的配置看起来是正确的。但是,您是否尝试更新供应商?也许某些文件可能已损坏。

如果更新过程不起作用,您能否将配置与我的完全比较:

doctrine:
    dbal:
        driver:   "%database_driver%"
        host:     "%database_host%"
        port:     "%database_port%"
        dbname:   "%database_name%"
        user:     "%database_user%"
        password: "%database_password%"
        charset:  UTF8
    orm:
        auto_generate_proxy_classes: "%kernel.debug%"
        auto_mapping: true
        dql:
            string_functions:
                GroupConcat: DoctrineExtensions\Query\Mysql\GroupConcat
                IF: DoctrineExtensions\Query\Mysql\IfElse
        filters:
            softdeleteable:
                class: Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter
                enabled: true
        mappings:
            StofDoctrineExtensionsBundle: ~
            gedmo_tree:
                type: annotation
                prefix: Gedmo\Tree\Entity
                dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Tree/Entity"
                alias: GedmoTree
                is_bundle: false
            translatable:
                type: annotation
                alias: Gedmo
                prefix: Gedmo\Translatable\Entity
                # make sure vendor library location is correct
                dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity"

并确保不要覆盖 services.yml 上的gedmo.listener.translatable。如果有任何代码覆盖了默认代码,请将其删除。默认配置:

gedmo.listener.translatable:
        class: Gedmo\Translatable\TranslatableListener
        tags:
            - { name: doctrine.event_subscriber, connection: default }
        calls:
            - [ setAnnotationReader, [ @annotation_reader ] ]
            - [ setDefaultLocale, [ %locale% ] ]
            - [ setTranslationFallback, [ false ] ]
于 2014-12-29T20:55:17.910 回答
0

StofDoctrineExtensionsBundle用于 sluggable 和 translatable 并且遇到了同样的问题。

我已经搜索并尝试了一段时间,并找到了一个适合我的解决方案:


实体: slug 字段从 name 字段生成

use Gedmo\Mapping\Annotation as Gedmo;
use Gedmo\Translatable\Translatable;

/**
 * @var string
 *
 * @Gedmo\Translatable
 * @ORM\Column(name="name", type="string", length=150, unique=true)
 */
private $name;

/**
 * @Gedmo\Translatable
 * @Gedmo\Slug(fields={"name"}, updatable=true)
 * @ORM\Column(type="string", unique=true)
 */
private $slug;

config.yml:在这里你必须设置persist_default_translation: true https://github.com/Atlantic18/DoctrineExtensions/issues/542#issuecomment-12983553

parameters:
    locale: en

doctrine:
    orm:
        auto_generate_proxy_classes: '%kernel.debug%'
        naming_strategy: doctrine.orm.naming_strategy.underscore
        auto_mapping: true
        mappings:
            gedmo_translatable:
                type: annotation
                prefix: Gedmo\Translatable\Entity
                dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity"
                alias: GedmoTranslatable # (optional) it will default to the name set for the mapping
                is_bundle: false
            gedmo_translator:
                type: annotation
                prefix: Gedmo\Translator\Entity
                dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Translator/Entity"
                alias: GedmoTranslator # (optional) it will default to the name set for the mapping
                is_bundle: false

stof_doctrine_extensions:
    default_locale: '%locale%'
    translation_fallback: true
    persist_default_translation: true    # I think this does the trick
    orm:
        default:
            sluggable: true
            translatable: true

DefaultController用于ParamConverter调用返回当前语言环境的正确实体的查询

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;

/**
 * @Route("/entry/{slug}", name="entry_detail")
 * @ParamConverter("entry", class="AppBundle:Entry", options={"repository_method" = "findOneByCriteria"})
 */
public function entryDetailAction(Request $request, Entry $entry)
{
    return $this->render('frontend/entry.html.twig', [
        'entry' => $entry,
    ]);
}

Entity Repository用查询方法返回实体

/**
 * Find an entry by criteria
 * Need this special function, because of translatable
 * https://github.com/stof/StofDoctrineExtensionsBundle/issues/232
 *
 * @param $params
 * @return mixed
 */
public function findOneByCriteria(array $params)
{
    $query = $this->createQueryBuilder('e');
    $i = 0;
    foreach ($params as $column => $value) {
        if ($i < 1) {
            $query->where("e.$column = :$column");
        } else {
            $query->andWhere("e.$column = :$column");
        }
        $query->setParameter($column, $value);
        $i++;
    }
    $query = $query->getQuery();
    $query->setHint(\Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER, 'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker');
    return $query->getOneOrNullResult();
}

我希望这个例子对某人有所帮助。

于 2018-01-02T21:32:16.077 回答