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