laravel基于数组匹配值排序eloquent集合

时间:2015-03-09 20:55:41

标签: php laravel

我正在尝试构建项目推荐系统,其中用户和项目需要技能标签。我尝试根据每个技能数组中匹配的技能数量为用户生成和排序推荐项目的集合,例如,与用户技能匹配技能最匹配的项目将首先出现在列表中推荐项目。

到目前为止,这是我的代码。

public function recommendedProjects()
{
    $projects = Project::all()->filter(function ($project) {

        foreach(unserialize($project->skills) as $projectSkill)
        {
            foreach(unserialize(Auth::user()->profile->skills) as $userSkill)
            {
                if($projectSkill === $userSkill)
                {
                    return true;
                }
            }
        }
    });

    return View::make('projects.projects')->with("title", "Recommended Projects")->with('projects', $projects);
}

到目前为止它有点有效,但只返回至少有一项匹配技能的项目。

如果我可以将结果数限制在最相关的20个项目左右,也会有所帮助。

感谢任何帮助,这是我的第一个Laravel项目。

修改

我将代码更改为在自己的表中存储技能而不是使用序列化,现在它返回所有具有至少一个匹配用户技能的项目。

我想对项目进行排序,以便首先显示与用户技能最匹配技能的项目。

例如,如果一个项目有3个必需的技能,用户拥有所有3个技能,那么该项目将首先出现在具有较少匹配技能的项目上。

这是我更新的代码

  $projects = Project::all()->filter(function ($project) {

            foreach ($project->skills as $projectSkill) {
                foreach (Auth::user()->skills as $userSkill) {
                    if ($projectSkill->name === $userSkill->name) {
                        return true;
                    }
                }
            }

    });

1 个答案:

答案 0 :(得分:2)

您只需要对您拥有的项目集合进行排序。试试这个:

$userSkills = Auth::user()->skills;

$projects = Projects::with('skills')->get();

$projects->sort(function($a, $b) use ($userSkills) {
    // Get the matching skills from both A and B
    $aMatchingSkills = $a->skills->intersect($userSkills);
    $bMatchingSkills = $b->skills->intersect($userSkills);

    // Return the count of A minus the count of B - See PHP uasort
    return $aMatchingSkills->count() - $bMatchingSkills->count();
});

这非常广泛地使用了雄辩的收集对象(sortintersectcount)。 sort使用PHP中一个非常有用的函数 - uasort

要删除没有匹配技能的项目,请尝试将Projects::with('skills')->get();位替换为...

Projects::with(['skills' => function($q) use ($userSkills) {
    $q->whereIn('name', $userSkills->fetch('name'));
}])->get();

现在变得有点复杂,我不能保证我发布的内容会起作用,但它很接近。