Level 122
indexing
Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.
After I checked mysql-slow.log, the results returned from the queries due to this controller are very slow (average takes about 58 seconds for a query). Please help me optimize these queries. The dev team has abandoned my project without support anymore, I'm really stuck.
public function topFavorite(Request $request)
{
$stories = Story::select(['id', 'name', 'slug', 'source_id', 'status', 'author_id', 'total_words', 'view', 'cover', 'desc'])
->with('author:id,name,slug')
->withCount(['chapters' => function ($query) {
$query->whereDate('publish_at', '<=', Carbon::now());
}])
->with('source:id,name,slug')->display()->get();
$stories = $stories->sortByDesc('favorite')->values()->all();
$currentPage = $request->page ?? 0;
$perPage = $request->per_page ?? AppConst::DEFAULT_PER_PAGE;
$currentItems = array_slice($stories, $perPage * ($currentPage - 1), $perPage);
$storiesPaginated = new LengthAwarePaginator($currentItems, count($stories), $perPage, $currentPage);
return response()->json($storiesPaginated);
}
public function recommendedNewestStories(Request $request)
{
$stories = Story::select(['id', 'name', 'slug', 'source_id', 'status', 'author_id', 'total_words', 'view', 'cover', 'desc'])->where('newest', true)
->with('author:id,name,slug')
->withCount(['chapters' => function ($query) {
$query->whereDate('publish_at', '<=', Carbon::now());
}])
->with('source:id,name,slug')->display()
->orderBy('created_at', 'desc')
->paginate($request->per_page ?? AppConst::DEFAULT_PER_PAGE);
return response()->json($stories);
}
// top story has most chapters in the month
public function hasMostChaptersPm(Request $request)
{
$stories = Story::select(['id', 'name', 'slug', 'source_id', 'status', 'author_id', 'total_words', 'view', 'cover', 'desc'])->withCount(['chapters' => function ($query) {
$query->whereDate('publish_at', '<=', Carbon::now()->whereDate('created_at', '>=', Carbon::now()->subMonth()));
}])
->with('author:id,name,slug')
->with('source:id,name,slug')->display()
->orderBy('chapters_count', 'desc')
->paginate($request->per_page ?? AppConst::DEFAULT_PER_PAGE);
return response()->json($stories);
}
// top story has most purchases in week
public function topStoryPurchases(Request $request)
{
$stories = [];
if(!Cache::has('topStoryInWeek_'.$request->page)){
$perPage = $request->per_page ?? AppConst::DEFAULT_PER_PAGE;
$results = Story::select(['id', 'name', 'slug', 'source_id', 'status', 'author_id', 'total_words', 'view', 'cover', 'desc'])->has('transactions')->withCount(['transactions' => function ($query) {
$query->where('created_at', '>=', Carbon::now()->subWeek());
}])
->with('author:id,name,slug')
->withCount(['chapters' => function ($query) {
$query->whereDate('publish_at', '<=', Carbon::now());
}])
->with('source:id,name,slug')->display()
->orderBy('transactions_count', 'desc')->take($perPage*5)->get();
// ->paginate($request->per_page ?? AppConst::DEFAULT_PER_PAGE);
$offset = 0;
for($i=1; $i<=5; $i++){
Cache::put('topStoryInWeek_'.$i, $results->slice($offset, $request->per_page), 4*3600);
$offset += $request->per_page;
}
$stories = Cache::get('topStoryInWeek_'.$request->page);
}
else{
$stories = Cache::get('topStoryInWeek_'.$request->page);
}
return response()->json($stories);
}
// Story newest
public function stNewest(Request $request)
{
// Story newest
$stories = Story::select(['id', 'name', 'slug', 'source_id', 'status', 'author_id', 'total_words', 'view', 'cover', 'desc'])->with('author:id,name,slug')->withCount(['chapters' => function ($query) {
$query->whereDate('publish_at', '<=', Carbon::now());
}])->with('source:id,name,slug')->display()
->orderBy('created_at', 'DESC')
->paginate($request->per_page ?? AppConst::DEFAULT_PER_PAGE);
return response()->json($stories);
}
// Story by source
public function stBySource(Request $request, Source $source)
{
$storiesQuery = Story::query();
if ($source->id == 1) {
$storiesQuery->withCount('transactions')->orderBy('transactions_count', 'desc');
} else {
$storiesQuery->orderBy('view', 'desc');
}
$stories = $storiesQuery->where('source_id', $source->id)
->with('author:id,name,slug')
->withCount(['chapters' => function ($query) {
$query->whereDate('publish_at', '<=', Carbon::now());
}])
->with('source:id,name,slug')
->display()
->paginate($request->per_page ?? AppConst::DEFAULT_PER_PAGE, ['id', 'name', 'slug', 'source_id', 'status', 'author_id', 'total_words', 'view', 'cover', 'desc']);
return response()->json($stories);
}
//story completed
public function stCompleted(Request $request)
{
$stories = Story::select(['id', 'name', 'slug', 'source_id', 'status', 'author_id', 'total_words', 'view', 'cover', 'desc'])->where('status', true)->with('categories:id,name,slug')
->with('author:id,name,slug')->withCount(['chapters' => function ($query) {
$query->whereDate('publish_at', '<=', Carbon::now());
}])->display()
->with('source:id,name,slug')->orderBy('updated_at', 'desc')->paginate($request->per_page ?? AppConst::DEFAULT_PER_PAGE);
return response()->json($stories);
}
// Story suggestion
public function stSuggestion(Request $request, Story $story)
{
$categories = $story->categories;
$categories = $categories->map(function ($item) {
return $item->id;
});
$stories = Story::select(['id', 'name', 'slug', 'source_id', 'status', 'author_id', 'total_words', 'view', 'cover', 'desc'])->with('author:id,name,slug')->withCount('transactions')
->display()
->orderBy('transactions_count', 'desc')->whereHas('categories', function (Builder $query) use ($categories) {
$query->whereIn('category_id', $categories);
})->take(10)->get();
return response()->json($stories);
}
// Story editor choice
public function stEditorChoice(Request $request)
{
// Story editor choice
$stories = Story::select(['id', 'name', 'slug', 'source_id', 'status', 'author_id', 'total_words', 'view', 'cover', 'desc', 'editor_choice'])->where('editor_choice', true)
->with('author:id,name,slug')
->with('source:id,name,slug')
->withCount(['chapters' => function ($query) {
$query->whereDate('publish_at', '<=', Carbon::now());
}])->display()
->paginate($request->per_page ?? AppConst::DEFAULT_PER_PAGE);
return response()->json($stories);
}
// Story hot
public function stHot(Request $request)
{
// Story hot
$stories = Story::select(['id', 'name', 'slug', 'source_id', 'status', 'author_id', 'total_words', 'view', 'cover', 'desc'])->has('transactions')->withCount('transactions')
->with('author:id,name,slug')
->with('source:id,name,slug')
->withCount(['chapters' => function ($query) {
$query->whereDate('publish_at', '<=', Carbon::now());
}])->display()
->orderBy('transactions_count', $request->order_by)
->paginate($request->per_page ?? AppConst::DEFAULT_PER_PAGE);
return response()->json($stories);
}
mysql-slow.log:
select `id`, `name`, `slug`, `source_id`, `status`, `author_id`, `total_words`, `view`, `cover`, `desc`, (select count(*) from `transactions` where `stories`.`id` = `transactions`.`story_id`) as `transactions_count` from `stories` where `display` = 1 and exists (select * from `categories` inner join `story_categories` on `categories`.`id` = `story_categories`.`category_id` where `stories`.`id` = `story_categories`.`story_id` and `category_id` in (3, 31, 33, 64)) order by `transactions_count` desc limit 10;
Please help me. Thank you so much everyone
Please or to participate in this conversation.