Laravel 5: Change array passed via $request - php

I have this statement:
$request->lines[$i]['price_ex_vat'] = preg_replace("/([^0-9\\.])/i", "", $request->lines[$i]['price_ex_vat']);
Its purpose is to remove the currency formatting on a value but I get the error Indirect modification of overloaded property Illuminate\Http\Request::$lines has no effect
Googling tells me I need to use ->merge() but it is just not sinking in how to do that. Any help appreciated.

As Laravel uses Symfony's ParameterBag to store the request's data it internally does this:
$p = new \Symfony\Component\HttpFoundation\ParameterBag(['foo' => 'bar', 'baz' => 'qux']);
$p->add(['baz' => 'xyz']);
dump(
$p->all()
);
Which prints out:
array:2 [
"foo" => "bar"
"baz" => "xyz"
]
Laravel's request exposes merge method that calls ParameterBag's add method internally. All is good until you manipulate one dimension data.
In your case, the solution could be like this:
$request = \Illuminate\Http\Request::create('/', 'POST',
[
'lines' => [
['price_ex_vat' => 'foo'],
['price_ex_vat' => 'bar'],
['price_ex_vat' => 'baz'],
],
]
);
$data = $request->input();
$data['lines'][1]['price_ex_vat'] = 'xyz'; // preg_replace or whatever you want.
dd(
$request->merge($data)->input();
);
Which prints accordingly:
array:1 [
"lines" => array:3 [
0 => array:1 [
"price_ex_vat" => "foo"
]
1 => array:1 [
"price_ex_vat" => "xyz"
]
2 => array:1 [
"price_ex_vat" => "baz"
]
]
]

I assume $request->lines is an array you are iterating through and want to change price_ex_vat on it. I would suggest making a separate variable to do the changes on it, then use merge to replace $request->lines
$arr = $request->lines;
foreach($arr as $line){ //or you can use a normal for loop if you prefer
$line['price_ex_vat'] = preg_replace("/([^0-9\\.])/i", "", $line['price_ex_vat']); //your changes here
}
$request->merge('lines',$arr);

Related

PHP array_slice or equivalent on array of arrays that are keyed by ID

I have a multi-dimensional array that is keyed by uuid's and need to slice/pop/unset an element by uuid (i.e., if I had a410463e-7fe2-4fba-8733-a812c0ee8c54 and wanted to remove that item by that uuid) so that the result is essentially the same minus the one item that was removed:
array:5 [
"5fc29794-9e08-4944-ba6d-4a5fcde5c88b" => array:3 [
"id" => "5fc29794-9e08-4944-ba6d-4a5fcde5c88b"
"name" => "fuga"
"value" => 0
]
"a410463e-7fe2-4fba-8733-a812c0ee8c54" => array:3 [
"id" => "a410463e-7fe2-4fba-8733-a812c0ee8c54"
"name" => "nihil"
"value" => 0
]
"c141d973-91fe-4227-8985-04bd0665f4a8" => array:3 [
"id" => "c141d973-91fe-4227-8985-04bd0665f4a8"
"name" => "eaque"
"value" => 0
]
"17030897-1aa9-487d-a4be-d574dd0c9d9b" => array:3 [
"id" => "17030897-1aa9-487d-a4be-d574dd0c9d9b"
"name" => "eveniet"
"value" => 3
]
"901d9f8f-573f-444f-8562-0cdf5888ba6e" => array:3 [
"id" => "901d9f8f-573f-444f-8562-0cdf5888ba6e"
"name" => "in"
"value" => 6
]
]
I know how to slice by index, but am having trouble finding resources on how this might be achieved. This is for a phpunit test. I've tried unset, but can't seem to store that in a variable or just call it in an assertion:
unset($array1[$id]);
unset($array2[$id]);
Does not persist the change.
$newUnchanged = unset($array1[$id]);
$oldUnchanged = unset($array2[$id]);
Throws syntax error, unexpected 'unset' error. Ultimately I want to assert that all of the unchanged items remained the same as prior to a single item being updated. I've also tried this ugly business which is removing a single item, but not the correct one:
$keyOne = array_search($id, array_keys($array1), true);
$oldUnchanged = array_slice($array1, $keyOne, null, true);
$keyTwo = array_search($id, array_keys($array2), true);
$newUnchanged = array_slice($array2, $keyTwo, null, true);
// Shows that the item that I wanted to slice still exists in both arrays
dd($id, $oldUnchanged, $newUnchanged);
// ^ Causes this test to fail
$this->assertEquals($oldUnchanged, $newUnchaged);
I figured out I have to clone the arrays before I can unset them
$oldUnchanged = $array1;
unset($oldUnchanged[$id]);
$newUnchanged = $array2;
unset($newUnchanged[$id]);

Nested arrays with undefinded lenght: Get most nested array

I am doing a request to an API and for each request I get an array with the BrowseNodes back. Inside this array I get this result:
array:1 [
"BrowseNode" => array:3 [
"BrowseNodeId" => "2502033031"
"Name" => "OBD-II Diagnosewerkzeuge"
"Ancestors" => array:1 [
"BrowseNode" => array:3 [
"BrowseNodeId" => "5142250031"
"Name" => "Motorwerkzeuge & Zubehör"
"Ancestors" => array:1 [
"BrowseNode" => array:3 [
"BrowseNodeId" => "2502064031"
"Name" => "Werkzeuge"
"Ancestors" => array:1 [
"BrowseNode" => array:4 [
"BrowseNodeId" => "79899031"
"Name" => "Kategorien"
"IsCategoryRoot" => "1"
"Ancestors" => array:1 [
"BrowseNode" => array:2 [
"BrowseNodeId" => "78191031"
"Name" => "Auto & Motorrad"
]
]
]
]
]
]
]
]
]
]
If this would be a fixed array which always had this length it would be easy for me to get the last BrowseNode Array and the value with the key "Name". In this case it would be the this one "Name" => "Auto & Motorrad".
However, because a category can have one or more nested arrays, it is not static...
That means I have to find a solution to always get the most nested array and from this one the name to get the category. Because it is dynamic data, I don't know how to solve that. I just know I always have to get the BrowseNode and then inside the BrowseNode array. I have to get the Ancestors and inside this Ancestors again. I have to get the BrowseNode array until I arrived at the last BrowseNode array and the get the name.
So, I have to iterate through my array until the BrowseNode array doesn't have an Ancestors array anymore and the get the name of this BrowseNode array.
Do you guys have any idea on how to do this?
I guess you can use recursion to achieve that.
On each object, search for Ancestors, if not found return the name, else do so again on the Ancestors.
Consider the following code:
$arr = array("BrowseNode" => array("BrowseNodeId" => "1", "Ancestors" => array("BrowseNode" => array("BrowseNodeId" => "2", "Ancestors" => array("BrowseNode" => array("BrowseNodeId" => "3"))))));
function getLastName($elem) {
$elem = $elem["BrowseNode"];
if (!array_key_exists("Ancestors", $elem))
return $elem['BrowseNodeId'];
else return getLastName($elem["Ancestors"]);
}
echo getLastName($arr);
Notice that this code return id instead of your Name - small modification I leave to you...
There might be a more "correct" way of doing this but since I'm writing this on my phone on a plane, you'll have to forgive my not being able to proof check my answer. But you could do a recursive function, like...
function recurseArray($browseNode)
{
if(isset($browseNode["Ancestors"])) {
recurseArray($browseNode["Ancestors"]["browseNode"])
} else {
// Do whatever you want with the last iteration
}
}
Hope that makes sense!

Updating array keys inside of an array

My goal is to be able to update a key value inside of an array inside of an array and I'm don't know if I'm using the right php array function.
BEFORE:
array:2 [
"week_number" => 1
"games" => array:1 [
0 => array:3 [
"game_number" => 1
"umpires" => []
"teams" => []
]
]
]
AFTER:
array:2 [
"week_number" => 1
"games" => array:1 [
0 => array:3 [
"game_number" => 1
"umpires" => []
"teams" => [1,2]
]
]
]
Test Class:
private function validParams($overrides = [])
{
return array_merge_recursive([
'week_number' => 1,
'games' => [[
'game_number' => 1,
'umpires' => [],
'teams' => [],
]]
], $overrides);
}
$response = $this->actingAs($this->authorizedUser)
->post(route('games.store', ['week' => $this->week->id]), $this->validParams([
'games' => [][
[
'teams' => [1,2]
]
]
]));
If you want to update the keys... typing $array['new_key'] = $array['old_key'] will duplicate the value with 2 sets of keys.
You have a few options here. Either you create a new array and just set your desired keys or work with array_keys and array_values and mix them up... your choice
http://php.net/manual/en/ref.array.php
See the list above, there are a lot of array functions you can use... see the two above and array_map... there is virtually a great number of ways you can do this. See how your problem is best handled after reviewing the documentation.
Good luck!
This is the moment where you need unset(): Adding a value with a different key will not update or overwrite the old value but simply add another key-value pair.
Hence, add the new value fist, then unset the old one. We can use To array_walk to itterate over the array:
array_walk($array, function (& $item) {
$item['new_key'] = $item['old_key'];
unset($item['old_key']);
});
Take note of the & reference operator in the lambda function: it ensures we are working on the original array and not a copy of it.
I found this as a solution.
private function validParams($overrides = [])
{
return array_replace_recursive([
'week_number' => 1,
'games' => [
0 => [
'game_number' => 1,
'umpires' => [],
'teams' => [],
]
]
], $overrides);
}
->post(route('games.store', ['week' => $this->week->id]), $this->validParams([
'games' => [
0 => [
'teams' => [1,2]
]
]
]));

Refactoring objects using Laravel Collections fails

What I try to do is that I need to return an array with key-value pairs from an array of objects.
From an api I get objects that looks something like this.
array:8 [▼
0 => TargetingSearch {#229 ▼
#data: array:6 [▼
"id" => "6005609368513"
"name" => "Software"
"audience_size" => 565991450
"path" => array:4 [▶]
"description" => ""
"topic" => "Technology"
]
#_type_checker: TypeChecker {#228 ▶}
}
The simple way to do it is to loop through the objects and push the values into an array.
$codes = [];
foreach($objects as $object) {
$codes[] = [
'id' => $object->id,
'name' => $object->name,
];
}
Which will return this that is exactly what I need.
['id' => 321, 'name' => "item1"],
['id' => 321, 'name' => "item1"],
['id' => 321, 'name' => "item1"],
I think that this is a little hard to manage and what I try to do is something a little more readable.
For example, by using the Laravel collection classes I could do something like this.
$codes = collect($objects)->pluck('id', 'name')->toArray();
The problem here is that this does not return the keys.
["item1" => "123"],
["item2" => "321"],
["item3" => "213"],
If I use
$codes = collect($objects)->only('id', 'name')->toArray();
It returns an empty array because the object itself is messing it all up.
anyone knows how to solve this?
You can use "map" method
collect($objects)->map(function ($item) {
return [
'id' => $item->id,
'name' => $item->name
];
});

How to extract individual array values from JSON response using Guzzle and Laravel

I'm struggling to get data from JSON response. This is my code for getting the data:
$client = new Client;
$r = $client->get("http://my.api.com/get-campaign/" . $id . "?api_token=1235");
$apiResult = json_decode($r->getBody(), true);
dd($apiResult);
And I get something like this:
array:4 [
"campaign" => array:1 [
0 => array:3 [
"manufacturer" => "Sony"
"product" => "PlayStation 4"
"created_at" => "2015-07-04T00:00:00+00:00"
]
]
"media" => array:2 [
"video" => "https://my.domain.com/421156.mp4"
"images" => "https://my.domain.com/tv/thumbs/421156-1.jpg"
]
"statistics" => array:3 [
"runs" => 172
"firstseen_at" => "2015-07-04T19:06:41+00:00"
"lastseen_at" => "2015-07-09T12:04:13+00:00"
]
"broadcasts" => array:172 []
]
How can I get single values from this response? Let's say I want to display, or assign to another variable the value of "manufacturer" and in another variable to store number of runs ("runs")?
For manufacturer I've tried to do something like this:
dd($apiResult["campaign"]->manufacturer);
But then error is shown - trying to get non-property object!
You're mixing object access with array access.
$apiResult = json_decode($r->getBody(), true);
dd($apiResult["campaign"][0]["manufacturer"]);
or with objects
$apiResult = json_decode($r->getBody(), false);
dd($apiResult->campaign[0]->manufacturer);
Looks like campaign is an array so you would need to do:
$apiResult["campaign"][0]->manufacturer
If you want to play with object then use following:
$apiResult = json_decode($r->getBody());
dd($apiResult->campaign[0]->manufacturer);
or want an associative array
$apiResult = json_decode($r->getBody(), true);
dd($apiResult["campaign"][0]["manufacturer"]);
For more detail read documentation of json_decode

Categories