Pregunta

Tengo una forma configurada con una entrada de texto y una entrada de selección múltiple. La entrada de selección múltiple tiene una lista de etiquetas. Las etiquetas se configuran como una relación polimórfica de muchos a muchos. Para ayudar a que las cosas se aclaren, a continuación hay un resumen de mis tablas y modelos:

Tablas:

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

En mi archivo rutas.php, estoy tratando de realizar una búsqueda así ...

$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();

Sin embargo, esto, por supuesto, no funciona. La búsqueda de palabras clave funciona bien, pero no estoy seguro de cómo agregar una consulta que solo recuperará las filas que tienen las etiquetas asociadas especificadas. La variable $ TAGS es una matriz que contiene las ID de las etiquetas.

Quiero devolver solo las filas de la tabla Org que tienen al menos una de las etiquetas especificadas en la matriz.

Actualizar: He actualizado mi código, y es un tipo de trabajo, pero parece devolver las etiquetas y no las organizaciones asociadas, aunque siento que me estoy acercando. Aquí está el código relevante que agregué (o simplemente lo mira arriba):

$query
    ->join('taggables', 'taggables.taggable_id', '=', 'org.id')
    ->join('tags', 'taggables.tag_id', '=', 'tags.id')
    ->where('taggables.taggable_type', '=', 'Org')
    ->whereIn('tags.id', $tags);

actualización 2: Esto parece funcionar cómo lo quiero, pero por alguna razón, recupera el nombre de la etiqueta en lugar del nombre de la organización ...

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

¿Fue útil?

Solución

Tengo la palabra clave + la búsqueda de etiquetas trabajando de la siguiente manera:

$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();

Si se ingresa una palabra clave y dos etiquetas para la búsqueda (por ejemplo), esto devolverá aquellas organizaciones que tienen una o más de las etiquetas, contienen palabras que son como la palabra clave ingresadas y ordenan los resultados para que las organizaciones conLas etiquetas más coincidentes aparecerán primero.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top