我正在将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)尽管我的解决方法可行,但这是一种合理的方法还是我可能会遇到问题?有更好的方法吗?
谢谢
答案 0 :(得分:1)
我认为您有两个问题:
首先,Laravel序列化要求您附加要包含的所有访问器-即使已经存在相同名称的属性。您没有在第一个示例中显式附加所需的值。
https://laravel.com/docs/5.8/eloquent-serialization#appending-values-to-json
第二,Laravel并不总是喜欢大写的属性名称。它很高兴地期望所有内容都是小写的(snake_case),并且基于一些快速测试,在涉及大小写时将适当的$value
传递给访问器似乎有些麻烦。
但是,您可以修改访问器以直接调用该属性,而不必依靠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->Thumbnail
和$this->Photo
做过类似的事情。我的示例具有相同的概念,但不依赖魔术方法。
__get/__set/__call performance questions with PHP