Laravel отношение через массив JSON объектов - PullRequest
0 голосов
/ 30 января 2020

Модели:

Пользователь который имеет много групп и имеет много роли через группа

и

группа которая hasMany пользователи .

Эти отношения хранятся в таблице group в столбце с именем 'members', который отформатирован следующим образом:

[
    {
        user_id: *user_id_one*
        role_id: *role_id_one*
    },
    {
        user_id: *user_id_two*
        role_id: *role_id_two*
    },
]

Требования:

  • Модели должны быть связаны через отношения, чтобы я мог их быстро загрузить.
  • Я не могу изменить структуру данных, потому что очень большое количество программ уже было сделано в отношении этих моделей и структур.
  • Это должно быть сделано с использованием sql версии от 5.7
  • Это должно быть сделано с использованием php 7.1, 7.2 или 7.3

Что я пробовал:

Сначала я попробовал это в Пользователь модель:

method:
$this->hasMany('\App\Group', 'members->[*].user_id')

query:
select * from `groups` where json_unquote(json_extract(`groups`.`members`, '$."[*].user_id"')) = ? and json_unquote(json_extract(`groups`.`members`, '$."[*].user_id"')) is not null

Затем:

method:
$this->hasMany('\App\Group', 'members->[*].user_id')
or
$this->hasMany('\App\Group', 'members->$[*].user_id')

query:
Column Not Found

Могучие staudenmeir / eloquent- json -отношения приблизили меня к

method:
$this->hasManyJson('\App\Group', 'members->[*].user_id')

query:
select * from `groups` where json_contains(`groups`.`members`, ?, '$."[*].user_id"')

Все они были опробованы с использованием обычного первичного ключа и пользовательских атрибутов, которые возвращали:

  • "JSON_ARRAY ( primary_key )"
  • "JSON_OBJECT ('id', primary_key ) "
  • " [' primary_key '] "
  • " {'id': ' primary_key '} "

Однако все они были в кавычках.

Уже учтено:

Вот пример рабочего атрибута

public function getGroupsAttribute()
{
    return Group::whereRaw("JSON_CONTAINS(members->'$[*].user_id', JSON_ARRAY('{$this->id}'))")->get();
}

Я подумала, прежде чем уйти и завела обычные отношения, которые я бы спросила здесь. Я мог бы, вероятно, сделать что-то с областью действия, чтобы применить что-то вроде следующего (с отношением, которое только что вернуло все группы), но это был бы тот же объем работы и менее чистый.

->with(['groups' => function ($query) use ($user) {
   $query->whereRaw("JSON_CONTAINS(members->'$[*].user_id', JSON_ARRAY('{$user->id}'))")
}])

1 Ответ

1 голос
/ 31 января 2020

С пакетом eloquent-json-relations вы можете реализовать отношение groups следующим образом:

class User extends Model
{
    use \Staudenmeir\EloquentJsonRelations\HasJsonRelationships;

    public function groups()
    {
       return $this->hasManyJson(Group::class, 'members[]->user_id');
    }
}

class Group extends Model
{
    use \Staudenmeir\EloquentJsonRelations\HasJsonRelationships;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...