使用 hasMany 时出错。我得到不相关的对象

Error when use hasMany. I get non related objects

用户关系:

public function events() {
     return $this->hasMany('Events', 'user_id');
}

事件关系:

public function user() {
     return $this->belongsTo('User');
}

我想获取当前月份的所有事件,除了今天的事件,所以我使用:

$pets= Auth::user()->events()
       ->where(function($query) use($myYear, $myMonth, $myDay) {
           $query->whereYear('start_date', '=', $myYear);
           $query->whereMonth('start_date', '=', $myMonth);
           $query->whereDay('start_date', '!=', $myDay);
       })->orWhere(function($query) use($myYear, $myMonth, $myDay)     {
           $query->whereYear('end_date', '=', $myYear);
           $query->whereMonth('end_date', '=', $myMonth);
           $query->whereDay('end_date', '!=', $myDay);
       })->get();

但这会检索所有用户的所有 events。我需要在-get()之前添加->where("user_id", Auth::user()->id),我不知道为什么。

谁能帮我解决这个问题?

您没有保留 $query 的引用以传递闭包,请这样尝试。

   $query = Auth::user()->events();
   $query->where(function($query) use($myYear, $myMonth, $myDay) {
       $query->whereYear('start_date', '=', $myYear);
       $query->whereMonth('start_date', '=', $myMonth);
       $query->whereDay('start_date', '!=', $myDay);
   });
   $query->orWhere(function($query) use($myYear, $myMonth, $myDay) {
       $query->whereYear('end_date', '=', $myYear);
       $query->whereMonth('end_date', '=', $myMonth);
       $query->whereDay('end_date', '!=', $myDay);
   })
   $pets = $query->get();

如何解决:在 mySQL 中(如果是 Lavavel,我假设您正在使用)只需打开 "general log"。这是关于如何做到这一点的相当不错的 Whosebug:How to enable MySQL Query Log?

这将记录对 MySQL 的所有调用,您将能够看到构造。


接下来是猜测:您可能会发现查询最终为:

SELECT events FROM events
    WHERE
      userID = :userID 
      AND (not start date)
      OR (not end date)

因为 AND 的计算优先级更高 (http://dev.mysql.com/doc/refman/5.7/en/operator-precedence.html) 这与

相同
SELECT events FROM events
    WHERE
      (
         userID = :userID 
         AND
         (not start date)
      )
      OR
      (not end date)

因此将包括第二个查询中的任何人,而不仅仅是用户。

但是你需要的是

SELECT events FROM events
    WHERE
      userID = :userID 
      AND
      (
          (not start date)
              OR
          (not end date)
      )

你如何 "fixed" 它,但通过在末尾添加额外的 "AND",你得到

SELECT events FROM events
    WHERE
      userID = :userID 
      AND (not start date)
      OR (not end date)
      AND userID = :userID

相同
SELECT events FROM events
    WHERE
      (
         userID = :userID 
         AND
         (not start date)
      )
      OR
      (
         (not end date)
         AND
         userID = :userID 
      )

以迂回的方式做你想做的事...

问题出在您的 or 语句上。您的查询当前如下所示:

where relationship_condition AND start_date_condition OR end_date_condition

在操作的逻辑顺序中,ANDs 在 ORs 之前执行,所以这等同于:

where (relationship_condition AND start_date_condition) OR end_date_condition

这意味着任何与您的 end_date_condition 匹配的记录都将被返回,无论它们是否与 relationship_condition 匹配。为了纠正这个问题,您需要正确分组您的 OR 条件,因此它看起来像这样:

where relationship_condition AND (start_date_condition OR end_date_condition)

因此,您的代码应如下所示:

$pets= Auth::user()->events()
    ->where(function ($query) use ($myYear, $myMonth, $myDay) {
        return $query
            ->where(function ($query) use ($myYear, $myMonth, $myDay) {
                return $query
                    ->whereYear('start_date', '=', $myYear)
                    ->whereMonth('start_date', '=', $myMonth)
                    ->whereDay('start_date', '!=', $myDay);
            })
            ->orWhere(function ($query) use($myYear, $myMonth, $myDay) {
                return $query
                    ->whereYear('end_date', '=', $myYear)
                    ->whereMonth('end_date', '=', $myMonth)
                    ->whereDay('end_date', '!=', $myDay);
            });
    })
    ->get();