Php 仅从Laravel集合获取特定属性

Php 仅从Laravel集合获取特定属性,php,laravel,Php,Laravel,我一直在查看Laravel系列的文档和API,但似乎没有找到我想要的: 我想从集合中检索包含模型数据的数组,但只获取指定的属性 例如,类似于Users::toArray('id','name','email'),其中集合实际上包含用户的所有属性,因为它们在其他地方使用,但在这个特定位置,我需要一个包含userdata的数组,并且只包含指定的属性 在拉雷维尔,似乎没有一个帮手来帮你我怎样才能用最简单的方法做到这一点 您需要定义$hidden和$visible属性。它们将被设置为全局(这意味着总是从

我一直在查看Laravel系列的文档和API,但似乎没有找到我想要的:

我想从集合中检索包含模型数据的数组,但只获取指定的属性

例如,类似于
Users::toArray('id','name','email')
,其中集合实际上包含用户的所有属性,因为它们在其他地方使用,但在这个特定位置,我需要一个包含userdata的数组,并且只包含指定的属性

在拉雷维尔,似乎没有一个帮手来帮你我怎样才能用最简单的方法做到这一点

  • 您需要定义
    $hidden
    $visible
    属性。它们将被设置为全局(这意味着总是从
    $visible
    数组返回所有属性)

  • 使用方法
    makeVisible($attribute)
    makeHidden($attribute)
    可以动态更改隐藏和可见属性。更多:

  • 使用
    User::get(['id'、'name'、'email'])
    ,它将返回一个包含指定列的集合,如果您想将其设置为数组,只需在
    get()
    方法之后使用
    toArray()
    ,如下所示:

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


    大多数情况下,您不需要将集合转换为数组,因为集合实际上是类固醇上的数组,并且您有易于使用的方法来操作集合。

    我现在想出了自己的解决方案:

    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。通过Laravel定制系列实现上述功能

    因为我希望能够简单地执行
    $collection->extract('id','url')
    首先,我创建了一个通用模型,它扩展了雄辩的模型,但使用了不同的集合类。所有的模型都需要扩展这个定制模型,而不是雄辩的模型

    <?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
    {
    ...
    

    您可以使用现有的
    集合
    方法的组合来完成此操作。一开始可能有点难以理解,但分解起来应该足够容易

    // 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()
    方法基本上只是迭代
    集合
    ,并将
    集合
    中的每个项传递给传入的回调。每次回调调用返回的值构建由
    map()
    方法生成的新
    集合

    collect($user->toArray())
    只是从
    Users
    属性中构建一个新的、临时的
    Collection

    ->only(['id','name','email'])
    将临时
    集合减少到只指定那些属性

    ->all()
    将临时
    集合
    转换回普通数组

    把它们放在一起,您会得到“对于用户集合中的每个用户,返回一个仅包含id、名称和电子邮件属性的数组。”


    Laravel 5.5更新 Laravel 5.5在模型上添加了一个
    only
    方法,该方法基本上与
    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']);
    });
    
    如果将其与Laravel 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']);
    

    这似乎可行,但不确定是否针对性能进行了优化

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

    输出:

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

    我有一个类似的问题,我需要从一个大数组中选择值,但我希望得到的集合只包含单个值的值

    pluck()
    可用于此目的(如果只需要一个关键项)

    您还可以使用
    reduce()
    。与reduce类似的内容:

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

    这是上面patricus[answer][1]的后续内容,但对于嵌套数组:


    这避免了直接从数据库加载统一属性:

    DB::table('roles')->pluck('title', 'name');
    
    参考文献:(搜索弹拨)


    也许下一步您可以应用
    toArray()
    ,如果您需要这种格式,下面的方法也可以

    $users = User::all()->map(function ($user) {
      return collect($user)->only(['id', 'name', 'email']);
    });
    
    上下文 例如,假设您希望显示一个表单,用于在一个系统中创建新用户,该用户有一个角色,并且该角色可用于多个用户

    用户模型如下所示

    class User extends Authenticatable
    {   
        /**
         * User attributes.
         *
         * @var array
         */
        protected $fillable = [
            'name', 'email', 'password', 'role_id'
        ];
    
    
        /**
         * Role of the user
         *
         * @return \App\Role
         */
        public function role()
        {
            return $this->belongsTo(Role::class);
        }
    ...
    
    以及榜样

    class Role extends Model
    {
        /**
         * Role attributes.
         *
         * @var array
         */
        protected $fillable = [
            'name', 'description'
        ];
        
        /**
         * Users of the role
         *
         * @return void
         */
        public function users()
        {
            return $this->hasMany(User::class);
        }
    }
    

    如何仅获取特定属性? 在我们想要创建的特定表单中,您需要来自角色的数据,但实际上不需要描述

    /**
     * Create user
     *
     * @param  \App\Role  $model
     * @return \Illuminate\View\View
     */
    public function create(Role $role)
    {
        return view('users.create', ['roles' => $role->get(['id', 'name'])]);
    }
    

    请注意,我们正在使用
    $role->get(['id',name'])
    来指定我们不需要描述。

    我不希望这是全局的,但选择要从集合中动态提取的属性。集合已由上一个查询创建,其中需要更多属性。因此,我需要生成一个只具有特定属性的数据数组。您可以通过传递要返回的列数组使查询动态化,也可以执行另一个
    ->get(['id',email',name'])
    操作,该操作不会重新查询数据库,但将返回一个仅包含选定值的新集合。像Pull/List、get、first等方法在这两种方法中都有相同的名称,q
    /**
     * Create user
     *
     * @param  \App\Role  $model
     * @return \Illuminate\View\View
     */
    public function create(Role $role)
    {
        return view('users.create', ['roles' => $role->get(['id', 'name'])]);
    }
    
    /**
     * Create user
     *
     * @param  \App\Role  $model
     * @return \Illuminate\View\View
     */
    public function create(Role $role)
    {
        return view('users.create', ['roles' => $role->get(['id', 'name'])]);
    }