Laravel 6 Eloquent модель сериализации игнорируя аксессоры - PullRequest
0 голосов
/ 21 сентября 2019

Я использую 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 или массив, я получаю ошибку «Malformed UTF-8, возможно, неправильно закодированная», как если бы Accessorsигнорируются, а необработанные данные сериализуются.Чтобы обойти это, я изменил модель:

<?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);

    }

}

Это скрывает исходные поля Photo и Thumbnail от сериализатора и включает в себя два новых метода доступа.Похоже, это работает и решает мою проблему.

Вопросы: 1) Сериализатор Laravel игнорирует мои аксессоры, как я подозреваю, и это задумано?2) Хотя мой обходной путь работает, это разумный подход или я могу столкнуться с проблемами?Есть ли лучший способ сделать это?

Спасибо

1 Ответ

1 голос
/ 21 сентября 2019

Я думаю, что у вас есть две проблемы:

Во-первых, для сериализации Laravel необходимо добавить любые методы доступа, которые вы хотите включить - даже если атрибут с таким именем уже существует.Вы явно не добавили нужные значения в первом примере.

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

Во-вторых, Laravel не всегда любит заглавные имена атрибутов.Он с радостью ожидает, что все будет в нижнем регистре (snake_case) и, основываясь на некотором быстром тестировании, похоже, испытывает некоторые затруднения, связывая надлежащий $value для передачи методу доступа, когда дело касается регистра.

Однако вы можете изменить свойAccessor для непосредственного вызова атрибута вместо того, чтобы полагаться на 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 / __ вызывает вопросы производительности с PHP

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...