support sirve que para illuminate collection array php laravel

php - sirve - Obtenga solo atributos específicos de Laravel Collection



merge collections laravel (7)

  1. Debe definir los atributos $hidden y $visible . Se establecerán globalmente (eso significa siempre devolver todos los atributos desde $visible array).

  2. Usando el método makeVisible($attribute) y makeHidden($attribute) puede cambiar dinámicamente los atributos ocultos y visibles. Más: Elocuente: Serialización -> Modificación temporal de la visibilidad de la propiedad

He estado revisando la documentación y la API de las colecciones de Laravel, pero no encuentro lo que estoy buscando:

Me gustaría recuperar una matriz con datos de modelo de una colección, pero solo obtengo atributos especificados.

Es decir, algo así como Users::toArray(''id'',''name'',''email'') , donde la colección tiene todos los atributos para los usuarios, porque se usan en otros lugares, pero en este lugar específico necesito una matriz con userdata y solo los atributos especificados

No parece haber un ayudante para esto en Laravel? - ¿Cómo puedo hacer esto de la manera más fácil?


Ahora he encontrado una solución propia para esto:

1. Creó una función general para extraer atributos específicos de matrices

La función a continuación extrae solo atributos específicos de una matriz asociativa, o una matriz de matrices asociativas (la última es lo que obtienes al hacer $ collection-> toArray () en Laravel).

Se puede usar así:

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

Estoy usando las siguientes funciones:

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; }

Esta solución no se centra en las implicaciones de rendimiento al recorrer las colecciones en grandes conjuntos de datos.

2. Implementa lo anterior a través de una colección personalizada i Laravel

Como me gustaría poder hacer simplemente $collection->extract(''id'',''url''); en cualquier objeto de colección, he implementado una clase de colección personalizada.

Primero creé un Modelo general, que amplía el modelo Eloquent, pero usa una clase de colección diferente. Todos los modelos necesitan extender este modelo personalizado, y no el modelo 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 ); } } ?>

En segundo lugar, creé la siguiente clase de colección personalizada:

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

Por último, todos los modelos deberían ampliar su modelo personalizado, como ese:

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

Ahora las funciones de no. 1 arriba son usados ​​por la colección para hacer que el método $collection->extract() esté disponible.


Puede hacerlo utilizando una combinación de métodos de Collection existentes. Puede ser un poco difícil de seguir al principio, pero debería ser lo suficientemente fácil de romper.

// 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(); });

Explicación

Primero, el método map() simplemente itera a través de la Collection y pasa cada elemento de la Collection a la devolución de llamada pasada. El valor devuelto por cada llamada de la devolución de llamada genera la nueva Collection generada por el método map() .

collect($user->toArray()) solo está creando una Collection nueva y temporal fuera de los atributos de los Users .

->only([''id'', ''name'', ''email'']) reduce la Collection temporal a solo aquellos atributos especificados.

->all() convierte la Collection temporal de nuevo en una matriz simple.

Póngalo todo junto y obtendrá "Para cada usuario en la colección de usuarios, devuelva una matriz de solo los atributos de identificación, nombre y correo electrónico".

Actualización de Laravel 5.5

Laravel 5.5 agregó un only método en el Modelo, que básicamente hace lo mismo que el collect($user->toArray())->only([...])->all() , por lo que esto se puede simplificar levemente en 5.5+ a:

// 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'']); });


Tuve un problema similar cuando necesitaba seleccionar valores de una matriz grande, pero quería que la colección resultante solo contuviera valores de un solo valor.

pluck() podría usarse para este propósito (si solo se requiere 1 elemento clave)

también puedes usar reduce() . Algo como esto con reduce:

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


esto es un seguimiento en el patricus [respuesta] [1] anterior pero para matrices anidadas :

$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();


esto parece funcionar, pero no estoy seguro si está optimizado para el rendimiento o no.

$request->user()->get([''id''])->groupBy(''id'')->keys()->all();

salida:

array:2 [ 0 => 4 1 => 1 ]


use User::get([''id'', ''name'', ''email'']) , le devolverá una colección con las columnas especificadas y si desea hacer una matriz, simplemente use toArray() después del get() método como tal:

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

La mayoría de las veces, no necesitará convertir la colección a una matriz porque las colecciones son en realidad matrices con esteroides y tiene métodos fáciles de usar para manipular la colección.