To create a Laravel model relationship between `PromokitListing` and `PromokitReview` where each listing is associated with one randomly selected review, you can follow several approaches. However, doing this in a truly "Eloquent" way while ensuring performance and maintainability can be a bit tricky because Eloquent does not natively support randomizing related models directly in the relationship definition. Below are a few methods to achieve this: ### Method 1: Custom Attribute with Lazy Loading You can define a custom attribute in your `PromokitListing` model that fetches a random review when accessed. This method does not preload the review with the initial query, which means it could lead to the N+1 query problem if not handled correctly. ```php class PromokitListing extends Model { public function reviews() { return $this->hasMany(PromokitReview::class); } public function review() { return $this->reviews()->inRandomOrder()->first(); } } ``` **Usage:** ```php $listing = PromokitListing::find(1); $randomReview = $listing->review; // Fetches a random review ``` To handle multiple listings efficiently, you should use eager loading with a constraint. However, customizing the eager loading process to apply `inRandomOrder()` for each listing individually isn't straightforward in Eloquent. ### Method 2: Overriding Eager Loading Methods You can override the eager loading method to include a subquery that selects a random review for each listing. This is more complex but handles the N+1 issue effectively. ```php class PromokitListing extends Model { public function reviews() { return $this->hasMany(PromokitReview::class); } public function review() { // This relationship returns a "dummy" relation that is only valid when using with('review') return $this->hasOne(PromokitReview::class)->selectSub(function ($query) { $query->select('*') ->from('promokit_reviews') ->whereColumn('promokit_listing_id', 'promokit_listings.id') ->inRandomOrder() ->limit(1); }, 'promokit_reviews'); } } ``` **Usage:** ```php $listings = PromokitListing::with('review')->get(); // Each listing will come with one randomly selected review preloaded ``` ### Method 3: Using a View or Database Query Another approach is to handle this at the database level by creating a view that selects random reviews for each listing, or by writing a more complex query that you can call through a model method or a scope. **Database View Example:** 1. Create a database view that selects random reviews for each listing. 2. Query this view through a Laravel model. ```sql CREATE VIEW v_random_reviews AS SELECT *, ROW_NUMBER() OVER (PARTITION BY promokit_listing_id ORDER BY RAND()) as rn FROM promokit_reviews; ``` Then query this view from a model method: ```php class PromokitListing extends Model { public function randomReview() { return $this->hasOne(PromokitReview::class, 'promokit_listing_id', 'id') ->from('v_random_reviews') ->where('rn', 1); } } ``` **Usage:** ```php $listing = PromokitListing::with('randomReview')->find(1); ``` ### Conclusion Each method has its pros and cons: - **Method 1** is simple but can cause N+1 problems if not used carefully. - **Method 2** is more complex but handles large datasets more efficiently by avoiding N+1 issues. - **Method 3** offloads complexity to the database, which can be more efficient and easier to maintain depending on your familiarity with SQL and database performance optimizations. Choose the method that best fits your application's needs in terms of performance, maintainability, and complexity.