Laravel - Como a pesquisa com base em tags em muitos-para-muitos polimórficos relação?
-
21-12-2019 - |
Pergunta
Eu tenho um formulário com uma entrada de texto e um multi-selecione a entrada.O multi-selecione a entrada tem uma lista de tags.As tags são definidas como uma relação muitos-para-muitos polimórficos relação.Para ajudar a tornar as coisas claras, abaixo está um esboço do meu tabelas e modelos:
Tabelas:
org
id - integer
name - text
...
tags
id - integer
name - text
taggables
tag_id - integer
taggable_id - integer
taggable_type - text
Modelos:
class Org extends Eloquent
{
...
public function tags()
{
return $this->morphToMany('Tag', 'taggable');
}
}
class Tag extends Eloquent
{
...
public function org()
{
return $this->morphedByMany('Org', 'taggable');
}
}
No meu routes.php arquivo, eu estou tentando realizar uma pesquisa como assim...
$search = Input::get('keyword');
$searchTerms = explode(' ', $search);
$query = Org::query();
$fields = array('name', 'description', 'additional_info', 'website');
foreach ($searchTerms as $term)
{
foreach ($fields as $field)
{
$query->orWhere($field, 'LIKE', '%'. $term .'%');
}
}
if(Input::get('tags'))
{
$tags = Input::get('tags');
$query
->join('taggables', 'taggables.taggable_id', '=', 'org.id')
->where('taggables.taggable_type', '=', 'Org')
->join('tags', 'taggables.tag_id', '=', 'tags.id')
->groupBy('org.id');
foreach ($tags as $tag)
{
$query->orWhere('tags.id', '=', $tag);
}
}
$org = $query->get();
No entanto, isso, claro, não funciona.A palavra-chave de pesquisa funciona bem, mas eu não tenho certeza de como adicionar uma consulta para recuperar somente as linhas que tem especificado tags associadas.O $marcas variável é um array contendo os IDs de tags.
Quero voltar somente as linhas do organograma tabela que tem, pelo menos, uma das marcas especificadas na matriz.
ATUALIZAÇÃO: Eu atualizei o meu código, e que tipo de obras, mas parece retornar marcas e não as organizações associadas, embora eu sinto que estou chegando perto.Aqui está o código relevante eu adicionados (ou apenas olhar para ele acima):
$query
->join('taggables', 'taggables.taggable_id', '=', 'org.id')
->join('tags', 'taggables.tag_id', '=', 'tags.id')
->where('taggables.taggable_type', '=', 'Org')
->whereIn('tags.id', $tags);
ATUALIZAÇÃO 2: Isso parece funcionar como eu quero, mas por algum motivo, ele recupera o nome da tag em vez do nome da organização...
$tags = Input::get('tags');
$query
->join('taggables', 'taggables.taggable_id', '=', 'org.id')
->where('taggables.taggable_type', '=', 'Org')
->join('tags', 'taggables.tag_id', '=', 'tags.id')
->groupBy('org.id');
foreach ($tags as $tag)
{
$query->orWhere('tags.id', '=', $tag);
}
Solução
Eu tenho a palavra-chave + tag de pesquisa de trabalho da seguinte forma:
$query = Org::query();
// Search by keyword(s)
if(Input::get('keyword'))
{
$search = Input::get('keyword');
$searchTerms = explode(' ', $search);
$fields = array('org.name', 'org.description', 'org.additional_info', 'org.website');
foreach ($searchTerms as $term)
{
foreach ($fields as $field)
{
$query->orWhere($field, 'LIKE', '%'. $term .'%');
}
}
}
// Search for tag(s)
if(Input::get('tags'))
{
$tags = Input::get('tags');
$query
->join('taggables', 'taggables.taggable_id', '=', 'org.id')
->where('taggables.taggable_type', '=', 'Org')
->whereIn('taggables.tag_id', $tags)
->groupBy('org.id')
->orderBy(DB::raw('count(*)'), 'desc')
->orderBy('name', 'asc');
}
$org = $query->get();
Se uma palavra-chave e duas tags são introduzidas para a pesquisa (por exemplo), isso irá retornar as organizações que tenham um ou mais dos tags, contêm palavras que são como a inserção de palavra-chave, e classificar os resultados de forma que as organizações com mais de correspondência tags aparecem em primeiro lugar.