I hope you can help :)
This is how the table looks:
+------------+----------------+------------------+---------+
| firstName | lastName | email | etc... |
+------------+----------------+------------------+---------+
| John | Doe | john@doe.com | etc... |
+------------+----------------+------------------+---------+
| John | Michaels | john@michaels.es | etc... |
+------------+----------------+------------------+---------+
This is how the code looks:
if($_GET['search-customers'] != '') {
$busqueda = $_GET['search-customers'];
$query->andWhere("(c.firstName LIKE '%$busqueda%' OR c.lastName LIKE '%$busqueda%' OR c.email LIKE '%$busqueda%')");
}
With that QUERY:
All right, I understand, When I type "John D", it try to find first in firstName (doesn't match) and also it doesn't match lastName or email.
How can I combine them?
The idea its to find the complete string in all possibilities.
Thanks!
答案 0 :(得分:5)
我会使用MySQL's Full-Text Search Functions为您提供另一种选择。让我们开始准备桌子:
ALTER TABLE persons ADD FULLTEXT (`firstname`, `lastname`);
现在,firstname
和lastname
是全文使用的列,用于搜索匹配项:
SELECT * FROM persons
WHERE MATCH (firstname,lastname)
AGAINST ('John D' IN NATURAL LANGUAGE MODE);
结果将是:
+------------+----------------+------------------+---------+
| firstName | lastName | email | etc... |
+------------+----------------+------------------+---------+
| John | Doe | john@doe.com | etc... |
+------------+----------------+------------------+---------+
| John | Michaels | john@michaels.es | etc... |
+------------+----------------+------------------+---------+
两个为什么?由于John
(作为单词)被找到,但John Doe
位于第一行,因为它与搜索词有很多相似之处。
说,让我们将此工具应用于Doctrine。我假设你的模型看起来像这样:
class Person{
/** @column(type="string", name="firstname")*/
protected $firstName;
/** @column(type="string", name="lastname")*/
protected $lastName;
/** @column(type="string")*/
protected $email;
}
让我们创建搜索功能:
public function search($term){
$rsm = new ResultSetMapping();
// Specify the object type to be returned in results
$rsm->addEntityResult('Models\Person', 'p');
// references each attribute with table's columns
$rsm->addFieldResult('p', 'firstName', 'firstName');
$rsm->addFieldResult('p', 'lastName', 'lastname');
$rsm->addFieldResult('p', 'email', 'email');
// create a native query
$sql = 'select p.firstName, p.lastname, p.email from persons p
where match(p.firstname, p.lastname) against(?)';
// execute the query
$query = $em->createNativeQuery($sql, $rsm);
$query->setParameter(1, $term);
// getting the results
return $query->getResult();
}
Finnally,例如:
$term = 'John D';
$results = search($term);
// two results
echo count($results);
附加说明:
MyISAM
表。CHAR
,VARCHAR
或TEXT
列编入索引。 IN NATURAL LANGUAGE MODE
时,如果结果代表记录的< 50%
,则mysql返回空结果。答案 1 :(得分:0)
也许你可以像这样使用explode
函数:
$busqueda = $_GET['search-customers'];
$names = explode(' ',$busqueda);
if(count($names)>1){
$query->andWhere("(c.firstName LIKE '%{$names[0]}%' AND c.lastName LIKE '%{$names[1]}%')");
}else{
$query->andWhere("(c.firstName LIKE '%$busqueda%' OR c.lastName LIKE '%$busqueda%' OR c.email LIKE '%$busqueda%')");
}
但是,使用like %word%
效率很低,因为它无法使用索引。
答案 2 :(得分:0)
最后,我决定连接firstName和lastName。我排除了电子邮件,然后查询看起来像:
$busqueda = $_GET['search-customers'];
$names = explode(' ',$busqueda);
$hasemail = strpos('@', $busqueda);
if ( $hasemail ) {
$query->andWhere("c.email LIKE '%$busqueda%'");
} else {
$query->andWhere("( CONCAT(c.firstName,' ',c.lastName) LIKE '%$busqueda%' OR c.email LIKE '%$busqueda%')");
}
答案 3 :(得分:0)
在您的存储库中,您可以执行以下操作:
yaml.Marshal
查询构建器能够生成可根据您的需求进行扩展的复杂查询