在 laravel json 关系预加载响应中类型转换

type casting in laravel json response in relationships eager loading

这是我的 post 模型。

class Post extends Model
{
    use SoftDeletes;
    protected $table = 'posts';
    protected $fillable = ['title','featuring_image', 'brief', 'body', 'seen_count'];


    public function user(){
        return $this->belongsTo(User::class);
    }



    public function comments()
    {
        return $this->hasMany(Comment::class);
    }

    public function someComments()
    {
        return $this->comments()->limit(Constants::COMMENTS_COUNT_LIMIT);
    }

    public function commentsCount()
    {
        return $this->comments()
            ->selectRaw('post_id, count(*) as count')
            ->groupBy('post_id');
    }

    public function likes()
    {
        return $this->hasMany(Like::class);
    }

    public function isLiked()
    {
        return $this->likes()->where('user_id', auth()->check() ? auth()->user()->id : 0);
    }

    public function likesCount()
    {
        return $this->likes()
            ->selectRaw('post_id, count(*) as count')
            ->groupBy('post_id');
    }


}

我在这个模型上执行了这个查询。

 $post = Post::with(['categories', 'user', 'commentsCount', 'likesCount', 'isLiked'])->find($post->id);

因为这个table和点赞和评论table之间的关系,'commentsCount', 'likesCount', 'isLiked'这个查询的输出是一个数组。但是我需要在 laravel josn 响应中接收 'commentsCount''likesCount' 的数字,以及 'isliked' 的布尔值作为输出。

您可能会发现使用 Eloquent 附带的 withCount() 更容易。

然后对于 is_liked,您可以使用范围来获取值并将 cast 其转换为布尔值:

public function scopeIsLiked($query)
{
    if (is_null($query->getQuery()->columns)) {
        $query->select([$query->getQuery()->from . '.*']);
    }

    $relation = Relation::noConstraints(function () {
        return $this->likes();
    });

    $q = $this->likes()->getRelationExistenceCountQuery(
        $relation->getRelated()->where('user_id', auth()->check() ? auth()->user()->id : 0)->newQuery(), $query
    );

    $query->selectSub($q->toBase(), 'is_liked');
}

请注意,您需要将 Relationuse 语句添加到 class:

的顶部
use Illuminate\Database\Eloquent\Relations\Relation;

您的模型可能看起来像:

class Post extends Model
{
    use SoftDeletes;

    protected $table = 'posts';

    protected $fillable = ['title', 'featuring_image', 'brief', 'body', 'seen_count'];

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function comments()
    {
        return $this->hasMany(Comment::class);
    }

    public function someComments()
    {
        return $this->comments()->limit(Constants::COMMENTS_COUNT_LIMIT);
    }

    public function likes()
    {
        return $this->hasMany(Like::class);
    }

    /**
     * Scope to add the "is_liked" flag.
     *
     * @param $query
     */
    public function scopeIsLiked($query)
    {
        if (is_null($query->getQuery()->columns)) {
            $query->select([$query->getQuery()->from . '.*']);
        }

        $relation = Relation::noConstraints(function () {
            return $this->likes();
        });

        $q = $this->likes()->getRelationExistenceCountQuery(
            $relation->getRelated()->where('user_id', auth()->check() ? auth()->user()->id : 0)->newQuery(), $query
        );

        $query->selectSub($q->toBase(), 'is_liked');
    }
}

您的查询将类似于:

$post = Post::with('categories', 'user')
    ->withCount('likes', 'comments')
    ->isLiked()
    ->find($post->id);

希望对您有所帮助!

您可以使用 Laravel 转换: 在每个模型中,您可以添加以下内容来转换一个值,例如:

protected $casts = [
   'isLiked' => 'boolean',
];

gives a nice solution using scopes, but for laravel 5.4+ you could get away with aliasing the withCount() result and then casting it to boolean with a $cast variable on the model or an accessor(使用访问器,您只能获得蛇形盒is_liked)。这样我们就不需要写复杂的作用域了。

模型将是

class Post extends Model
{
    // rest of model 

    protected $casts = ['isLiked'=>'boolean'];

    public function likes()
    {
        return $this->hasMany(Like::class);
    }
}

然后在你的控制器中

$post = Post::with('categories', 'user')
    ->withCount(
        [
            'likes as likesCount', 'comments as commentsCount',
            'likes as isLiked' =>function($query){
                 $query->where('user_id', auth()->check() ? auth()->user()->id : 0);
             }
        ]
    )
    ->find($post->id);

现在你得到 likesCount (int), commentsCount (int) and isLiked (boolean)