参数 #3 ($constraints) 必须是 Closure 类型,数组给定

Argument #3 ($constraints) must be of type Closure, array given

我正在尝试呈现来自用户的所有广告。用户在他的 table 中保存了纬度和经度,所以我想做的是过滤一些地方,这些地方将绘制该搜索区域中那些用户的 ads/posts(我正在使用 google 地图 api),但我不断收到此消息,我无法使用 Vue 呈现页面。

lluminate\Database\Eloquent\Builder::eagerLoadRelation(): Argument #3 ($constraints) must be of type Closure, array given,

我有广告和用户。一个用户包含一个地方的经纬度,这是我的模型(我把它缩短了):

class User extends Authenticatable {
protected $fillable = [ 'name', 'email', 'email_verified_at', 'password', 'address', 'lat', 'lng' 'published_ad_id' ];

public function ads(){
    return $this->hasMany("App\Models\Ad", "published_ad_id");
}
}

这是我的广告模型:

class Ad extends Model
{
    use HasFactory;
    protected $table = 'ads';
    protected $primaryKey = 'id';
    protected $fillable = ['user_id','title', 'description', 'image', 'music_genre'];
//    protected $guarded = ['created_at', 'updated_at', 'availabilities_id'];
    public function user()
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    public function availability()
    {
        return $this->hasOne(Availability::class , 'availabilities_id');
    }
}

这将是我的控制器:

class AnuncioController extends Controller
{

    public function index(Request $request)
    {
        //        $anuncios = Ad::query();
        $userLocationLat = $request->input('lat');
        $userLocationLng = $request->input('lng');
        $distance = $request->input('distance');

        $nearestUsers = [];

        foreach (User::all() as $users){
            $distanceBetweenLocations = $this->getDistance($users->lat, $users->lng, $userLocationLat, $userLocationLng);
            if ($distanceBetweenLocations <= $distance ){
                $nearestUsers[] = $users;
            }
//            elseif ($userLocationLat == null){
//                $nearestUsers[] = $users;
//            }
        }


$anuncios = Ad::with(['user'=>$nearestUsers])->latest()->paginate(5)->withQueryString();

         return Inertia::render('Anuncio/Index', compact('anuncios')
        );
    }


 private function getDistance($point1_lat, $point1_long, $point2_lat, $point2_long, $unit = 'km', $decimals = 2) {
        // Calculate the distance in degrees
        $degrees = rad2deg(acos((sin(deg2rad($point1_lat))*sin(deg2rad($point2_lat))) + (cos(deg2rad($point1_lat))*cos(deg2rad($point2_lat))*cos(deg2rad($point1_long-$point2_long)))));

        // Convert the distance in degrees to the chosen unit (kilometres, miles or nautical miles)
        switch($unit) {
            case 'km':
                $distance = $degrees * 111.13384; // 1 degree = 111.13384 km, based on the average diameter of the Earth (12,735 km)
                break;
            case 'mi':
                $distance = $degrees * 69.05482; // 1 degree = 69.05482 miles, based on the average diameter of the Earth (7,913.1 miles)
                break;
            case 'nmi':
                $distance =  $degrees * 59.97662; // 1 degree = 59.97662 nautic miles, based on the average diameter of the Earth (6,876.3 nautical miles)
        }
        return round($distance, $decimals);
    }
    }

如您所见,我正在尝试传递用户数组,以便我可以在前面的部分使用它,但没有用。

在前面我有这个vue.js:

<template>
    <AppLayout>
        <h1>HOLA</h1>
        <div v-for="anuncio in anuncios" :key="anuncio.id" class="max-w-sm rounded overflow-hidden shadow-lg">

            <div class="px-6 py-4">
                <div class="font-bold text-xl mb-2">{{ anuncio.title }}</div>
                <p class="text-gray-700 text-base">
                    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptatibus quia, nulla! Maiores et perferendis eaque, exercitationem praesentium nihil.
                </p>
                <p>
                    {{anuncio.description}} 
                </p>
                <p>
                    {{ anuncio.user.name}} 
                </p>
            </div>
            <div class="px-6 pt-4 pb-2">
                <span class="inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2">#photography</span>
                <span class="inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2">#travel</span>
                <span class="inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2">#winter</span>
            </div>
        </div>
    </AppLayout>

</template>

<script>
import AppLayout from "../../Layouts/AppLayout";
export default {
    name: "index",
    // props: ['restaurants'],
    props: {
      anuncios: Object
    },
    components: {AppLayout}
}
</script>

<style scoped>

</style>

我认为问题出在控制器以及我如何将数据传递给 Ads,但我找不到哪里做错了或如何获取该数组。

你应该使用闭包作为值并在里面过滤。

$anuncios = Ad
    ::with([
        'user' => function ($query) use ($nearestUsers) {
            $query->whereIn('id', $nearestUsers)
        }
    ])
    ->latest()
    ->paginate(5)
    ->withQueryString();

尝试将所有用户 ID 收集到 $nearestUsers 数组,并使用该数组过滤广告。 像这样,

        foreach (User::all() as $users){
            $distanceBetweenLocations = $this->getDistance($users->lat, $users->lng, $userLocationLat, $userLocationLng);
            if ($distanceBetweenLocations <= $distance ){
                $nearestUsers[] = $users->id;
            }
        }

        $anuncios = Ad::with(['user'])->whereIn('user_id', $nearestUsers)->latest()->paginate(5)->withQueryString();