Laravel - Come cercare in base ai tag in Multi-to-Molte Relazione polimorfica?
-
21-12-2019 - |
Domanda
Ho un modulo configurato con un ingresso di testo e un ingresso multi-selezione. L'input multi-select ha un elenco di tag. I tag sono allestiti come una relazione polimorfica a molti-a molti. Per aiutare a rendere le cose chiare, sotto è un contorno delle mie tabelle e dei miei modelli:
Tabelle:
org
id - integer
name - text
...
tags
id - integer
name - text
taggables
tag_id - integer
taggable_id - integer
taggable_type - text
.
Modelli:
class Org extends Eloquent
{
...
public function tags()
{
return $this->morphToMany('Tag', 'taggable');
}
}
class Tag extends Eloquent
{
...
public function org()
{
return $this->morphedByMany('Org', 'taggable');
}
}
.
Nel mio file PHORES.php, sto cercando di eseguire una ricerca come ...
$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();
.
Tuttavia, questo ovviamente non funziona. La ricerca della parola chiave funziona bene, ma non sono sicuro di come aggiungere una query che recupera solo le righe che hanno i tag associati specificati. La variabile $ tag è un array contenente gli ID dei tag.
Voglio restituire solo le righe dalla tabella Org che ha almeno uno dei tag specificati nell'array.
Aggiornamento: Ho aggiornato il mio codice, e il tipo di opere, ma sembra restituire tag e non le organizzazioni associate - anche se sento che mi sto avvicinando. Ecco il codice pertinente che ho aggiunto (o solo guardalo sopra):
$query
->join('taggables', 'taggables.taggable_id', '=', 'org.id')
->join('tags', 'taggables.tag_id', '=', 'tags.id')
->where('taggables.taggable_type', '=', 'Org')
->whereIn('tags.id', $tags);
.
Aggiornamento 2: Questo sembra funzionare come lo voglio, ma per qualche ragione, recupera il nome del tag anziché il nome dell'organizzazione ...
$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);
}
. Soluzione
Ho ricevuto la parola chiave + tag ricerca che funziona nel modo seguente:
$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 una parola chiave e due tag sono inseriti per la ricerca (ad esempio), questo restituirà tali organizzazioni che hanno uno o più tag, contengono parole che sono come la parola chiave inserita e ordinare i risultati in modo che le organizzazioni conI tag più corrispondenti appariranno prima.