为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

PHP
慕侠2389804 2022-01-23 11:01:25
我将 Laravel 6 与 SQL Server 2017 数据库后端一起使用。在数据库中,我有一个名为 PersonPhoto 的表,其中包含一个 Photo 列和一个 Thumbnail 列,其中照片和缩略图存储为 VARBINARY。我定义了以下 Eloquent 模型,使用两个访问器将图像转换为 base64 编码:<?phpnamespace 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 字符,可能编码不正确”错误,就好像访问器被忽略并且原始数据正在被序列化一样。为了解决这个问题,我改变了模型:<?phpnamespace 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)虽然我的解决方法有效,但这是一种合理的方法还是我可能会遇到问题?有更好的方法吗?
查看完整描述

1 回答

?
心有法竹

TA贡献1866条经验 获得超5个赞

我认为你有两个问题:


首先,Laravel 序列化要求你附加任何你想包含的访问器——即使同名的属性已经存在。您没有在第一个示例中显式附加所需的值。


https://laravel.com/docs/5.8/eloquent-serialization#appending-values-to-json


其次,Laravel 并不总是喜欢大写的属性名称。它很高兴地期望所有内容都是小写的(snake_case),并且基于一些快速测试,$value当涉及到 case 时,似乎很难将要传递给访问器的正确关联起来。


但是,您可以修改您的访问器以直接调用该属性,而不是依赖 Laravel 来确定您的要求并达到预期的结果。


<?php


namespace App;


use Illuminate\Database\Eloquent\Model;


class PersonPhoto extends Model

{

    protected $connection = 'mydb';

    protected $table = 'PersonPhoto';

    protected $primaryKey = 'PersonID';


    // add the desired appends for serialization

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


    public function person()

    {

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

    }


    public function getPhotoAttribute()

    {

        // access the attribute directly

        return base64_encode($this->attributes['Photo']);

    }



    public function getThumbnailAttribute()

    {

        // access the attribute directly

        return base64_encode($this->attributes['Thumbnail']);

    }


}

编辑:我实际上看到您在第二个示例中使用$this->Thumbnailand做了类似的事情$this->Photo。我的例子是相同的概念,但不依赖魔术方法。


查看完整回答
反对 回复 2022-01-23
  • 1 回答
  • 0 关注
  • 227 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信