在没有直接关系的情况下获取Lavavel(5)数据

时间:2018-10-24 22:04:35

标签: laravel laravel-5

我有一个包含这些表格的应用

  • 用户
  • 频道(使用user_id用户外键)
  • 播放列表(向用户提供user_id外键,向通道提供外channel_id外)
  • 曲目(使用playlist_id外键播放列表,而不使用user_id外键)

User模型定义为:

public function channels()
{
    return $this->hasMany('App\Channel');
}

Channel模型定义为:

public function playlists()
{
    return $this->hasMany('App\Playlist');
}

(和一个$this->belongsTo('App\User')

Playlist模型定义为:

public function tracks()
{
    return $this->hasMany('App\Track');
}

(和一个$this->belongsTo('App\Channel')

Track模型定义为:

public function playlist()
{
   return $this->belongsTo('App\Playlist');
}

现在在特定播放列表中列出曲目时,我会这样做:

function list($playlist) {
    $tracks = Track::with('playlist')->get();
    return response()->json($tracks);
}

这在页面http://.../tracks/2(其中2是播放列表ID)上正常工作,但是如果用户将2更改为3,则他可能会看到播放列表#3中的曲目,而这可能不是他的。那么如何从播放列表中获取用户ID,以仅显示用户实际拥有的属于播放列表的曲目?

1 个答案:

答案 0 :(得分:2)

在给定的代码中,您似乎并没有真正加载URL中ID所指定的播放列表。 $playlist应为2,其中包含示例网址(http://.../tracks/2):

function list($playlist) {
    $tracks = Track::with('playlist')->get();
    return response()->json($tracks);
}

您只是在整个系统中加载 all 个曲目,并希望加载它们各自的Playlist对象。

假设使用该URL,则要显示播放列表2的曲目,当且仅当该曲目属于经过身份验证的用户时,应该要做的是通过其ID查找播放列表,然后授权Playlist属于登录用户,然后使用以下关系加载其tracks

public function list($id)
{
    // Find a playlist with the given ID, or 404 if none could be found.
    $playlist = Playlist::findOrFail($id);

    // If the playlist does not belong to the user, throw an AuthorizationException.
    if ($playlist->user_id != auth()->user()->id) {
        throw new AuthorizationException();
    }

    // Return a response, passing through the tracks belonging to the playlist.
    return response()->json($playlist->tracks);
}

处理授权的更好方法是使用Laravel's built in authorisation features,尤其是policies。这样一来,您就可以将授权逻辑与控制器分开,并将所有授权逻辑保留在相同/相似的位置:

  • 使用php artisan make:policy PlaylistPolicy创建策略,该策略将创建类App\Policies\PlaylistPolicy
  • 在该政策中,只需定义一个方法即可表示您要针对播放列表进行的授权操作。在此示例中,您正在授权用户是否可以查看给定的播放列表,因此,view是我在此处建议的方法名称。
  • 该方法将接受2个参数,即经过身份验证的用户和您感兴趣的Playlist对象:

    public function view(User $user, Playlist $playlist)
    {
        //
    }
    
  • 在该方法中,您只需添加一些逻辑即可确定给定用户(登录用户)是否有权访问查看给定{{1} }。如果用户具有访问权限,则该方法应返回Playlist,否则,将返回true

    false
  • 现在,您只需要在public function view(User $user, Playlist $playlist) { return $user->id === $playlist->user_id; } 中注册策略。您只需将App\Providers\AuthServiceProvider模型映射到Playlist,只需添加到PlaylistPolicy属性即可。

    $policies
  • 现在,可以使用protected $policies = [ Playlist::class => PlaylistPolicy::class ]; 方法代替控制器中的if语句,该方法应该出现在控制器上(只要authorize特征为{{1} } d)。

    AuthorizesRequests