简体   繁体   English

Laravel-如何基于多对多态关系中的标签进行搜索?

[英]Laravel - How to search based on tags in many-to-many polymorphic relation?

I have a form set up with a text input and a multi-select input. 我有一个设置为文本输入和多选输入的表单。 The multi-select input has a list of tags. 多选输入具有标签列表。 The tags are set up as a many-to-many polymorphic relation. 标签设置为多对多态关系。 To help make things clear, below is an outline of my tables and models: 为了使事情更清楚,下面是我的表和模型的概述:

Tables: 表:

org
   id - integer
   name - text
   ...

tags
   id - integer
   name - text

taggables
   tag_id - integer
   taggable_id - integer
   taggable_type - text

Models: 楷模:

class Org extends Eloquent
{
    ...

    public function tags()
    {
        return $this->morphToMany('Tag', 'taggable');
    }
}


class Tag extends Eloquent
{
    ...

    public function org() 
    {
        return $this->morphedByMany('Org', 'taggable');
    }
}

In my routes.php file, I am trying to perform a search like so... 在我的routes.php文件中,我试图像这样执行搜索...

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

However, this of course doesn't work. 但是,这当然不起作用。 The keyword search works fine, but I am not sure how to add a query that will retrieve only the rows that have the specified associated tags. 关键字搜索工作正常,但是我不确定如何添加查询以仅检索具有指定关联标签的行。 The $tags variable is an array containing the IDs of tags. $ tags变量是一个包含标签ID的数组。

I want to return only the rows from the org table that have at least one of the tags specified in the array. 我只想返回org表中具有至少一个在数组中指定的标签之一的行。

UPDATE: I have updated my code, and it kind of works, but it seems to return tags and not the associated organizations - though I feel I'm getting close. 更新:我已经更新了我的代码,并且可以正常工作,但是它似乎返回标签,而不返回相关的组织,尽管我觉得我已经接近了。 Here is the relevant code I added (or just look at it above): 这是我添加的相关代码(或仅在上面查看):

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

UPDATE 2: This seems to work how I want it, but for some reason, it retrieves the name of the tag instead of the organization name... 更新2:这似乎可以按我的意愿工作,但是由于某种原因,它检索标记的名称而不是组织名称...

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

I got the keyword + tag search working in the following way: 我通过以下方式获得了关键字+标签搜索:

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

If a keyword and two tags are entered for the search (for example), this will return those organizations which have one or more of the tags, contain words which are like the entered keyword, and sort the results so that organizations with the most matching tags will appear first. 如果输入了一个关键词和两个标签进行搜索(例如),这将返回具有一个或多个标签,包含与输入的关键词相似的词的组织,并对结果进行排序,以使匹配度最高的组织标签将首先显示。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM