I'm using the Laravel contains method on a collection https://laravel.com/docs/5.3/collections#method-contains. But it does not work for me.
foreach ($this->options as $option) {
if($options->contains($option->id)) {
dd('test');
}
}
dd($options); looks like this:
Collection {#390
#items: array:1 [
0 => array:3 [
0 => array:7 [
"id" => 10
"slug" => "test"
"name" => "test"
"poll_id" => 4
"created_at" => "2016-11-12 20:42:42"
"updated_at" => "2016-11-12 20:42:42"
"votes" => []
]
1 => array:7 [
"id" => 11
"slug" => "test-1"
"name" => "test"
"poll_id" => 4
"created_at" => "2016-11-12 20:42:42"
"updated_at" => "2016-11-12 20:42:42"
"votes" => []
]
2 => array:7 [
"id" => 12
"slug" => "test-2"
"name" => "test"
"poll_id" => 4
"created_at" => "2016-11-12 20:42:42"
"updated_at" => "2016-11-12 20:42:42"
"votes" => []
]
]
]
}
Result of dd($option->id); is 10.
What could be wrong? Or is there a better way?
You should pass a key / value pair to the contains method, which will
determine if the given pair exists in the collection. Use contains() method in this way:
foreach ($this->options as $option) {
// Pass key inside contains method
if($option->contains('id', $option->id)) {
dd('test');
}
}
Use the following, which tells Laravel you want to match the 'id':
$options->contains('id', $option->id);
Docs
foreach ($this->options as $option) {
if(!$options->flatten(1)->where('id',$option->id)->isEmpty()) {
dd('test');
}
}
The contains method determines whether the collection contains a given item.
There are basically three ways in which it can be used :
simply checking the item
$collection = collect(['name' => 'Sarah', 'age' => 23]);
$collection->contains('Desk');
// false
$collection->contains('Sarah');
// true
checking the key/value pair :
$collection = collect([
['name' => 'Sarah', 'age' => 23],
['name' => 'Vicky', 'age' => 34],
]);
$collection->contains('name', 'Hank');
// false
checking via callback function :
$collection = collect([3, 5, 7, 9, 11]);
$collection->contains(function ($value, $key) {
return $value < 2;
});
// false
Now, for your problem, we will use the second category, i.e :
foreach ($this->options as $option) {
// here id is key and $option->id is value
if($option->contains('id', $option->id)) {
dd('test');
}
}
Link to docs
Related
I have a table from which i am fetching some columns
$records=Table::select('id','text','type')->paginate(250)->toArray();
$data=$records->['data'];
I am getting output as :-
array:250 [
0 => array:4 [
"id" => 1
"text" => "text1"
"type" => "A"
]
1 => array:4 [
"id" => 1
"text" => "text2"
"type" => "B"
]
2 => array:4 [
"id" => 1
"text" => "text3"
"type" => "C"
]
3 => array:4 [
"id" => 2
"text" => "text4"
"type" => "A"
]
4 => array:4 [
"id" => 2
"text" => "text5"
"type" => "B"
]
5 => array:4 [
"id" => 2
"text" => "text6"
"type" => "C"
]
6 => array:4 [
"id" => 3
"text" => "text7"
"type" => "A"
]
7 => array:4 [
"id" => 3
"text" => "text8"
"type" => "B"
]
8 => array:4 [
"id" => 3
"text" => "text9"
"type" => "C"
]....
]
I want to convert it into array of objects/array of arrays where results of same id should merge in such a way that value of "type" should be key and value of "text" as value. Below is a sample of expected result:-
array:20 [
{
"id" => 1
"A" => "text1"
"B"=>"text2"
"C"=>"text3"
}
{
"id" => 2
"A" => "text4"
"B"=>"text5"
"C"=>"text6"
}
{
"id" => 3
"A" => "text7"
"B"=>"text8"
"C"=>"text9"
}...
]
I have tried using array_column.
$sortedRecords = array_column($data, 'text','type');
Using array_column, i am able to convert value of "type" as key and "text" value as its value. But i am not able getting how to display id also and how to loop for each distinct id as it is displaying result of only last id.
Following logic might help you on your way. The source array is called $arr, the result array $newArr.
The snippet runs through all unique id's in the source array and accumulates the accompanying text values.
$newArr = [];
$ids = array_values(array_unique(array_column($arr, 'id')));
foreach ($ids as $key => $id) {
foreach ($arr as $value) {
if ($value['id'] === $id) {
$newArr[$key]['id'] = $id;
$newArr[$key][$value['type']] = $value['text'];
}
}
}
working demo
You can get information in groups with group By and perform any operation you need
$records = Table::select('id','text','type')->groupBy('type')->paginate(20)->toArray();
i have a function that it fills the one array like below :
if (isset($options[$attribute->id][$optionId])) {
foreach ($options[$attribute->id][$optionId] as $item) {
. . . .
$attributeOptionsData[] = [
'id' => $optionId,
'label' => $attributeOption->label ? $attributeOption->label : $attributeOption->admin_name,
'swatch_value' => $attribute->swatch_type == 'image' ? $attributeOption->swatch_value_url : $attributeOption->swatch_value,
'products' => $options[$attribute->id][$optionId],
'images' => $productImage ?? null,
];
dd($attributeOptionsData);
}
the result of this dd is like below :
array:1 [▼
0 => array:5 [▼
"id" => 1
"label" => "black"
"swatch_value" => "#000000"
"products" => array:1 [▶]
"images" => "product/4618/rAkC2aC3QJB6kMiAAzIGk6nUzGHxpdfIS55g3T0P.jpeg"
]
]
now what i want to do is that after the last line add some content to this array and make it like below:
array:1 [▼
0 => array:5 [▼
"id" => 1
"label" => "مشکی"
"swatch_value" => "#000000"
"products" => array:1 [▶]
"images" => "product/4618/rAkC2aC3QJB6kMiAAzIGk6nUzGHxpdfIS55g3T0P.jpeg"
"custom_field" => "some value"
]
]
on the line that i dd the array i want add the customfield to it . how can i do that thanks in advance.
the reason i dont insert like others in that i want to add the custom field in a foreach loop based on 1 field of that array
So, if you simply want to add something at the bottom of an array, just use array_push().
In your case, you would need to retrieve the whole $attributeOptionsData[] in a foreach loop and append the array to the key you're in, during that loop. Be aware that this is somehow inefficient. If you want to add a line based on a value you can retrieve in the first foreach loop, you could've just made an if-statement asking for that value and add it with array_push() afterwards.
Either way, I think this is what you're looking for:
if (isset($options[$attribute->id][$optionId])) {
foreach ($options[$attribute->id][$optionId] as $item) {
$attributeOptionsData[] = [
'id' => $optionId,
'label' => $attributeOption->label ? $attributeOption->label : $attributeOption->admin_name,
'swatch_value' => $attribute->swatch_type == 'image' ? $attributeOption->swatch_value_url : $attributeOption->swatch_value,
'products' => $options[$attribute->id][$optionId],
'images' => $productImage ?? null,
];
}
foreach($attributeOptionsData as $key=>$data){
array_push($attributeOptionsData[$key], ["custom_field" => "some value"])
}
}
$attributeOptionsData is an associative array. You can assign values to it by specifying the array $key:
$attributeOptionsData[$key] = $value;
Am working on a Laravel application whereby I have an associative array that am to pass to an API endpoint, Before posting to the API, I want to delete the img key together with its value . I have tried to use unset function but it is not removing the img key
Array where I want to remove the image property
$a[] = [
0 => array:4 [
"name" => "Martoo nnn"
"relationship" => "Spouse"
"dob" => "2001-02-03"
"img" => "img.png"
]
1 => array:4 [
"name" => "sdsdsd sdsdsd"
"relationship" => "Child"
"dob" => "2019-04-04"
"img" => "img1.png"
]
2 => array:4 [
"name" => "sdsdsd sddds"
"relationship" => "Child"
"dob" => "2019-04-05"
"img" => "img2.png"
]
3 => array:4 [
"name" => "dssdsd dsdsd"
"relationship" => "Child"
"dob" => "2019-04-02"
"img" => "img3.png"
]
4 => array:4 [
"name" => "dssdsd dssdsd"
"relationship" => "Child"
"dob" => "2019-04-04"
"img" => "img4.png"
]
];
Unset method
$array = $a;
unset($array['img']);
//dd($a);
You can do something like this,
foreach ($array as $key => &$value) { // & defines changes will be made # value itself
unset($value['img']);
}
And Yes, I don't understand why you initialised $a as $a[]?
$newarray = array_filter($a, function($k) {
return $k != 'img';
}, ARRAY_FILTER_USE_KEY);
and pass this new array
It sounded crazy simple to me at first but I can't find the solution!
Here is My collection :
Collection {#433
#items: array:432 [
0 => array:5 [
"word_id" => 12218
"name" => "ordered"
"rank" => 12217
"is_real" => 1
"id" => 1
]
1 => array:5 [
"word_id" => 12097
"name" => "one-dimensional"
"rank" => 12096
"is_real" => 1
"id" => 2
]
2 => array:5 [
"word_id" => 19679
"name" => "watery"
"rank" => 19678
"is_real" => 1
"id" => 3
]
.
.
.
But I want it to be like this :
Collection {#433
#items: array:432 [
0 => array:5 [
"name" => "ordered"
"id" => 1
]
1 => array:5 [
"name" => "one-dimensional"
"id" => 2
]
2 => array:5 [
"name" => "watery"
"id" => 3
]
.
.
.
How can it be done with laravel collection? Do I have to change my collection to array and do the manipulation myself? How?
Or you can also use
$collection = $collection ->map(function ($item) {
return collect($item)->forget(['work_id','rank','is_real']);
});
$collection = $collection->map(function ($item) {
return array_only($item, ['id', 'name']);
});
You can use the only() method.
The only method returns the items in the collection with the specified
keys
$collection = $collection->map(function ($item) {
return $item->only(['id', 'name'])
});
This way your collection still remains as collections;
Please note, only() method is only available for Laravel collections
not for an array
An alternative approach could be to use the Arr::only() helper to reduce the items:
$collection = $collection->map(static fn($item) => Arr::only($item, ['id', 'name']));
Question background
Hello, I have the following array of movie crew members:
array:7 [▼
0 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5e9d"
"department" => "Directing"
"id" => 139098
"job" => "Director"
"name" => "Derek Cianfrance"
"profile_path" => "/zGhozVaRDCU5Tpu026X0al2lQN3.jpg"
]
1 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5ed7"
"department" => "Writing"
"id" => 139098
"job" => "Story"
"name" => "Derek Cianfrance"
"profile_path" => "/zGhozVaRDCU5Tpu026X0al2lQN3.jpg"
]
2 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5edd"
"department" => "Writing"
"id" => 132973
"job" => "Story"
"name" => "Ben Coccio"
"profile_path" => null
]
3 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5ee3"
"department" => "Writing"
"id" => 139098
"job" => "Screenplay"
"name" => "Derek Cianfrance"
"profile_path" => "/zGhozVaRDCU5Tpu026X0al2lQN3.jpg"
]
4 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5ee9"
"department" => "Writing"
"id" => 132973
"job" => "Screenplay"
"name" => "Ben Coccio"
"profile_path" => null
]
5 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5eef"
"department" => "Writing"
"id" => 1076793
"job" => "Screenplay"
"name" => "Darius Marder"
"profile_path" => null
]
11 => array:6 [▼
"credit_id" => "52fe49de9251416c750d5f13"
"department" => "Camera"
"id" => 54926
"job" => "Director of Photography"
"name" => "Sean Bobbitt"
"profile_path" => null
]
]
As you can see this is a list of credits I'm getting via the TMDb API. The first step of building the above array was to filter out all jobs that I don't want to display, here's how I did that:
$jobs = [ 'Director', 'Director of Photography', 'Cinematography', 'Cinematographer', 'Story', 'Short Story', 'Screenplay', 'Writer' ];
$crew = array_filter($tmdbApi, function ($crew) use ($jobs) {
return array_intersect($jobs, $crew);
});
My question
I'd like to figure out how to take the above result one step further and combine jobs where the id is the same, so as to end up with something like this, for example:
array:7 [▼
0 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5e9d"
"department" => "Directing"
"id" => 139098
"job" => "Director, Story, Screenplay"
"name" => "Derek Cianfrance"
"profile_path" => "/zGhozVaRDCU5Tpu026X0al2lQN3.jpg"
]
I have also considered ditching doing this in my logic and instead doing it in my blade template, but I'm not sure how to achieve that.
How would you accomplish this?
You could nicely use Laravel's Collection in such a situation, which has a great number of methods which will help you in this case.
First, turn this array (the one you already filtered on jobs) to a Collection:
$collection = collect($crew);
Second, group this Collection by it's ids:
$collectionById = $collection->groupBy('id');
Now, the results are grouped by the id and transformed to a Collection in which the keys correspond to the id, and the value an array of 'matching' results. More info about it here.
Finally, just a easy script that iterates through all the results for each id and combines the job field:
$combinedJobCollection = $collectionById->map(function($item) {
// get the default object, in which all fields match
// all the other fields with same ID, except for 'job'
$transformedItem = $item->first();
// set the 'job' field according all the (unique) job
// values of this item, and implode with ', '
$transformedItem['job'] = $item->unique('job')->implode('job', ', ');
/* or, keep the jobs as an array, so blade can figure out how to output these
$transformedItem['job'] = $item->unique('job')->pluck('job');
*/
return $transformedItem;
})->values();
// values() makes sure keys are reordered (as groupBy sets the id
// as the key)
At this point, this Collection is returned:
Collection {#151 ▼
#items: array:4 [▼
0 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5e9d"
"department" => "Directing"
"id" => 139098
"job" => "Director, Story, Screenplay"
"name" => "Derek Cianfrance"
"profile_path" => "/zGhozVaRDCU5Tpu026X0al2lQN3.jpg"
]
1 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5edd"
"department" => "Writing"
"id" => 132973
"job" => "Story, Screenplay"
"name" => "Ben Coccio"
"profile_path" => null
]
2 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5eef"
"department" => "Writing"
"id" => 1076793
"job" => "Screenplay"
"name" => "Darius Marder"
"profile_path" => null
]
3 => array:6 [▼
"credit_id" => "52fe49de9251416c750d5f13"
"department" => "Camera"
"id" => 54926
"job" => "Director of Photography"
"name" => "Sean Bobbitt"
"profile_path" => null
]
]
}
Note: to use this Collection as an array, use:
$crew = $combinedJobCollection->toArray();
There are multiple ways to achieve this, for example: search the array for overlapping id's, but I think this is the easiest way to achieve this.
Goodluck!
Since you are trying to edit the array elements and its size, I believe array_map() or array_filter() won't be a solution to this.
This is what I could come up with...
$jobs = [
'Director', 'Director of Photography', 'Cinematography',
'Cinematographer', 'Story', 'Short Story', 'Screenplay', 'Writer'
];
$crew = [];
foreach($tmdbApi as $key => $member) {
if($member['id'] == $id && in_array($member['job'], $jobs)) {
if(!isset($crew[$key])) {
$crew[$key] = $member;
} else {
$crew_jobs = explode(', ', $crew[$key]['job']);
if(!in_array($member['job'], $crew_jobs)) {
$crew_jobs[] = $member['job'];
}
$crew[$key]['job'] = implode(', ', $crew_jobs);
}
}
}
Hope this answers your question :)