로드시 Laravel / Eloquent 모델에 커스텀 속성을 추가 하시겠습니까?


219

RedBean $model->open() 메소드 로 달성 할 수있는 것과 비슷한 Laravel / Elloquent 모델에로드 할 때 사용자 정의 속성 / 속성을 추가하고 싶습니다 .

예를 들어, 현재 내 컨트롤러에는 다음이 있습니다.

public function index()
{
    $sessions = EventSession::all();
    foreach ($sessions as $i => $session) {
        $sessions[$i]->available = $session->getAvailability();
    }
    return $sessions;
}

루프를 생략하고 '사용 가능한'속성을 이미 설정하고 채우는 것이 좋을 것입니다.

객체가로드 될 때이 속성을 첨부하기 위해 설명서에 설명 된 모델 이벤트 중 일부를 사용해 보았지만 지금까지 성공하지 못했습니다.

노트:

  • '사용 가능'은 기본 테이블의 필드가 아닙니다.
  • $sessionsAPI의 일부로 JSON 객체로 반환되므로 $session->available()템플릿 과 같은 것을 호출 하는 것은 옵션이 아닙니다.

답변:


316

ModeltoArray()메소드는 기본 테이블의 열과 직접 관련되지 않은 접근자를 무시하기 때문에 문제가 발생 합니다.

Taylor Otwell 이 여기 에서 언급했듯이 "이것은 의도적이며 성능상의 이유입니다." 그러나 이것을 달성하는 쉬운 방법이 있습니다.

class EventSession extends Eloquent {

    protected $table = 'sessions';
    protected $appends = array('availability');

    public function getAvailabilityAttribute()
    {
        return $this->calculateAvailability();  
    }
}

$ appends 속성에 나열된 모든 속성은 적절한 접근자를 추가 한 경우 모델의 배열 또는 JSON 형식에 자동으로 포함됩니다.

이전 답변 (Laravel 버전 <4.08) :

내가 찾은 가장 좋은 해결책은 toArray()메소드 를 재정의하고 명시 적으로 속성을 설정하는 것입니다.

class Book extends Eloquent {

    protected $table = 'books';

    public function toArray()
    {
        $array = parent::toArray();
        $array['upper'] = $this->upper;
        return $array;
    }

    public function getUpperAttribute()
    {
        return strtoupper($this->title);    
    }

}

또는 많은 커스텀 접근자가 있으면 모두 반복하여 적용하십시오.

class Book extends Eloquent {

    protected $table = 'books';

    public function toArray()
    {
        $array = parent::toArray();
        foreach ($this->getMutatedAttributes() as $key)
        {
            if ( ! array_key_exists($key, $array)) {
                $array[$key] = $this->{$key};   
            }
        }
        return $array;
    }

    public function getUpperAttribute()
    {
        return strtoupper($this->title);    
    }

}

오늘 최고의 질문과 답변. 나는 이것을 달성하는 방법에 대한 다른 구현을 연구하고 있었고 laravel.io에 질문을 게시하기 전에 이것을 발견했습니다! 예 !!!
Gayan Hewa

그리고 경우에 따라 json에 추가하지 않는 방법이 있습니까?
Jordi Puigdellívol

3
이러한 관습 속성은 관계를 통해 모델을 호출 할 때 나타나지 않는 것 같습니다. (예 : Models \ Company :: with ( 'people')). 어떤 생각?
앤드류

@ JordiPuigdellívol Laravel 5에서는를 사용하여 제외 protected $hidden = []할 열 / 접근자를 추가 할 수 있습니다 .
junkystu

124

Laravel Eloquent 문서 페이지마지막 내용 은 다음과 같습니다.

protected $appends = array('is_admin');

그것은 같은 방법을 수정하는 것과 같은 추가 작업없이 모델에 새로운 접근자를 자동으로 추가하는 데 사용할 수 있습니다 ::toArray() .

getFooBarAttribute(...)접근 foo_bar자를 만들고 $appends배열에 추가하십시오 .


4
아 흥미 롭군 이 기능은 내 질문이 게시 된 후 Laravel에 추가되었습니다 ( github.com/laravel/framework/commit/… ). 이것은 v4.08 이상을 사용하는 모든 사람에게 정답입니다.
coatesap

3
접근자를위한 콘텐츠를 생성하기 위해 관계를 사용하는 경우 사용할 수 없습니다. 이 경우 toArray메서드 를 재정의해야 할 수도 있습니다 .
gpmcadam

2
참조한 문서가 https://laravel.com/docs/5.5/eloquent-serialization 로 이동 한 것처럼 보입니다 .
mibbler

40

당신은 당신의 이름을 변경하는 경우 getAvailability()에 방법을 getAvailableAttribute()당신의 방법이 될 접근 하면 사용하여 읽을 수 있습니다->available 직선 모델에.

문서 : https://laravel.com/docs/5.4/eloquent-mutators#accessors-and-mutators

편집 : 속성이 "가상"이기 때문에 기본적으로 객체의 JSON 표현에 포함되지 않습니다.

그러나 이것을 발견했습니다 : 사용자 정의 모델 접근자는-> toJson () 호출 할 때 처리되지 않습니까?

속성을 배열에 반환하려면 $ attributes 배열의 키로 속성을 추가하십시오.

class User extends Eloquent {
    protected $attributes = array(
        'ZipCode' => '',
    );

    public function getZipCodeAttribute()
    {
        return ....
    }
}

나는 그것을 테스트하지는 않았지만 현재 설정에서 시도하는 것이 쉽지는 않습니다.


이것은 객체에서 ->available사용할 수있는 만큼 작동 $session하지만 $sessionsJSON 문자열 (API의 일부)로 직접 변환되므로 이것을 사용할 기회가 없습니다.
coatesap

물건이 어떻게 작동하는지 잘 모르겠습니다. 경우 EventSession::all()는 API에서 반환 JSON 개체, 당신은 정말, 권리를 Laravel 모델을 사용하지 않는? 죄송합니다. 모델을 어떻게 구현했는지 혼란 스럽습니다.
Alexandre Danault 2016 년

EventSession은 표준 Eloquent 객체 ( class EventSession extends Eloquent)입니다. ::all()그냥 예입니다. EventSession::find(170071)또 다른 것입니다. 이것들은 SessionController ( SessionController extends \BaseController) 전체의 다양한 지점에서 호출되며 '/ sessions / 170071'과 같은 URL을 통해 호출됩니다.
coatesap

열쇠는 Eloquent의 내장 객체에서 JSON으로의 변환에있을 수 있다고 생각합니다. public $available모델 과 같은 사용자 지정 특성을 추가하더라도 개체가 변환 될 때 표시되지 않습니다.
coatesap

3
이 문서는 2013 년 10 월 8 일에 Laravel 4.0.8이 릴리스 된 이후에 제공됩니다. 공식 문서를 참조하십시오 : laravel.com/docs/eloquent#converting-to-arrays-or-json (찾아보기 protected $appends = array('is_admin');)
Ronald Hulshof

23

모델에 속성 그림이 있는데 Storage 폴더의 파일 위치가 포함되어 있습니다. 이미지는 base64로 인코딩되어 반환되어야합니다.

//Add extra attribute
protected $attributes = ['picture_data'];

//Make it available in the json response
protected $appends = ['picture_data'];

//implement the attribute
public function getPictureDataAttribute()
{
    $file = Storage::get($this->picture);
    $type = Storage::mimeType($this->picture);
    return "data:" . $type . ";base64," . base64_encode($file);
}

1
$ attributes & $ appends의 pictureData가 아닌 picture_data 여야합니다. 그리고 $ attributes 변수도 건너 뛸 수 있습니다.
Madushan Perera

16

setAttribute모델의 함수를 사용 하여 사용자 정의 속성을 추가 할 수 있습니다.


9

users 테이블에 first_name과 last_name이라는 2 개의 열이 있고 전체 이름을 검색하려고한다고 가정 해 봅시다. 다음 코드를 사용하여 달성 할 수 있습니다.

class User extends Eloquent {


    public function getFullNameAttribute()
    {
        return $this->first_name.' '.$this->last_name;
    }
}

이제 다음과 같이 이름을 얻을 수 있습니다.

$user = User::find(1);
$user->full_name;

7

1 단계 : $appends
2 단계 : 속성에 대한 접근 자 정의의 속성 정의
예:

<?php
...

class Movie extends Model{

    protected $appends = ['cover'];

    //define accessor
    public function getCoverAttribute()
    {
        return json_decode($this->InJson)->cover;
    }

3

구독 모델에서 구독이 일시 중지되었는지 여부를 알아야합니다. 여기 내가 어떻게했는지

public function getIsPausedAttribute() {
    $isPaused = false;
    if (!$this->is_active) {
        $isPaused = true;
    }
}

그런 다음 뷰 템플릿 $subscription->is_paused에서 결과를 얻는 데 사용할 수 있습니다.

getIsPausedAttribute사용자 지정 특성을 설정하는 형식입니다,

is_paused뷰에서 속성을 가져 오거나 사용하는 데 사용 됩니다.


2

필자의 경우 빈 열을 만들고 접근자를 설정하면 정상적으로 작동합니다. 내 접근자가 dob 열에서 사용자의 나이를 채우고 있습니다. toArray () 함수도 작동했습니다.

public function getAgeAttribute()
{
  return Carbon::createFromFormat('Y-m-d', $this->attributes['dateofbirth'])->age;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.