Получите все значки с прогрессом пользователя, если таковые имеются

У меня много отношений между пользователями и достижениями. Расположение стола аналогично этому.

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, который позволяет запрашивать отношения при получении результатов.

Afraz Ahmad 14.09.2018 19:15
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Laravel Scout - это популярный пакет, который предоставляет простой и удобный способ добавить полнотекстовый поиск в ваше приложение Laravel. Он...
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
1
1
68
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вам нужно узнать о методе whereHas, который позволяет запрашивать отношения при получении результатов.

В модели пользователя

// создаем отношения достижений

public function achievements()
{
    return $this->belongsToMany(Achievement::class)
              ->withPivot('is_complete', 'percentage_complete', 'completed_at');
}

// затем запросите его, как показано ниже.

$achievements= $user->achievements;

Узнать больше здесь

Спасибо, я разберусь в этом подробнее. То, что вы оставили здесь, похоже, получит информацию о пользователе и прикрепит все начатые достижения. Я хочу получить все достижения, а затем прикрепить любой прогресс, который есть у пользователя для каждого из них, даже если у них еще нет записей о прогрессе. Таким образом, я могу перечислить все значки и показать их прогресс, если таковой имеется.

Chris 14.09.2018 19:35

По-прежнему получает только те, которые пользователь запустил или для которых есть запись в сводной таблице. Нужно получить все достижения и показать прогресс, даже если его нет. Идея состоит в том, чтобы они приземлились на странице достижений и увидели все доступные достижения, и любые, которые они начали, покажут их прогресс.

Chris 14.09.2018 22:02

В отношениях 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. Надеюсь, что это имеет смысл.

Chris 14.09.2018 21:12

Вы имеете в виду, что предоставленный мной код этого не делает? Тогда любезно объясните дальше.

Elisha Senoo 15.09.2018 21:26

Если у меня есть 4 записи в таблице достижений, и у меня есть 3 записи для пользователя в таблице achievement_user, поскольку они начали 3 из достижений. Когда я вызываю $ user-> достижения, я получаю только 3 достижения, которые они начали. Я пытаюсь получить все достижения, поэтому в этом случае мне нужны все 4 достижения, а затем пользователи прогрессируют, даже если нет прогресса. Идея состоит в том, чтобы вывести пользователя на страницу достижений, чтобы показать все возможные достижения, которых он может достичь. При перечислении достижений я хочу показать прогресс этого пользователя, если таковой имеется.

Chris 17.09.2018 16:51
Ответ принят как подходящий

Это ответ на ваш недавний комментарий.

Чтобы добиться желаемого, я представил новый метод модели 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();

Пришлось сделать пару настроек, таких как получение некоторых результатов в виде массива, а не объектов. Спасибо за помощь. Ценить это.

Chris 21.09.2018 20:05

Большой! Я счастлив, что это было полезно. Не забудьте вернуться, чтобы отредактировать этот ответ с изменениями, когда сможете.

Elisha Senoo 22.09.2018 20:18

Другие вопросы по теме