Laravel:如何搜索儿童关系

时间:2014-07-27 22:58:55

标签: php laravel-4 eloquent

我觉得这可能是一个简单的问题;但是,对于我的生活,我不能想到这一点。我对Laravel来说比较新,所以请耐心等待。 (而且我已经倾倒了试图找到这个的文档)

我有一个简单的一对多关系设置,一切都按预期工作。

会员资格有很多会员会员属于会员资格

在构建搜索时,我正在搜索会员取得巨大成功,但意识到我需要在显示结果时在会员资格中设置到期字段。我目前正在使用Members :: Query进行搜索。我的问题是,有没有办法从子关系中提取父信息而不必重写所有的搜索逻辑,并且(畏缩)必须提交单独的查询来拉取每个父记录?

这是相关代码:

会员资格模式

class Membership extends Eloquent {
    protected $table = 'memberships';
    protected $fillable = array('expires');

    public function members() {
        return $this->hasMany('Member');
    }
}

会员模型

class Member extends Eloquent {

    protected $table = 'members';
    protected $fillable = array('various','fields','here');

    public function membership() {
        return $this->belongsTo('Membership');
    }
}

搜索功能

public function searchMember()
{
    $search = Input::get('search');
    $searchTerms = explode(' ', $search);
    $query = Member::query();

    $fields = array('firstname', 'middlename', 'lastname', 'email', 'dlnumber', 'membership_id');

    foreach ($searchTerms as $term)
    {
        foreach ($fields as $field)
        {
            $query->orWhere($field, 'LIKE', '%'. $term .'%');
        }
    }

    $results = $query->paginate(10);
    return View::make('members.search')->with('results', $results);
}

如前所述,一切都按预期工作,我只需要从父成员资格关系中提取一个字段。

提前致谢!

编辑:在重新阅读我的问题之后,我还想指出这是应用程序中唯一没有使用Eloquent ORM和急切加载的地方。如果有一种方法我可以/应该利用这些,那将是最好的(imo)

1 个答案:

答案 0 :(得分:15)

您可以使用whereHas

Member::whereHas('membership', function ($q) {
   $q->where('expiration', 'like', 'somethingToSearchFor');
})->get();

在你的情况下:

注意:所有ifforeach和闭包都变得混乱,所以我不会这样做,而是适当地提取它。它只是一个如何构建查询的示例。

$fields = array('membership' => ['expiration'], 'firstname', 'middlename', 'lastname', 'email', 'dlnumber', 'membership_id');

// orWhereHas will use joins, so we'll start with fields foreach
foreach ($fields as $relation => $field)
{
  if (is_array($field))
  {
    // here we join table for each relation
    $query->orWhereHas($relation, function ($q) use ($field, $search) {

      // here we need to use nested where like: ... WHERE key = fk AND (x LIKE y OR z LIKE y)
      $q->where(function ($q) use ($field, $search) {
        foreach ($field as $relatedField)
        {
          foreach ($search as $term)
          {
            $q->orWhere($relatedField, 'like', "%{$term}%");
          } 
        } 
      });
    });
  } 
  else
  {
    foreach ($search as $term)
    {
      $query->orWhere($field, 'like', "%{$term}%"); 
    } 
  } 
}

上面我们重复了foreach ($search as $term)而不是将其放在顶部,因为每个$term$relation个最终都会有一个联接。就像我说的那样,重构它并提取代码,这样你可以用不同的关系来使用它,它看起来并不那么混乱。