Я пытаюсь заставить работать отношение «многие к маю», но не могу заставить его работать.
У меня есть база данных с 3 таблицами: users
, favorites
и videos
. Таблица избранного содержит 2 foreign keys
, которые указывают на таблицу пользователей и таблицу видео.
В настоящее время у меня есть следующее:
Модель пользователя:
public function getVideos()
{
return $this->hasMany(Video::class, ['id' => 'video_id'])->viaTable(UserFavorites::tableName(), ['favorite_id' => 'id']);
}
Видео Модель:
public function getUsers()
{
return $this->hasMany(User::class, ['id' => 'user_id'])->via(UserFavorites::tableName());
}
Видеоконтроллер: (активный контроллер)
public function actions()
{
$actions = parent::actions();
$actions['index']['prepareDataProvider'] = [$this, 'prepareDataProvider'];
return $actions;
}
public function prepareDataProvider()
{
$user = User::findOne('1=1');
return new ActiveDataProvider([
'query' => $user->getVideos()
]);
}
После того, что они сделали в:
Отношение «многие ко многим» в yii2 activedataprovider
но это не сработало. Я также пробовал с extraFields
и expand
безуспешно.
Как мне сделать так, чтобы результат выглядел примерно так:
[{
"id": 1,
"name": "video name",
"likes": 69,
"user": [{
"id": 1,
"name": "John"
}]
},
...
]
Активный контроллер REST
.
Похоже, вы пытаетесь получить одно видео с пользователем, которому оно понравилось, вы должны использовать действие просмотра, а не действие индекса, которое следует использовать для получения списка видео, вы можете использовать базовое действие view
, нет нужно переопределить его, он будет работать так, как вам нужно.
В контроллере должно быть достаточно настройки модели.
use yii\rest\ActiveController;
class VideoController extends ActiveController
{
public $modelClass = Video::class;
}
Попробуйте установить $_verbs
и actionOptions
, если вам нужно, чтобы они не использовались по умолчанию.
Модель.
Вы должны использовать extraFields
, чтобы представить метод как поле.
use yii\db\ActiveRecord;
class Video extends ActiveRecord
{
// Other methods here...
public function getUsers()
{
return $this->hasMany(User::class, ['id' => 'user_id'])
->viaTable(UserFavorites::tableName(), [
'video_id' => 'id'
]);
}
public function extraFields()
{
return [
'users'
];
}
}
Если вы хотите использовать то же имя для вызова API, что и функция, т. е. вызов API использует expand=users
, а метод вызывается getUsers()
, вы можете использовать ярлык users
на expandFields
, если имена разные, вы можете использовать расширенный формат, то есть 'likes' => 'users'
Затем запросите ваш API с помощью:
https://apiv1.example.com/videos/45?expand=users
Должен дать вам ожидаемые результаты, как в вашем посте
[{
"id": 1,
"name": "video name",
"likes": 69,
"users": [{
"id": 1,
"name": "John"
}]
},
...
]
Обратите внимание, что массив пользователей будет называться «пользователи», а не «пользователь», если вы настроили таким же образом, вы можете изменить это, используя расширенную нотацию внутри extraFields
.
Я только что заметил, что вы используете via
, но даете ему имя таблицы вместо имени отношения. Проверьте документацию по этому вопросу в Yii docs Один из способов исправить это — использовать viaTable
Я обновлю ответ.
Спасибо за объяснение того, как точки связаны; Я изменил имя метода на
getUsers
и имя дополнительного поля наusers
. Теперь я получаю сообщение об ошибке «не имеет отношения с именем ...».