Возврат новой коллекции без изменения оригинальной коллекции - PullRequest
0 голосов
/ 01 ноября 2019

У меня есть коллекция Laravel, и я хочу изменить одно из значений ее свойства на отрицательное целое число. Для этого я использую метод коллекции map, но он также изменяет исходную коллекцию.

Мой код:

$modified_revenue_data = $revenue_data->map(function ($item) {
    if ($item->is_claw_back == 1 && $item->claw_back_date != null) {
        return $item->revenue = $item->revenue * -1;
    }

    return $item;
});

Я хочу сохранить новую коллекцию в $modified_revenue_data, но *Также изменяется 1008 *.

Как правильно сделать это, не изменяя исходную коллекцию?

Ответы [ 2 ]

0 голосов
/ 01 ноября 2019

Я думаю, вы можете сделать это, используя cloning, потому что внутри вашего обратного вызова переменная $user является ссылкой.

$modified_revenue_data = $revenue_data->map(function ($item) {
    $clone = clone $item;
    if ($clone->is_claw_back == 1 && $clone->claw_back_date != null) {
        return $clone->revenue = $clone->revenue * -1;
    }
    return $clone;
});

PHPссылка - это псевдоним, который позволяет двум разным переменным записывать одно и то же значение. Начиная с PHP5, переменная объекта больше не содержит сам объект в качестве значения. Он содержит только идентификатор объекта, который позволяет методам доступа к объекту найти фактический объект. Когда объект отправляется с помощью аргумента, возвращается или присваивается другой переменной, различные переменные не являются псевдонимами: они содержат копию идентификатора, который указывает на тот же объект.

Попробуйте этот пример, чтобыполучить четкое представление о том, что происходит

class User {
  public $name;
  public $age;
  function __construct($name, $age){
    $this->name = $name;
    $this->age =  $age;
  }
}

$a = collect([1, 2, 3, 4, 5]);

$b = $a->map(function ($el) {
     return $el = $el * 2;
});

/*
$a =  [
    0 => 1
    1 => 2
    2 => 3
    3 => 4
    4 => 5
];

$b = [
    0 => 2
    1 => 4
    2 => 6
    3 => 8
    4 => 10
  ]
*/

$users = collect([
  new User('Dan', 27),
  new User('Mark', 18)
]);

$moreUsers = $users->map(function($user){
  $mUser = clone $user;
  $mUser->age++;
  return $mUser;
});

/*
$users = array:2 [
    0 => User^ {#2
      +name: "Dan"
      +age: 27
    }
    1 => User^ {#5
      +name: "Mark"
      +age: 18
    }
]

$moreUsers = array:2 [
    0 => User^ {#8
      +name: "Dan"
      +age: 28
    }
    1 => User^ {#9
      +name: "Mark"
      +age: 19
    }
]
*/
0 голосов
/ 01 ноября 2019

Не должно обновлять оригинальную коллекцию. Я провел небольшой тест и могу подтвердить, что это поведение метода map():

$a = collect([1, 2, 3, 4, 5]);

$b = $a->map(function ($el) {
     return $el * 2; 
});

dd($b);
=> Illuminate\Support\Collection {#3726
     all: [
       2,
       4,
       6,
       8,
       10,
     ],
   }
dd($a);
=> Illuminate\Support\Collection {#3743
     all: [
       1,
       2,
       3,
       4,
       5,
     ],
   }

Это поведение также указано в документации :

map ()

...

Как и большинство других методов сбора, карта возвращает новую коллекцию экземпляр; не изменяет коллекцию, к которой она вызывается. Если вы хотите преобразовать исходную коллекцию, используйте метод transform().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...