如何在 yii2 中让 many-to-many 休息 API
How make a many-to-many rest API in yii2
我正在尝试建立 many-to-may 关系,但我做不到。
我有一个包含 3 个 table 的数据库:users
、favorites
和 videos
。收藏夹 table 包含 2 个 foreign keys
指向用户 table 和视频 table.
目前我有:
用户模型:
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()
]);
}
按照他们所做的:
但这没有用。我也试过 extraFields
和 expand
没有运气。
我该怎么做才能使结果看起来像这样:
[{
"id": 1,
"name": "video name",
"likes": 69,
"user": [{
"id": 1,
"name": "John"
}]
},
...
]
您需要更新几个地方的代码。
REST
活动控制器。
看起来您正在尝试获取 一个 用户喜欢的视频,您应该使用查看操作,而不是索引操作,它应该用于获取视频列表,您可以使用基本 view
操作,无需覆盖它,它会按照您的需要工作。
在controller里面,设置模型应该就够了。
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()
您可以在 expandFields
上使用 users
快捷方式,如果名称不同,则可以使用扩展格式,即 'likes' => 'users'
然后,通过以下方式查询您的 API:
https://apiv1.example.com/videos/45?expand=users
应该会像 post
中那样给您预期的结果
[{
"id": 1,
"name": "video name",
"likes": 69,
"users": [{
"id": 1,
"name": "John"
}]
},
...
]
请注意,用户数组将被称为 'users' 而不是 'user' 如果您以相同的方式配置,您可以使用 extraFields
中的扩展符号更改它。
我正在尝试建立 many-to-may 关系,但我做不到。
我有一个包含 3 个 table 的数据库:users
、favorites
和 videos
。收藏夹 table 包含 2 个 foreign keys
指向用户 table 和视频 table.
目前我有:
用户模型:
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()
]);
}
按照他们所做的:
但这没有用。我也试过 extraFields
和 expand
没有运气。
我该怎么做才能使结果看起来像这样:
[{
"id": 1,
"name": "video name",
"likes": 69,
"user": [{
"id": 1,
"name": "John"
}]
},
...
]
您需要更新几个地方的代码。
REST
活动控制器。
看起来您正在尝试获取 一个 用户喜欢的视频,您应该使用查看操作,而不是索引操作,它应该用于获取视频列表,您可以使用基本 view
操作,无需覆盖它,它会按照您的需要工作。
在controller里面,设置模型应该就够了。
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()
您可以在 expandFields
上使用 users
快捷方式,如果名称不同,则可以使用扩展格式,即 'likes' => 'users'
然后,通过以下方式查询您的 API:
https://apiv1.example.com/videos/45?expand=users
应该会像 post
中那样给您预期的结果[{
"id": 1,
"name": "video name",
"likes": 69,
"users": [{
"id": 1,
"name": "John"
}]
},
...
]
请注意,用户数组将被称为 'users' 而不是 'user' 如果您以相同的方式配置,您可以使用 extraFields
中的扩展符号更改它。