TL; DR:为什么Doctrine的ArrayCollection仅支持在不设置密钥的情况下映射数组?
我想从我的Doctrine实体创建一个关联数组(key-> value):ie customerId => CustomerName
,userId => userName
等。创建一个关联数组不是火箭科学,所以还有很多其他方法可以实现这一目标。
但是,我仍然想知道为什么ArrayCollection:map
(或类似的方法)没有选项来执行此操作。使用键创建数组是由它的构造方法和ArrayCollection::set()
支持的。你甚至可以创建一个这样的数组:
$arraycollection = new ArrayCollection();
$arraycollection->add('John Doe');
$arraycollection->set('foo', 'bar');
$arraycollection->set(418, 'teapot');
但您无法使用ArrayCollection::map()
设置密钥。为什么?我是第一个寻找这样的功能的开发人员(不太可能),还是我错过了一个重要原则,使其成为不必要的,不可能的,不可取的或不良的做法?
答案 0 :(得分:2)
我找到了这个答案Adam Wathan的博客 Customizing Keys When Mapping Collections :
想要在地图操作期间自定义键的问题是 我经常被问到的事情。
我认为它看起来像一个棘手问题的原因是因为在PHP中, 我们使用相同的数据类型来表示list和dictionary。
他使用Laravel的Collection库:
$emailLookup = $employees->reduce(function ($emailLookup, $employee) {
$emailLookup[$employee['email']] = $employee['name'];
return $emailLookup;
}, []);
这正是我想要使用的解决方案,但它不在Doctrine的ArrayCollection中。由于向后兼容性,添加reduce()方法的pull request已关闭。
感谢this example,您可以根据Doctrine的ArrayCollection实现自己的类:
use Doctrine\Common\Collections\ArrayCollection;
class ExtendedArrayCollection extends ArrayCollection
{
/**
* Reduce the collection into a single value.
*
* @param \Closure $func
* @param null $initialValue
* @return mixed
*/
public function reduce(\Closure $func, $initialValue = null)
{
return array_reduce($this->toArray(), $func, $initialValue);
}
}
答案 1 :(得分:1)
这就是source code:
中ArrayCollection
类的描述方式
ArrayCollection
是一个包含常规PHP数组的Collection
实现。
它的map()
方法只是array_map()
的包装器,它返回一个新的ArrayCollection
对象,该对象包装array_map()
返回的PHP数组。
为了使一切清楚,array_map()
为数组的每个元素调用一个函数(它的第一个参数);函数返回的值存储在结果数组中。
例如:
$input = [ 'one' => 1, 'two' => 2, 'three' => 3, ];
$output = array_map(function ($x) { return $x * $x; }, $input);
print_r($output);
输出:
Array
(
[one] => 1
[two] => 4
[three] => 9
)
可以使用一个或多个数组(从第二个参数开始)调用 array_map()
。 ArrayCollection::map()
仅使用一个数组(它包装的数组)调用它。当使用单个数组调用它时,array_map()
会保留其字符串键(但重新编号数字键)。
<强>修订:强>
ArrayCollection::map()
未设置键或值。它将函数应用于存储在集合中的所有值,并返回一个新集合。
如果需要在类型为ArrayCollection
的对象中的指定键上放置值,则可以使用常规PHP语法access array elements using square brackets。
以下代码与您在问题中发布的代码等效。
$arraycollection = new ArrayCollection();
$arraycollection[] = 'John Doe';
$arraycollection['foo'] = 'bar';
$arraycollection[418] = 'teapot';
使用方括号进行访问是有效的,因为ArrayCollection
类实现了扩展Collection
接口的ArrayAccess
接口。
答案 2 :(得分:0)
但您无法使用ArrayCollection :: map()设置密钥。
地图不是将集合转换为地图的功能。
通常,map函数对列表中的值进行操作,并且独立于数据结构,因此ArrayCollection:map的行为非常自然。