我正在尝试使用gedmo doctrine extensions翻译实体。
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
我可以毫无问题地翻译标题。但是slu is不行......
通常情况下,在默认语言(tr)上,slug auto是在没有任何生成过程的情况下自动生成的。
实体档案:
<?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;
}
}
我不知道如何应用这些听众。
如何自动翻译slug?
我的config.yml for doctrine和stof_doctrine_extensions:
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
答案 0 :(得分:4)
经过一番挣扎,我想我已经找到了解决问题的方法。让我们开始做生意。
首先,我注意到你正在使用 StofDoctrineExtensionsBundle ,它是 Gedmo Doctrine2扩展程序的包装器。
安装/使用似乎更容易,但从长远来看,它会使问题复杂化。在这种情况下,例如,为了解决您的问题,您必须修改侦听器,并且使用该捆绑包,我能想到的唯一解决方案是破解代码并手动更改服务的优先级。这导致了第一个解决方案:
第一个解决方案:破解捆绑(不是很好)
服务可以在
中找到StofDoctrineExtensionsBundle /资源/配置/ listeners.xml
您需要查找和修改可缓存服务并提高其优先级。这样,该服务将在可翻译服务之前执行。 slu will将首先被创建并且可翻译将很好地存储它。
修改(虽然我认为它可能有效但尚未尝试过):
<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扩展(如何操作here)。
您会注意到,为了安装扩展程序,您必须在包中创建包含必要服务的文件。那很好。转到该文件并修改可缓存服务的优先级:
gedmo.listener.sluggable:
class: Gedmo\Sluggable\SluggableListener
tags:
- { name: doctrine.event_subscriber, connection: default, priority: 1 }
calls:
- [ setAnnotationReader, [ @annotation_reader ] ]
现在已经准备好了。
这些是我的yml和php的实体Post(我认为它们与你的非常相似,但可以有所不同):
<强> 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。
希望它有所帮助和善意。
答案 1 :(得分:1)
对我来说很奇怪:你的ORM按实体配置是在2个文件(yaml和annotation)中完成的吗?
听众看起来按照正确的顺序加载。也许它是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: {}
答案 2 :(得分: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 ] ]
答案 3 :(得分:0)
我使用StofDoctrineExtensionsBundle
进行缓慢和可翻译并遇到同样的问题。
我已经搜索并尝试了一段时间,找到了适合我的解决方案:
<强>实体:强> slug字段从名称字段生成
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,
]);
}
实体存储库,其中包含返回实体的查询方法
/**
* 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();
}
我希望这个例子可以帮助别人。