我使用symfony2.4和KNP教义行为可翻译。
我有实体Site
(用于ID,主机,已启用)和实体SiteTranslation
(对于已翻译的字段:名称,说明,...)。
我使用查询来获得结果
$qb = $this->createQueryBuilder('s')
->addSelect('translation') // to eager fetch translations (optional)
->leftJoin('s.translations', 'translation') // or innerJoin ?
->orderBy('s.root', 'ASC')
->addOrderBy('s.lft', 'ASC');
我想在Twig中打印结果。对于来自Site
实体的ID,主机和已启用字段,这很容易:
{{ item.id }}
但是我无法打印翻译的字段(名称,描述,......)
{{ item.name }}
它不起作用。
错误讯息:
ContextErrorException:警告:call_user_func_array()期望参数1是有效的>回调,类'Net \ ConBundle \ Entity \ SiteTranslation'在> D:\ Users ...中没有方法'name' vendor \ knplabs \ doctrine-> behavior \ src \ Knp \ DoctrineBehaviors \ Model \ Translatable \ TranslatableMethods.php第140行
可翻译字段的getter和setter位于SiteTranslation实体中。
更新
我仍然没有找到错误的解决方案。
这是Site
实体:
<?php
namespace Pnet\ConlocoBundle\Entity;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
/**
* @UniqueEntity("host", message="site.host.unique", groups={"edit"})
* @Gedmo\Tree(type="nested")
* @ORM\Entity(repositoryClass="Pnet\ConlocoBundle\Entity\Repository\SiteRepository")
* @ORM\Table(name="site")
*/
class Site
{
use ORMBehaviors\Translatable\Translatable; // knp translatable strategy
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(type="string", length=40, unique=true)
* @Assert\NotBlank(message="site.host.notBlank", groups={"edit"})
* @Assert\Length(max = "40", maxMessage = "site.host.maxLength", groups={"edit"})
*/
protected $host;
/**
* @ORM\Column(type="string", length=255, nullable=true)
* @Assert\Image()
*/
protected $image;
/**
* @ORM\Column(type="boolean")
* @Assert\Choice(choices = {"1", "0"}, message = "site.isDefault.choice", groups={"edit"})
*/
protected $isDefault;
/**
* @ORM\Column(type="boolean")
* @Assert\Choice(choices = {"1", "0"}, message = "site.enabled.choice", groups={"edit"})
*/
protected $enabled;
/**
* @ORM\Column(type="string", length=64, nullable=true)
*/
protected $analytics;
/**
* @Gedmo\TreeLeft
* @ORM\Column(name="lft", type="integer")
*/
private $lft;
/**
* @Gedmo\TreeLevel
* @ORM\Column(name="lvl", type="integer")
*/
private $lvl;
/**
* @Gedmo\TreeRight
* @ORM\Column(name="rgt", type="integer")
*/
private $rgt;
/**
* @Gedmo\TreeRoot
* @ORM\Column(name="root", type="integer", nullable=true)
*/
private $root;
/**
* @Gedmo\TreeParent
* @ORM\ManyToOne(targetEntity="Site", inversedBy="children")
* @ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="CASCADE")
*/
private $parent;
/**
* @ORM\OneToMany(targetEntity="Site", mappedBy="parent")
* @ORM\OrderBy({"lft" = "ASC"})
*/
private $children;
private $file;
public $idByFilter;
public $nameByFilter;
/**
* Proxy translations (Knp/Doctrine Behaviors)
* An extra feature allows you to proxy translated fields of a translatable entity.
* You can use it in the magic __call method of you translatable entity so that when
* you try to call getName (for example) it will return you the translated value
* of the name for current locale:
*/
public function __call($method, $arguments)
{
return $this->proxyCurrentLocaleTranslation($method, $arguments);
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set host
*
* @param string $host
* @return Site
*/
public function setHost($host)
{
$this->host = $host;
return $this;
}
/**
* Get host
*
* @return string
*/
public function getHost()
{
return $this->host;
}
/**
* Set isDefault
*
* @param boolean $isDefault
* @return Site
*/
public function setIsDefault($isDefault)
{
$this->isDefault = $isDefault;
return $this;
}
/**
* Get isDefault
*
* @return boolean
*/
public function getIsDefault()
{
return $this->isDefault;
}
/**
* Set enabled
*
* @param boolean $enabled
* @return Site
*/
public function setEnabled($enabled)
{
$this->enabled = $enabled;
return $this;
}
/**
* Get enabled
*
* @return boolean
*/
public function getEnabled()
{
return $this->enabled;
}
/**
* Set analytics
*
* @param string $analytics
* @return Site
*/
public function setAnalytics($analytics)
{
$this->analytics = $analytics;
return $this;
}
/**
* Get analytics
*
* @return string
*/
public function getAnalytics()
{
return $this->analytics;
}
/**
* Get ID from Filter
*
* @return string
*/
public function getIdByFilter()
{
return $this->idByFilter;
}
/**
* Get name from Filter
*
* @return string
*/
public function getNameByFilter()
{
return $this->nameByFilter;
}
/**
* Set image
*
* @param string $image
* @return Site
*/
public function setImage($image)
{
$this->image = $image;
return $this;
}
/**
* Get image
*
* @return string
*/
public function getImage()
{
return $this->image;
}
/**
* Set file
*
* @param string $file
* @return Site
*/
public function setFile($file)
{
$this->file = $file;
return $this;
}
/**
* Get file
*
* @return string
*/
public function getFile()
{
return $this->file;
}
/**
*
* Tree functions
*/
public function setParent(Site $parent = null)
{
$this->parent = $parent;
}
public function getParent()
{
return $this->parent;
}
public function getRoot()
{
return $this->root;
}
public function getLvl()
{
return $this->lvl;
}
public function getChildren()
{
return $this->children;
}
public function getLft()
{
return $this->lft;
}
public function getRgt()
{
return $this->rgt;
}
/**
* Add a method to the entity class that shows the name indented by nesting level
*/
public function getLeveledName()
{
return str_repeat(
html_entity_decode(' ', ENT_QUOTES, 'UTF-8'),
($this->getLvl()) * 3
) . $this->getName();
}
public function getLeveledPosition()
{
return str_repeat(
html_entity_decode(' ', ENT_QUOTES, 'UTF-8'),
($this->getLvl()) * 3
);
}
}
这是SiteTranslation
实体:
namespace Pnet\ConlocoBundle\Entity;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
/**
* @ORM\Entity
*/
class SiteTranslation
{
use ORMBehaviors\Translatable\Translation;
/**
* @ORM\Column(type="string", length=60)
* @Assert\NotBlank(message="site.name.notBlank", groups={"edit"})
* @Assert\Length(max = "60", maxMessage = "site.name.maxLength", groups={"edit"})
*/
protected $name;
/**
* @ORM\Column(type="string", length=100)
* @Assert\NotBlank(message="site.title.notBlank", groups={"edit"})
* @Assert\Length(max = "100", maxMessage = "site.title.maxLength", groups={"edit"})
*/
protected $title;
/**
* @ORM\Column(type="string", length=200)
* @Assert\NotBlank(message="site.longTitle.notBlank", groups={"edit"})
* @Assert\Length(max = "200", maxMessage = "site.longTitle.maxLength", groups={"edit"})
*/
protected $longTitle;
/**
* @ORM\Column(type="string", length=250, nullable=true)
* @Assert\Length(max = "250", maxMessage = "site.keywords.maxLength", groups={"edit"})
*/
protected $keywords;
/**
* @ORM\Column(type="string", length=500, nullable=true)
* @Assert\Length(max = "500", maxMessage = "site.description.maxLength", groups={"edit"})
*/
protected $description;
/**
* Set name
*
* @param string $name
* @return Site
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set title
*
* @param string $title
* @return Site
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set longTitle
*
* @param string $longTitle
* @return Site
*/
public function setLongTitle($longTitle)
{
$this->longTitle = $longTitle;
return $this;
}
/**
* Get longTitle
*
* @return string
*/
public function getLongTitle()
{
return $this->longTitle;
}
/**
* Set keywords
*
* @param string $keywords
* @return Site
*/
public function setKeywords($keywords)
{
$this->keywords = $keywords;
return $this;
}
/**
* Get keywords
*
* @return string
*/
public function getKeywords()
{
return $this->keywords;
}
/**
* Set description
*
* @param string $description
* @return Site
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* @return string
*/
public function getDescription()
{
return $this->description;
}
}
答案 0 :(得分:5)
<强> TL; DR:强>
作为(可能是脏的)解决方法,请使用
{{ item.getName }}
在您的Twig模板中而不是
{{ item.name }}
<强>解释强>
我遇到了同样的问题,我认为在与Twig一起使用时,这应该被认为是Knp DoctrineBehaviors文档中的一个错误。当你在Twig模板中调用它时:
{{ item.name }}
这是Twig在幕后获取name
属性的原因:
name
对象item
公共属性
name
对象的item
公共方法getName()
公共方法。对象__call()
魔术方法(并使用name
参数调用它)此处的问题是第4步。您定义的神奇__call()
方法(正如DoctrineBehaviors官方文档所推荐)使用name
参数而不是getName
进行调用。然后,它会调用尝试调用翻译课程的proxyCurrentLocaleTranslation()
公共方法的name
方法。当然,它不存在,因为你只有getName()
方法。
在Twig中查看此问题:https://github.com/twigphp/Twig/issues/342
通过直接使用Twig中的{{ item.getName }}
代码,将调用正确的方法名称。
答案 1 :(得分:2)
这项工作对我来说:
public function __call($method, $arguments)
{
try {
return $this->proxyCurrentLocaleTranslation($method, $arguments);
} catch (\Symfony\Component\Debug\Exception\ContextErrorException $e) {
return $this->proxyCurrentLocaleTranslation('get' . ucfirst($method), $arguments);
}
}
答案 2 :(得分:0)
您尚未将所有可翻译属性/方法移至<Name>Translation
类。
该异常明确指出您的SiteTranslation类中没有name / getName方法。
请阅读my answer over here,了解如何正确使用Knp \ DoctrineBehaviors的魔术翻译代理。