What you want is to write an advanced query to search product based on related models too, so as previous suggestion by others, you have to write join statements.
Check my example code below, which is written to search members, the search string also will bring members if the string matches, members skills or positions, so this will surely help you.
$users = User::select('app_users.*')
->distinct()
->join('app_members', 'app_users.id', '=', 'app_members.app_users_id')
->leftJoin('app_members_jobtitles', 'app_members.id', '=', 'app_members_jobtitles.app_members_id')
->leftJoin('app_jobtitles', 'app_members_jobtitles.app_jobtitles_id', '=', 'app_jobtitles.id')
->leftJoin('app_members_tags', 'app_members.id', '=', 'app_members_tags.app_members_id')
->leftJoin('app_technologies', 'app_members_tags.app_technologies_id', '=', 'app_technologies.id')
->whereNull('app_users.activation')
->where('app_users.block','=',0)
->where(function ($query)use ($search) {
$query->orWhere('app_users.first_name', 'like', '%'.$search.'%')
->orWhere('app_users.last_name', 'like', '%'.$search.'%')
->orWhere('app_members.company', 'like', '%'.$search.'%')
->orWhere('app_members.job_title', 'like', '%'.$search.'%')
->orWhere('app_jobtitles.title', 'like', '%'.$search.'%')
->orWhere('app_technologies.title', 'like', '%'.$search.'%')
->orWhere('app_members.summary', 'like', '%'.$search.'%');
})
->get();
Note the following join in the above code, which is in your case category and sub category
->leftJoin('app_members_jobtitles', 'app_members.id', '=', 'app_members_jobtitles.app_members_id')
->leftJoin('app_jobtitles', 'app_members_jobtitles.app_jobtitles_id', '=', 'app_jobtitles.id')