Php array#map并将2个参数传递给映射函数-array#map():参数#3应为数组
我有一个抽象类,如下所示:Php array#map并将2个参数传递给映射函数-array#map():参数#3应为数组,php,laravel,laravel-4,Php,Laravel,Laravel 4,我有一个抽象类,如下所示: abstract class Transformer { /** * Transform a collection of items * * @param array $items * @param bool $format * @return array */ public function transformCollection(array $items, $format) {
abstract class Transformer {
/**
* Transform a collection of items
*
* @param array $items
* @param bool $format
* @return array
*/
public function transformCollection(array $items, $format)
{
return array_map([$this, 'transform'], $items, $format);
}
/**
* Transform a item
*
* @param array $item
* @param bool $format
* @return mixed
*/
public abstract function transform(array $item, $format);
}
然后我有以下实现它的类:
class ServiceLogTransformer extends Transformer {
public function transform(array $service_log, $format = false)
{
return [
'id' => $service_log['id'],
'date' => $service_log['log_date'],
'time' => $service_log['log_time'],
'type' => ($format ? status_label($service_log['log_type']) : $service_log['log_type']),
'entry' => $service_log['log_entry']
];
}
}
当此代码运行时,我得到错误:
数组_映射():参数#3应为数组
在类中调用array\u map
函数时,如何传递2个或多个参数?我查看了PHP文档,看起来这是允许的,但它在我的Larave 4.2项目中不起作用
有什么想法吗?请务必阅读文档: 但您将bool
$format
作为参数传递
“调用数组\映射函数时,如何传递2个或多个参数
在一个班级里
我将使用use()
语法创建匿名函数
public function transformCollection(array $items, $format)
{
return array_map(function($item) use ($format) {
return $this->transform($item, $format);
}, $items);
}
不能使用
array\u map
将硬编码值传递给回调函数(通常称为currying
或函数语言中部分应用的函数).array\u map
采用的数组数量可变,所有数组都应具有相同数量的元素。每个数组当前索引处的元素作为单独的参数传递给回调。因此,例如,如果执行此操作:
$arr1 = [1, 2, 3, 4];
$arr2 = [2, 4, 6, 8];
$func = function ($a, $b) { return $a.'-'.$b; };
$arr3 = array_map($func, $arr1, $arr2);
你得到这个:
['1-2', '2-4', '3-6', '4-8']
希望这能解释它背后的想法——传入的每个数组都会将第一个数组中当前位置的元素作为相关参数传递给回调函数
因此,正如我所说,它不用于向回调传递“静态”值。但是,您可以通过动态定义匿名函数来实现这一点。在transformCollection
方法中:
return array_map(function ($item) use ($format) {
return $this->transform($item, $format);
}, $items);
大多数答案表明,带有
use
关键字的匿名函数是将附加参数传递给其他可调用函数的典型方式
abstract class Transformer {
public function transformCollection(array $items, $format)
{
return array_map(function($item) use ($format) {
return $this->transform($item, $format);
}, $items);
}
}
不过,最有可能的情况是,标准的foreach
循环覆盖array\u map
,更适合这种特殊情况,因为它可能更高效、更易于阅读。这还可以防止索引被重新编号,以及使用可遍历的和ArrayAccess
项
abstract class Transformer {
public function transformCollection(array $items, $format)
{
foreach($items as $key => $item) {
$items[$key] = $this->transform($item, $format);
}
return $items;
}
}
如果你真的想使用array\u map
,匿名函数不适合你的环境(即PHP5.3之前的版本),你需要传递$format
作为第二个参数,那么你需要将$format
转换成与$items
长度相同的数组
abstract class Transformer {
public function transformCollection(array $items, $format)
{
// Fill an array of same length as $items with the $format argument.
$format = array_fill(0, count($items), $format);
return array_map([$this, 'transform'], $items, $format);
}
}
编辑:
我最近意识到,由于您正在使用实例转换数据,所以还有另一个选项可用。它涉及到将$format
存储到实例中,可能使用setter,并在作为参数提供时覆盖它。这样,就可以通过使用$This->format
的转换方法访问它
abstract class Transformer {
protected $format;
public function setFormat($format)
{
$this->format = $format;
}
public function transformCollection(array $items, $format = null)
{
if (isset($format)) {
$this->setFormat($format);
}
// ...
}
// ...
}
这可能不适用于Laravel4.2//PHP5.3之前的版本(正如Shaun提到的),但对于一些遇到这个问题的人来说可能会很有用
abstract class Transformer {
/**
* Transform a collection of items
*
* @param array $items
* @param bool $format
* @return array
*/
public function transformCollection(array $items, $format)
{
$args = func_get_args();
return $this->mapWith([$this, 'transform'], $args);
}
/**
* @param callback<array|string> $callback
* @param array $args first a collection to disect, then optional additional arguments to the callback
* @return array
*/
private function mapWith($callback, $args) {
$data = array_shift($args);
$closure = \Closure::fromCallable($callback);
$scope = \is_array($callback) ? $callback[0] : null;
return array_map(function ($item) use ($scope, $closure, $args) {
array_unshift($args, $item);
if (null !== $scope) {
array_unshift($args, $scope);
$closure = [$closure, 'call'];
}
return \call_user_func_array($closure, $args);
}, $data);
}
/**
* Transform a item
*
* @param array $item
* @param bool $format
* @return mixed
*/
public abstract function transform(array $item, $format);
}
function status_label($index){return vsprintf('label: %s', [$index,]);}
#Then I have the following class that implements it:
class ServiceLogTransformer extends Transformer {
public function transform(array $service_log, $format = false)
{
return [
'id' => $service_log['id'],
'date' => $service_log['log_date'],
'time' => $service_log['log_time'],
'type' => ($format ? status_label($service_log['log_type']) : $service_log['log_type']),
'entry' => $service_log['log_entry']
];
}
}
$logs = [
['id' => 123454, 'log_date'=>'20180926', 'log_time'=>'151913', 'log_type'=>'q', 'log_entry' => 'lorem',],
['id' => 353454, 'log_date'=>'20180926', 'log_time'=>'152013', 'log_type'=>'r', 'log_entry' => 'dolor',],
];
$slt = new ServiceLogTransformer();
$new = $slt->transformCollection($logs, false);
$lab = $slt->transformCollection($logs, true);
var_dump($logs);
var_dump($new);
var_dump($lab);
抽象类转换器{
/**
*转换项目集合
*
*@param数组$items
*@param bool$格式
*@return数组
*/
公共函数集合(数组$items,$format)
{
$args=func_get_args();
返回$this->mapWith([$this,'transform'],$args);
}
/**
*@param callback$callback
*@param array$args首先是要分离的集合,然后是回调的可选附加参数
*@return数组
*/
私有函数mapWith($callback,$args){
$data=数组移位($args);
$closure=\closure::fromCallable($callback);
$scope=\is_数组($callback)?$callback[0]:null;
返回数组映射(函数($item)使用($scope、$closure、$args){
数组_unshift($args,$item);
如果(空!==$scope){
数组_unshift($args,$scope);
$closure=[$closure,'call'];
}
return\call\u user\u func\u数组($closure,$args);
}美元数据);
}
/**
*变换项目
*
*@param数组$item
*@param bool$格式
*@返回混合
*/
公共抽象函数转换(数组$item,$format);
}
函数状态_label($index){return vsprintf('label:%s',[$index,]);}
#然后我有以下实现它的类:
类ServiceLogTransformer扩展了Transformer{
公共函数转换(数组$service\u log,$format=false)
{
返回[
'id'=>$service_log['id'],
'date'=>$service\u log['log\u date'],
'time'=>$service\u log['log\u time'],
'type'=>($format?status_label($service_log['log_type']):$service_log['log_type']),
'entry'=>$service\u log['log\u entry']
];
}
}
$logs=[
['id'=>123454,'log\u date'=>20180926','log\u time'=>151913','log\u type'=>q','log\u entry'=>lorem',],
['id'=>353454,'log\u date'=>20180926','log\u time'=>152013','log\u type'=>r','log\u entry'=>dolor',],
];
$slt=新的ServiceLogTransformer();
$new=$slt->transformCollection($logs,false);
$lab=$slt->transformCollection($logs,true);
var_dump($logs);
var_dump(新);
var_dump(实验室);
因此,这是一种动态使用,通过在php匿名函数下面的闭包类上使用call方法。如果回调是数组,它将->call的范围绑定到第一个数组元素,该元素应该是该方法的对象
abstract class Transformer {
/**
* Transform a collection of items
*
* @param array $items
* @param bool $format
* @return array
*/
public function transformCollection(array $items, $format)
{
$args = func_get_args();
return $this->mapWith([$this, 'transform'], $args);
}
/**
* @param callback<array|string> $callback
* @param array $args first a collection to disect, then optional additional arguments to the callback
* @return array
*/
private function mapWith($callback, $args) {
$data = array_shift($args);
$closure = \Closure::fromCallable($callback);
$scope = \is_array($callback) ? $callback[0] : null;
return array_map(function ($item) use ($scope, $closure, $args) {
array_unshift($args, $item);
if (null !== $scope) {
array_unshift($args, $scope);
$closure = [$closure, 'call'];
}
return \call_user_func_array($closure, $args);
}, $data);
}
/**
* Transform a item
*
* @param array $item
* @param bool $format
* @return mixed
*/
public abstract function transform(array $item, $format);
}
function status_label($index){return vsprintf('label: %s', [$index,]);}
#Then I have the following class that implements it:
class ServiceLogTransformer extends Transformer {
public function transform(array $service_log, $format = false)
{
return [
'id' => $service_log['id'],
'date' => $service_log['log_date'],
'time' => $service_log['log_time'],
'type' => ($format ? status_label($service_log['log_type']) : $service_log['log_type']),
'entry' => $service_log['log_entry']
];
}
}
$logs = [
['id' => 123454, 'log_date'=>'20180926', 'log_time'=>'151913', 'log_type'=>'q', 'log_entry' => 'lorem',],
['id' => 353454, 'log_date'=>'20180926', 'log_time'=>'152013', 'log_type'=>'r', 'log_entry' => 'dolor',],
];
$slt = new ServiceLogTransformer();
$new = $slt->transformCollection($logs, false);
$lab = $slt->transformCollection($logs, true);
var_dump($logs);
var_dump($new);
var_dump($lab);