У меня много отношений между пользователями и достижениями. Расположение стола аналогично этому.
users
-id
-first_name
-last_name
-email
acheivements
-id
-type-name
-description
achievement_user
-id
-acievement_id
-user_id
-is_complete (boolean)
-percentage_complete (integer)
-completed_at
Я могу получить большую часть того, что мне нужно, например все достижения с type = badge для пользователя, которые находятся в сводной таблице. Я также могу получить список всех достижений, отмеченных значком type = badge. Там, где я застрял, я пытаюсь получить все достижения с помощью type = badge вместе с is_complete, percent_complete, completed_at для данного пользователя. Итак, если всего 8 значков, и они запустили 3 из них, я бы хотел вернуть 8 записей, где 3 из них будут иметь информацию из сводной таблицы. Я знаю, что могу взять все значки и пролистать их, чтобы добавить дополнительную информацию, но я знаю, что есть красноречивый способ, который будет проще.
Спасибо за любую помощь.






Вам нужно узнать о методе whereHas, который позволяет запрашивать отношения при получении результатов.
В модели пользователя
// создаем отношения достижений
public function achievements()
{
return $this->belongsToMany(Achievement::class)
->withPivot('is_complete', 'percentage_complete', 'completed_at');
}
// затем запросите его, как показано ниже.
$achievements= $user->achievements;
Узнать больше здесь
Спасибо, я разберусь в этом подробнее. То, что вы оставили здесь, похоже, получит информацию о пользователе и прикрепит все начатые достижения. Я хочу получить все достижения, а затем прикрепить любой прогресс, который есть у пользователя для каждого из них, даже если у них еще нет записей о прогрессе. Таким образом, я могу перечислить все значки и показать их прогресс, если таковой имеется.
По-прежнему получает только те, которые пользователь запустил или для которых есть запись в сводной таблице. Нужно получить все достижения и показать прогресс, даже если его нет. Идея состоит в том, чтобы они приземлились на странице достижений и увидели все доступные достижения, и любые, которые они начали, покажут их прогресс.
В отношениях belongsToMany используйте функцию withPivot следующим образом:
//in User model
public function acheivements()
{
return $this->belongsToMany('App\Acheivement')->withPivot('is_complete', 'percentage_complete', 'completed_at');
}
//in Acheivement model
public function users()
{
return $this->belongsToMany('App\User')->withPivot('is_complete', 'percentage_complete', 'completed_at');
}
Спасибо. Я сам дошел до этого, но снова не решаю, что пытаюсь сделать. Если у меня есть 3 достижения (id = 1, 2 и 3) в моей таблице достижений и в таблице achievement_user, у пользователя есть две записи, поскольку они начали или завершили 2 достижения (id = 1 и 2). Когда я вызываю user-> достижения, он вернет только 2 достижения. Я все еще хочу, чтобы он возвращал все 3 достижения, только поля withPivot будут пустыми или пустыми для достижения с id = 3. Надеюсь, что это имеет смысл.
Вы имеете в виду, что предоставленный мной код этого не делает? Тогда любезно объясните дальше.
Если у меня есть 4 записи в таблице достижений, и у меня есть 3 записи для пользователя в таблице achievement_user, поскольку они начали 3 из достижений. Когда я вызываю $ user-> достижения, я получаю только 3 достижения, которые они начали. Я пытаюсь получить все достижения, поэтому в этом случае мне нужны все 4 достижения, а затем пользователи прогрессируют, даже если нет прогресса. Идея состоит в том, чтобы вывести пользователя на страницу достижений, чтобы показать все возможные достижения, которых он может достичь. При перечислении достижений я хочу показать прогресс этого пользователя, если таковой имеется.
Это ответ на ваш недавний комментарий.
Чтобы добиться желаемого, я представил новый метод модели User под названием achievementsblock, который использует метод php array_map.
Я не тестировал код, но вы должны уловить идею.
//in User model
public function achievements()
{
return $this->belongsToMany('App\Achievements')->withPivot('is_complete', 'percentage_complete', 'completed_at');
}
//in User model
public function achievementsblock()
{
$all_achievements = Achievement::all();
return array_map(function($temp_achievement){
$achievement_ids = $this->achievements()->pluck('id');
$new_temp = new \stdClass();
$new_temp->type_name = $temp_achievement->type_name;
$new_temp->description = $temp_achievement->description;
if (in_array($temp_achievement->id, $achievement_ids)){
$user_achievement = $this->achievements()->where("achievements.id"," = ",$temp_achievement->id)->first();
$new_temp->is_complete = $user_achievement->is_complete;
$new_temp->percentage_complete = $user_achievement->percentage_complete;
$new_temp->completed_at = $user_achievement->completed_at;
}
else {
$new_temp->is_complete = 0;
$new_temp->percentage_complete = 0;
$new_temp->completed_at = null;
}
return $new_temp;
}, $all_achievements);
}
В ваших контроллерах вы можете получить блок достижений для пользователя следующим образом:
$user_achievement_blocks = User::first()->achievementsblock();
Пришлось сделать пару настроек, таких как получение некоторых результатов в виде массива, а не объектов. Спасибо за помощь. Ценить это.
Большой! Я счастлив, что это было полезно. Не забудьте вернуться, чтобы отредактировать этот ответ с изменениями, когда сможете.
Вам нужно узнать о методе whereHas, который позволяет запрашивать отношения при получении результатов.