2014-02-16 3 views
2

symfony2.4 및 KNP 독트런 동작을 변환 할 수 있습니다.Knp DoctrineBehaviors가 ContextErrorException을 throw합니다. 경고 : call_user_func_array()가 매개 변수 1이 유효한 콜백이 될 것으로 예상합니다.

엔터티 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'); 

를 얻기 위해 쿼리를 사용합니다.

{{ item.id }} 

하지만 그것은 작동하지 않습니다

{{ item.name }} 

번역 필드 (이름, 설명, ...)을 인쇄 할 수 없습니다 : ID, 호스트 및 Site 기업에서 사용 가능 필드의 경우는 간단합니다.

오류 메시지 :

ContextErrorException : 경고 : call_user_func_array는() 매개 변수 1>에 유효한> 콜백, 클래스의 순 \ ConBundle \ 엔티티 \ SiteTranslation는 '방법'이름 '이없는 것으로 예상 D : \ 사용자 ... \ 업체 \ knplabs \ doctrine-> 행동 \ SRC \ KNP \ DoctrineBehaviors \ 모델 \ 번역 가능한 \ TranslatableMethods.php 라인 (140)

게터 및 번역 분야에 대한 세터 SiteTranslation 엔티티에 있습니다.

업데이트 : 난 아직도 오류에 대한 해결책을 찾을 수 없습니다

. 여기

<?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('&nbsp;', ENT_QUOTES, 'UTF-8'), 
     ($this->getLvl()) * 3 
    ) . $this->getName(); 
} 
public function getLeveledPosition() 
{ 
    return str_repeat(
     html_entity_decode('&nbsp;', ENT_QUOTES, 'UTF-8'), 
     ($this->getLvl()) * 3 
    ); 
} 
} 

그리고 SiteTranslation 개체됩니다 : 당신은 당신의 <Name>Translation 클래스에 모든 번역 속성/메소드를

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

이동하지 않은

여기 Site 엔티티입니다.

예외는 분명히 SiteTranslation 클래스에 이름/getName 메서드가 없음을 나타냅니다.

Knp \ DoctrineBehaviors의 마법 번역 프록시가 올바르게 사용되는 방법을 보려면 my answer over here을 읽으십시오.

+0

사이트 엔티티에서 내가 번역 속성/방법이 없습니다. 나는 그들을 모두 SiteTranslation으로 옮겼습니다. 그리고 SiteTranslation에서 나는 $ name; public function setName ($ name)과 public function getName()을 보호했습니다. 사이트 엔티티에서 저는 __call을 가지고 있습니다 : return $ this-> proxyCurrentLocaleTranslation ($ method, $ arguments); – kvaje

+0

번역 클래스의'$ name' 속성의 가시성을'protected'에서'public'으로 바꾸고 다시보고 해 주실 수 있습니까? – nifr

+0

공개'$ name' (으)로 변경되었지만 여전히 작동하지 않습니다. 오류 메시지는 동일합니다. – kvaje

5

TL; DR : A (아마 더러운) 해결 방법으로

,

{{ item.name }} 

설명 대신 나뭇 가지 템플릿에

{{ item.getName }} 

를 사용

나는 같은 문제를 보았고 이것이 Knp DoctrineBehaviors 문서의 버그로 간주되어야한다고 생각합니다. 당신이 당신의 나뭇 가지 템플릿이를 호출 할 때 :

{{ item.name }} 

이 나뭇 가지가 name 속성을 얻기 위해 무대 뒤에서 무엇이며 다음 item 객체의 name 공공 재산을 얻기 위해

  1. 시도
  2. 찾을 수 없다면 item 객체의 공개 메소드 을 확인하십시오. 찾을 수 없다면
  3. 을 확인하고 getName() 공개 메소드를 확인하십시오. 발견되지 않는 경우는
  4. __call() 마법 방법에 대한 검사 (그리고 name 매개 변수와 함께 호출)

이 문제는 여기에 4 단계가 정의한 마법 __call() 방법입니다 (권장하는대로 "항목"개체 공식 DoctrineBehaviors 문서에 따라) getName 대신 name 매개 변수가 호출됩니다. 그런 다음 proxyCurrentLocaleTranslation() 메서드를 호출하여 name 번역 클래스의 공용 메서드를 호출합니다. 물론 getName() 메소드 만 있기 때문에 존재하지 않습니다.

가 나뭇 가지에서이 문제를 참조하십시오 : 직접 나뭇 가지에 {{ item.getName }} 코드를 사용하여 https://github.com/twigphp/Twig/issues/342

을 적절한 방법 이름이 호출됩니다.

+0

나는 당신과 나는 {{item.getName}}에 동의했다. – kvaje

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); 
    } 

} 
관련 문제