我在网站上实施搜索,为了简单起见,我决定创建一个能够完成艰苦工作的课程。
基本上我的类使用EntityManager和我想要搜索的实体并创建DQL并执行查询。对于普通实体,这工作完全正常但是当我传递User实体(从fos用户包实体扩展)时,我收到此错误:
[语义错误]第0行,第139行附近' last_login LIKE':错误:类Soundmerger \ UserBundle \ Entity \ User没有名为last_login的字段或关联
生成的dql查询似乎很好,因为它适用于其他实体,我怀疑它来自那里。
这是我的搜索类:
use Doctrine\Common\Util\Debug;
use Doctrine\ORM\EntityManager;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Query;
class Search {
private $em;
private $searchables;
public function __construct(EntityManager $em, ArrayCollection $searchables){
$this->em = $em;
$this->searchables = $searchables;
}
public function search($query){
$words = explode("+", $query);
$qb = array();
$results = array();
foreach($this->searchables as $qNumber => $searchable){
$qb[$qNumber] = "SELECT s FROM $searchable s ";
$columns = $this->em->getClassMetadata($searchable)->getColumnNames();
foreach($words as $i => $word){
foreach($columns as $k => $column){
$string = "s.$column LIKE '%$word%'";
if($i == 0 && $k == 0){
$qb[$qNumber] .= "WHERE $string";
} else {
$qb[$qNumber] .= "OR $string";
}
}
}
$res[] = $this->em->createQuery($qb[$qNumber])->getResult(Query::HYDRATE_SIMPLEOBJECT);
}
return $this->formatSearch($res);
}
private function formatSearch($results){
$formatedResult = array();
foreach($results as $k => $result){
if(!empty($result)){
$formatedResult[$k]["type"] = get_class($result[0]);
$formatedResult[$k]["data"] = $result[0];
}
}
return $formatedResult;
}
}
我的搜索控制器:
/**
* @Route("/search/{query}")
* @Template()
*/
public function indexAction($query)
{
$em = $this->getDoctrine()->getManager();
$searchables = new ArrayCollection(
array(
"SoundmergerUserBundle:Professional",
"SoundmergerFaqBundle:Faq",
"SoundmergerUserBundle:User",
));
$search = new Search($em, $searchables);
return array('search' => $search->search($query));
}
最后是我的用户实体:
/**
* @ORM\Entity
* @ORM\Table(name="fos_user")
* @AttributeOverrides({
* @AttributeOverride(name="emailCanonical",
* column=@ORM\Column(
* name = "emailCanonical",
* type = "string",
* length = 255,
* nullable = true
* )
* ),
* @AttributeOverride(name="email",
* column=@ORM\Column(
* name = "email",
* type = "string",
* length = 255,
* nullable = true
* )
* ),
* @AttributeOverride(name="username",
* column=@ORM\Column(
* name = "username",
* type = "string",
* length = 255,
* unique = false
* )
* ),
* @AttributeOverride(name="usernameCanonical",
* column=@ORM\Column(
* name = "usernameCanonical",
* type = "string",
* length = 255,
* unique = false
* )
* ),
* })
*/
class User extends BaseUser
{
const STRUCTURE_SOLO = "solo";
const STRUCTURE_GROUP = "group";
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(type="string", nullable=true)
* @var string
*/
protected $nomProfile = null;
/**
* @ORM\Column(type="text", nullable=true)
* @var string
*/
protected $description = null;
/**
* @ORM\Column(type="string", nullable=true)
* @var string
*/
protected $type = null;
/**
* @ORM\Column(type="string")
* @var string
*/
protected $structure = self::STRUCTURE_SOLO;
/**
* @ORM\Column(type="string", nullable=true)
* @var string
*/
protected $tel = null;
/**
* @ORM\Column(type="string", nullable=true)
* @var string
*/
protected $site = null;
/**
* @ORM\Column(type="boolean")
* @var bool
*/
protected $firstLogin = true;
/**
* @ORM\OneToOne(targetEntity="Soundmerger\MainBundle\Entity\Address", cascade={"persist"})
*/
protected $address;
/**
* @ORM\OneToMany(targetEntity="Soundmerger\MainBundle\Entity\Style", mappedBy="user", cascade={"persist"})
*/
protected $styles;
/**
* @ORM\OneToMany(targetEntity="Soundmerger\UserBundle\Entity\Member", mappedBy="user")
* @ORM\JoinColumn(nullable=true)
*/
protected $members;
/** @ORM\Column(name="discogs_id", type="string", length=255, nullable=true) */
protected $discogs_id;
/** @ORM\Column(name="discogs_access_token", type="string", length=255, nullable=true) */
protected $discogs_access_token;
public function __construct()
{
parent::__construct();
$this->members = new ArrayCollection();
$this->styles = new ArrayCollection();
}
/**
* Get id
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* Get NomProfile
* @return string
*/
public function getNomProfile()
{
return $this->nomProfile;
}
/**
* Get type
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* Get structure
* @return string
*/
public function getStructure()
{
return $this->structure;
}
/**
* Get tel
* @return string
*/
public function getTel()
{
return $this->tel;
}
/**
* Get site
* @return string
*/
public function getSite()
{
return $this->site;
}
/**
* Get description
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set nomProfile
* @param string $nomProfile
* @return \Soundmerger\UserBundle\Entity\Utilisateur
*/
public function setNomProfile($nomProfile)
{
$this->nomProfile = $nomProfile;
return $this;
}
/**
* Set type
* @param string $type
* @return \Soundmerger\UserBundle\Entity\Utilisateur
*/
public function setType($type)
{
$this->type = $type;
return $this;
}
/**
* Set structure
* @param string $structure
* @return \Soundmerger\UserBundle\Entity\Utilisateur
*/
public function setStructure($structure)
{
if (!in_array($structure, array(self::STRUCTURE_SOLO, self::STRUCTURE_GROUP))) {
throw new \InvalidArgumentException("Invalid structure");
}
$this->structure = $structure;
return $this;
}
/**
* Set tel
* @param string $tel
* @return \Soundmerger\UserBundle\Entity\Utilisateur
*/
public function setTel($tel)
{
$this->tel = $tel;
return $this;
}
/**
* Set site
* @param string $site
* @return \Soundmerger\UserBundle\Entity\Utilisateur
*/
public function setSite($site)
{
$this->site = $site;
return $this;
}
/**
* Set description
* @param type $description
* @return \Soundmerger\UserBundle\Entity\Utilisateur
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Set the first login
* @param bool $firstLogin
* @return \Soundmerger\UserBundle\Entity\Utilisateur
*/
public function setFirstLogin($firstLogin)
{
$this->firstLogin = $firstLogin;
return $this;
}
/**
* Is it the first login
* @return bool returns true if its the first login, false otherwise
*/
public function isFirstLogin()
{
return $this->firstLogin;
}
/**
* Set address
*
* @param Address $address
* @return $this
*/
public function setAddress(Address $address)
{
$this->address = $address;
return $this;
}
/**
* Get adress
*
* @return mixed
*/
public function getAddress()
{
return $this->address;
}
/**
* @return Style
*/
public function getStyles()
{
return $this->styles;
}
/**
* @param Style $style
* @return $this
*/
public function addStyle(Style $style)
{
if (!$this->styles->contains($style)) {
$style->setUser($this);
$this->styles->add($style);
}
return $this;
}
public function setStyles(PersistentCollection $styles)
{
foreach ($styles as $style) {
$this->addStyle($style);
}
}
/**
* @return ArrayCollection
*/
public function getMembers()
{
return $this->members;
}
/**
* @param Member $members
*/
public function addMember(Member $member)
{
if (!$this->members->contains($member)) {
$this->members->add($member);
}
return $this;
}
public function setDiscogsId($discogs_id)
{
$this->discogs_id = $discogs_id;
return $this;
}
public function getDiscogsId()
{
return $this->discogs_id;
}
public function setDiscogsAccessToken($discogs_access_token)
{
$this->discogs_access_token = $discogs_access_token;
return $this;
}
public function getDiscogsAccessToken()
{
return $this->discogs_access_token;
}
public function isRegisteredWithDiscogs(){
return $this->discogs_id != null;
}
}
关于为什么这只发生在用户实体上的任何想法(它必须归因于继承,但我似乎无法找到解决方法)
顺便说一下:它是一个大学项目,因此使用外部捆绑进行搜索的想法实际上是不可能的。感谢您的帮助
丹