Мне нужен массив с категориями, в каждой категории по 4 поста: массив с двумя постами с type_1 и массив с двумя постами с type_2. Без типа_3.
Дисплей должен выглядеть так (без использования лезвия):
category name_1
post type_1 name
post type_1 name
post type_2 name
post type_2 name
category name_2
post type_1 name
post type_1 name
post type_2 name
post type_2 name
post_table:
$table->enum('type', ['type_1', 'type_2', 'type_3'])->default('type_1');
$table->unsignedBigInteger('category_id')->index();
$table->foreign('category_id')->references('id')->on('categories');
категории_таблица:
$table->string('name');
Модель категории:
return $this->hasMany('App\Models\Post');
Почтовая модель:
return $this->belongsTo('App\Models\Category');
Я пытался:
$categories = ['category_1', 'category_2'];
foreach ($categories as $cat) {
$postsType1[$cat->name] = $cat->posts()->where('type', 'type_1')->latest()->limit(2)->get();
$postsType2[$cat->name] = $cat->posts()->where('type', 'type_2')->latest()->limit(2)->get();
}
Но это два отдельных массива в категориях. Мне нужен один массив категорий с двумя сообщениями каждого типа.
🤔 А знаете ли вы, что...
С PHP можно создавать красивые и функциональные графики с помощью библиотеки GD.
Вы можете использовать коллекцию groupBy()
с несколькими условиями
$posts = Post::query()
->latest()
->get()
->groupBy([
function($post) {
return $post->category->name;
},
function($post) {
return $post->type;
},
])
->map(function($records, $category) {
return $records->sortKeys()->map(function($rows, $type){
return $rows->take(2)->all();
});
})
->all();
И если вы хотите просто сгруппировать по названию категории и отсортировать по типу сообщения
$posts = Post::get()
->group(function($post){
return $post->category->name;
})
-> map(function($value, $key){
return $value->sortBy('type')->sortByDesc('created_at')->take(2);
})
->all();
ОБНОВЛЯТЬ Чтобы избежать получения всех записей Post без каких-либо ограничений, другим вариантом будет:
//in migration file for the posts table
$table->index(['type', 'category_id']);
class Category extends Model
{
public function type1News()
{
return $this->hasMany(Post::class)->where('type', 'type_1')->latest();
}
public function type2News()
{
return $this->hasMany(Post::class)->where('type', 'type_2')->latest();
}
public function type3News()
{
return $this->hasMany(Post::class)->where('type', 'type_3')->latest();
}
}
Затем, чтобы получить данные
$categories = Cache::remember('categoriesWithLatestNews', 3600, function() {
$cats = Category::get();
$cats->each->load([
'type1News' => function($query){
return $query->take(2);
},
'type2News' => function($query){
return $query->take(2);
},
'type3News' => function($query){
return $query->take(2);
}
]);
return $cats;
});
С 1 миллионом записей в таблице сообщений время отклика впервые составило 2,75 секунды. (Без составного индекса время отклика превышает 120 с.)
Затем после того, как он кэшируется в течение указанных секунд, поэтому время отклика находится в мс.
Хотя этот подход требует нескольких запросов к базе данных, всего 31 запрос (10 записей категорий): 1 для получения всех категорий, а затем 3 для каждой категории для получения отношений.