You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel Eloquent条件查询及关联加载:社交网站用户关系获取

Solution for Laravel Eloquent Query with Dynamic Relationship Loading

Got it, let's break this down into actionable steps to get exactly what you need. You want to fetch relationship records where the current user is either the sender (from_id) or receiver (to_id), filter by a specific status, and eager load the corresponding user details based on which side the current user is on. Here's how to implement it:

Step 1: Define Relationships in Your Model

First, let's assume your relationship table corresponds to a Friendship model (rename this if your model has a different name). Add these two belongsTo relationships to link to the User model:

// app/Models/Friendship.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Friendship extends Model
{
    protected $fillable = ['from_id', 'to_id', 'status'];

    // Relationship to the user who sent the request
    public function sender(): BelongsTo
    {
        return $this->belongsTo(User::class, 'from_id');
    }

    // Relationship to the user who received the request
    public function receiver(): BelongsTo
    {
        return $this->belongsTo(User::class, 'to_id');
    }

    // Optional: Add a dynamic attribute to get the "friend" user directly
    public function getFriendAttribute()
    {
        return $this->from_id === auth()->id() 
            ? $this->receiver 
            : $this->sender;
    }
}

The getFriendAttribute dynamic attribute is a nice touch—it lets you access the corresponding friend user directly via $friendship->friend, no extra logic needed later.

Step 2: Build the Eloquent Query

Now, let's construct the query to filter by status, include the current user as either sender or receiver, and eager load the necessary user details:

use Illuminate\Support\Facades\Auth;
use App\Models\Friendship;

// Replace with your desired status (e.g., 'Accepted', 'Sent')
$targetStatus = 'Accepted';

$friendships = Friendship::where('status', $targetStatus)
    // Critical: Wrap the OR conditions in a closure to avoid logic errors
    ->where(function ($query) {
        $query->where('from_id', Auth::id())
              ->orWhere('to_id', Auth::id());
    })
    // Eager load both sender and receiver (we'll pick the right one via the dynamic attribute)
    ->with(['sender' => function ($query) {
        // Only select the user fields you need to optimize performance
        $query->select('id', 'name', 'email', 'avatar');
    }, 'receiver' => function ($query) {
        $query->select('id', 'name', 'email', 'avatar');
    }])
    ->get();

How It Works:

  1. Status Filter: We first narrow down records to only those with your specified status.
  2. User Check: The closure around from_id/to_id ensures we're only fetching records where the current user is part of the relationship—this is critical because without the closure, the OR condition would break the status filter.
  3. Eager Loading: We preload both sender and receiver to avoid N+1 database queries. Using a closure in with() lets us select only the user fields we actually need, which boosts performance.
  4. Accessing the Friend: Thanks to the dynamic friend attribute, you can loop through the results and get the corresponding user easily:
    foreach ($friendships as $friendship) {
        // Get the friend's details
        $friendName = $friendship->friend->name;
        $friendEmail = $friendship->friend->email;
    }
    

Alternative: If You Don't Want the Dynamic Attribute

If you prefer not to use the dynamic attribute, you can transform the collection after fetching it:

$friendships = Friendship::where('status', $targetStatus)
    ->where(function ($query) {
        $query->where('from_id', Auth::id())
              ->orWhere('to_id', Auth::id());
    })
    ->with(['sender', 'receiver'])
    ->get()
    ->map(function ($friendship) {
        // Assign the correct user to a "friend" key
        $friendship->friend = $friendship->from_id === Auth::id() 
            ? $friendship->receiver 
            : $friendship->sender;
        
        // Optional: Remove unused relationships to clean up the data
        unset($friendship->sender, $friendship->receiver);
        
        return $friendship;
    });

This achieves the same result, just with an extra collection transformation step.

内容的提问来源于stack exchange,提问作者Atinder Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:16:11