【问题标题】:Laravel: How to search child relationshipLaravel:如何搜索子关系
【发布时间】:2014-07-27 22:58:54
【问题描述】:

我觉得这可能是一个简单的问题;但我一辈子都无法弄清楚这一点。我对 Laravel 比较陌生,所以请耐心等待。 (我已经倾注了试图找到这个的文档)

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

Membership hasMany Members Members belongsTo Membership

在构建搜索时,我成功地搜索了会员,但我意识到我需要在显示结果时在会员中设置过期字段。我目前正在使用 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);
}

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

提前致谢!

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

【问题讨论】:

    标签: php laravel-4 eloquent


    【解决方案1】:

    您为此使用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 建立一个连接。就像我说的,重构它并提取代码,这样你就可以在不同的关系中使用它,它看起来不会那么混乱。

    【讨论】:

    • 这是一种使用whereHas()方法在子模型中搜索数据的神奇方法,如何同时搜索父模型?例如,如果成员有一个父模型说Country,那么我如何搜索属于问题中提到的其他搜索字段的搜索国家的成员?
    猜你喜欢
    • 2015-10-30
    • 2015-06-11
    • 1970-01-01
    • 2018-11-09
    • 1970-01-01
    • 2019-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多