[php] Laravel 컬렉션에서 특정 속성 만 가져옵니다.

Laravel Collections에 대한 문서와 API를 검토했지만 원하는 것을 찾지 못하는 것 같습니다.

컬렉션에서 모델 데이터가있는 배열을 검색하고 싶지만 지정된 속성 만 가져옵니다.

Users::toArray('id','name','email'), 컬렉션은 다른 곳에서 사용되기 때문에 실제로 사용자에 대한 모든 속성을 보유하지만이 특정 장소에서는 사용자 데이터가있는 배열과 지정된 속성 만 필요합니다.

라 라벨에 이것에 대한 도우미가없는 것 같습니까? -가장 쉬운 방법은 무엇입니까?



답변

기존 Collection방법 의 조합을 사용하여이를 수행 할 수 있습니다 . 처음에는 따라하기가 조금 어려울 수 있지만 무너질만큼 쉬워야합니다.

// get your main collection with all the attributes...
$users = Users::get();

// build your second collection with a subset of attributes. this new
// collection will be a collection of plain arrays, not Users models.
$subset = $users->map(function ($user) {
    return collect($user->toArray())
        ->only(['id', 'name', 'email'])
        ->all();
});

설명

첫째, map()메서드는 기본적으로을 반복하고의 Collection각 항목을 Collection전달 된 콜백에 전달합니다. 콜백의 각 호출에서 반환 된 값 Collectionmap()메서드에 의해 생성 된 새 항목을 빌드합니다 .

collect($user->toArray())속성 에서 새롭고 일시적인 Collection것을 만드는 것입니다 Users.

->only(['id', 'name', 'email'])Collection지정된 속성 만 임시 로 줄 입니다.

->all()임시 Collection배열을 일반 배열로 되돌립니다.

모두 합치면 “사용자 컬렉션의 각 사용자에 대해 ID, 이름 및 이메일 속성의 배열 만 반환합니다.”라는 메시지가 표시됩니다.


Laravel 5.5 업데이트

Laravel 5.5는 only기본적으로와 동일한 작업을 수행 하는 메서드를 Model에 추가했습니다 collect($user->toArray())->only([...])->all(). 따라서 5.5+ 에서는 다음과 같이 약간 단순화 할 수 있습니다.

// get your main collection with all the attributes...
$users = Users::get();

// build your second collection with a subset of attributes. this new
// collection will be a collection of plain arrays, not Users models.
$subset = $users->map(function ($user) {
    return $user->only(['id', 'name', 'email']);
});

이것을 라 라벨 5.4에 도입 된 컬렉션에 대한 “고급 메시징” 과 결합하면 더욱 단순화 할 수 있습니다.

// get your main collection with all the attributes...
$users = Users::get();

// build your second collection with a subset of attributes. this new
// collection will be a collection of plain arrays, not Users models.
$subset = $users->map->only(['id', 'name', 'email']);


답변

use User::get(['id', 'name', 'email']), 지정된 열이있는 컬렉션을 반환하고 배열로 만들려면 toArray()다음 get()과 같은 메서드 뒤에 사용 하십시오 .

User::get(['id', 'name', 'email'])->toArray()

대부분의 경우 컬렉션은 실제로 스테로이드의 배열이고 컬렉션을 조작하는 데 사용하기 쉬운 메서드가 있으므로 컬렉션을 배열로 변환 할 필요가 없습니다.


답변

아래 방법도 작동합니다.

$users = User::all()->map(function ($user) {
  return collect($user)->only(['id', 'name', 'email']);
});


답변

나는 이제 이것에 대한 자체 해결책을 생각해 냈습니다.

1. 배열에서 특정 속성을 추출하는 일반 함수 생성

아래 함수는 연관 배열 또는 연관 배열의 배열에서 특정 속성 만 추출합니다 (마지막은 Laravel에서 $ collection-> toArray ()를 수행 할 때 얻는 것입니다).

다음과 같이 사용할 수 있습니다.

$data = array_extract( $collection->toArray(), ['id','url'] );

다음 기능을 사용하고 있습니다.

function array_is_assoc( $array )
{
        return is_array( $array ) && array_diff_key( $array, array_keys(array_keys($array)) );
}



function array_extract( $array, $attributes )
{
    $data = [];

    if ( array_is_assoc( $array ) )
    {
        foreach ( $attributes as $attribute )
        {
            $data[ $attribute ] = $array[ $attribute ];
        }
    }
    else
    {
        foreach ( $array as $key => $values )
        {
            $data[ $key ] = [];

            foreach ( $attributes as $attribute )
            {
                $data[ $key ][ $attribute ] = $values[ $attribute ];
            }
        }
    }

    return $data;
}

이 솔루션은 대규모 데이터 세트의 컬렉션을 반복 할 때 성능에 미치는 영향에 초점을 맞추지 않습니다.

2. 사용자 지정 컬렉션을 통해 위의 구현 i Laravel

$collection->extract('id','url');모든 컬렉션 개체에 대해 간단히 수행 할 수 있기를 원 하기 때문에 사용자 지정 컬렉션 클래스를 구현했습니다.

먼저 Eloquent 모델을 확장하지만 다른 컬렉션 클래스를 사용하는 일반 모델을 만들었습니다. 모든 모델은 Eloquent 모델이 아니라이 커스텀 모델을 확장해야합니다.

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model as EloquentModel;
use Lib\Collection;
class Model extends EloquentModel
{
    public function newCollection(array $models = [])
    {
        return new Collection( $models );
    }
}
?>

둘째로 다음과 같은 사용자 지정 컬렉션 클래스를 만들었습니다.

<?php
namespace Lib;
use Illuminate\Support\Collection as EloquentCollection;
class Collection extends EloquentCollection
{
    public function extract()
    {
        $attributes = func_get_args();
        return array_extract( $this->toArray(), $attributes );
    }
}
?>

마지막으로, 모든 모델은 다음과 같이 대신 사용자 지정 모델을 확장해야합니다.

<?php
namespace App\Models;
class Article extends Model
{
...

이제 기능이 없습니다. 위의 1은 컬렉션에서 $collection->extract()메서드를 사용할 수 있도록 깔끔하게 사용됩니다 .


답변

  1. $hidden$visible속성 을 정의해야 합니다. 전역으로 설정됩니다 (즉, 항상 $visible배열 에서 모든 속성을 반환 함 ).

  2. 방법을 사용 makeVisible($attribute)하고 makeHidden($attribute)동적 숨겨진 변경하고 눈에 보이는 속성. 추가 : Eloquent : 직렬화-> 일시적으로 속성 가시성 수정


답변

큰 배열에서 값을 선택해야하는 비슷한 문제가 있었지만 결과 컬렉션에 단일 값의 값만 포함되기를 원했습니다.

pluck() 이 용도로 사용할 수 있습니다 (단 하나의 키 항목 만 필요한 경우).

당신은 또한 사용할 수 있습니다 reduce(). 다음과 같이 축소하십시오.

$result = $items->reduce(function($carry, $item) {
    return $carry->push($item->getCode());
}, collect());


답변

이것은 위의 patricus [answer] [1]에 대한 후속 조치이지만 중첩 배열에 대한 것입니다.

$topLevelFields =  ['id','status'];
$userFields = ['first_name','last_name','email','phone_number','op_city_id'];

return $onlineShoppers->map(function ($user) {
    return collect($user)->only($topLevelFields)
                             ->merge(collect($user['user'])->only($userFields))->all();
    })->all();