猿问

Laravel 6 Eloquent 模型序列化忽略访问器

我将 Laravel 6 与 SQL Server 2017 数据库后端一起使用。在数据库中,我有一个名为 PersonPhoto 的表,其中包含一个 Photo 列和一个 Thumbnail 列,其中照片和缩略图存储为 VARBINARY。


我定义了以下 Eloquent 模型,使用两个访问器将图像转换为 base64 编码:


<?php


namespace App;


use Illuminate\Database\Eloquent\Model;


class PersonPhoto extends Model

{

    protected $connection = 'mydb';

    protected $table = 'PersonPhoto';

    protected $primaryKey ='PersonID';


    public function person(){


        return $this->belongsTo('App\Person', 'PersonID');


    }


    public function getPhotoAttribute($value){


        return base64_encode($value);


    }



    public function getThumbnailAttribute($value){


        return base64_encode($value);


    }


}

这在 Blade 模板中运行良好,但是当我尝试序列化为 JSON 或数组时,我收到“格式错误的 UTF-8 字符,可能编码不正确”错误,就好像访问器被忽略并且原始数据正在被序列化一样。为了解决这个问题,我改变了模型:


<?php


namespace App;


use Illuminate\Database\Eloquent\Model;


class PersonPhoto extends Model

{

    protected $connection = 'mydb';

    protected $table = 'PersonPhoto';

    protected $primaryKey ='PersonID';


    //Added to hide from and add fields to serializer

    protected $hidden = ['Photo', 'Thumbnail'];

    protected $appends = ['encoded_photo', 'encoded_thumbnail'];


    public function person(){


        return $this->belongsTo('App\Person', 'PersonID');


    }


    public function getPhotoAttribute($value){


        return base64_encode($value);


    }


    public function getThumbnailAttribute($value){


        return base64_encode($value);


    }



    //Added these new accessors

    public function getEncodedPhotoAttribute(){


         return base64_encode($this->Photo);


    }


    public function getEncodedThumbnailAttribute(){


        return base64_encode($this->Thumbnail);


    }


}

这隐藏了序列化程序的原始照片和缩略图字段,并包括两个新的访问器。这似乎有效并解决了我的问题。


问题:1)Laravel 的序列化程序是否像我怀疑的那样忽略了我的访问器,这是设计使然吗?2)虽然我的解决方法有效,但这是一种合理的方法还是我可能会遇到问题?有更好的方法吗?


慕侠2389804
浏览 228回答 1
1回答

心有法竹

我认为你有两个问题:首先,Laravel 序列化要求你附加任何你想包含的访问器——即使同名的属性已经存在。您没有在第一个示例中显式附加所需的值。https://laravel.com/docs/5.8/eloquent-serialization#appending-values-to-json其次,Laravel 并不总是喜欢大写的属性名称。它很高兴地期望所有内容都是小写的(snake_case),并且基于一些快速测试,$value当涉及到 case 时,似乎很难将要传递给访问器的正确关联起来。但是,您可以修改您的访问器以直接调用该属性,而不是依赖 Laravel 来确定您的要求并达到预期的结果。<?phpnamespace App;use Illuminate\Database\Eloquent\Model;class PersonPhoto extends Model{&nbsp; &nbsp; protected $connection = 'mydb';&nbsp; &nbsp; protected $table = 'PersonPhoto';&nbsp; &nbsp; protected $primaryKey = 'PersonID';&nbsp; &nbsp; // add the desired appends for serialization&nbsp; &nbsp; protected $appends = ['Photo','Thumbnail'];&nbsp; &nbsp; public function person()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return $this->belongsTo('App\Person', 'PersonID');&nbsp; &nbsp; }&nbsp; &nbsp; public function getPhotoAttribute()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // access the attribute directly&nbsp; &nbsp; &nbsp; &nbsp; return base64_encode($this->attributes['Photo']);&nbsp; &nbsp; }&nbsp; &nbsp; public function getThumbnailAttribute()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // access the attribute directly&nbsp; &nbsp; &nbsp; &nbsp; return base64_encode($this->attributes['Thumbnail']);&nbsp; &nbsp; }}编辑:我实际上看到您在第二个示例中使用$this->Thumbnailand做了类似的事情$this->Photo。我的例子是相同的概念,但不依赖魔术方法。
随时随地看视频慕课网APP
我要回答