To achieve the desired functionality using Eloquent in Laravel, you can utilize eager loading with constraints and join clauses to maintain the sort order from the pivot table. Here's how you can modify your Eloquent query to include the sort order from the category_post pivot table while fetching posts assigned to subcategories of a given category.
use App\Models\Post;
use Illuminate\Support\Facades\DB;
// Assuming $categoryId is the ID of the main category
$posts = Post::query()
->select('posts.*')
->join('category_post', 'posts.id', '=', 'category_post.post_id')
->join('categories as sub_categories', 'category_post.category_id', '=', 'sub_categories.id')
->where('sub_categories.parent_id', $categoryId)
->where('posts.status', 'published')
->orderBy('category_post.sort_order', 'DESC')
->orderBy('posts.search_rank', 'DESC')
->orderBy('posts.published_at', 'DESC')
->orderBy('posts.title', 'ASC')
->get();
// The posts are now loaded in the correct order, and are Eloquent models.
Explanation:
-
Selecting Posts: The
select('posts.*')ensures that only the columns from thepoststable are included in the final result set, avoiding any ambiguity in column names when joining tables. -
Join Operations:
- The first join connects
postswith thecategory_postpivot table on the post ID. - The second join connects the
category_posttable to thecategoriestable (aliased assub_categories) on the category ID.
- The first join connects
-
Filtering:
- The
where('sub_categories.parent_id', $categoryId)clause filters categories to include only those that are subcategories of the specified parent category. - The
where('posts.status', 'published')ensures that only posts with a status of 'published' are included.
- The
-
Ordering: The
orderByclauses ensure that the results are ordered first by thesort_orderin the pivot table, then bysearch_rank,published_at, andtitleof the posts.
This approach should give you the desired posts, correctly ordered, and as Eloquent models, allowing you to utilize all Eloquent features on the results.