Laravel collection find common items - php

I am trying to find the common items existing in a collection like the following one:
I would like to end up with a new collection that contains the 928 and the 895 (common items between the key 95 and the key 94).
How can I do it?
I have an array of keys, but I don't understand how to loop over the keys AND the values without create a mess of variables and additional arrays:
foreach ($ids as $id) {
$item_ids->each(function ($item, $key) {
});
}

Well, I ended up with that solution:
$all = $item_ids->all();
$list = [];
foreach ($all as $single) {
$list[] = $single->toArray();
}
$commonItems = collect(call_user_func_array('array_intersect', $list));

So, this is a more laravel approach:
$items = $item_ids['items']->map(function ($item){
$collection[] = $item['items'];
return collect($collection)->duplicates();
});

Related

Building an array in nested foreach loops in Laravel controller

I am trying to build an array of user ids from a long eloquent relationship, using nested foreach loops in a Laravel controller, but can't get it to work.
Users can have publishers, those publishers can have teams and each team has members. Users can be in multiple teams so I also need to remove duplicate IDs.
I want to end up with a count to see how many team members are associated with a user.
In my user model
public function publishers()
{
return $this->belongsToMany('App\Publisher')->withTimestamps();
}
In my publisher model
public function teams()
{
return $this->belongsToMany('App\Team')->withTimestamps();
}
and in my team model
public function members()
{
return $this->belongsToMany('App\User')->withPivot('status', 'title', 'team_role_ids')->withTimestamps();
}
and in my profile controller
foreach ($user->publishers as $userPublisher) {
foreach ($userPublisher->teams as $publisherTeam) {
$teamUserIds[] = $publisherTeam->members->pluck('id')->toarray();
}
}
$deDupedIds = array_unique($teamUserIds, SORT_NUMERIC);
$idsCount = count($deDupedIds);
But I'm getting multiple arrays and not just one compiled array and the count isn't working. Any idea what I'm doing wrong?
You are assigning a new array into $teamUserIds each iteration. That's why you are getting multiple arrays.
$teamUserIds = [];
foreach ($user->publishers as $userPublisher) {
foreach ($userPublisher->teams as $publisherTeam) {
$teamUserIds = array_merge($teamUserIds, $publisherTeam->members->pluck('id')->toarray());
}
}
$deDupedIds = array_unique($teamUserIds, SORT_NUMERIC);
$idsCount = count($deDupedIds);
you are adding arrays of id $publisherTeam->members->pluck('id')->toarray(); as a new index in $teamUserIds . but what you want to do is to merge the array of ids
so your code would be like this :
foreach ($user->publishers as $userPublisher) {
foreach ($userPublisher->teams as $publisherTeam) {
$teamUserIds = array_merge($teamUserIds , $publisherTeam->members->pluck('id')->toarray());
}
}
$deDupedIds = array_unique($teamUserIds, SORT_NUMERIC);
$idsCount = count($deDupedIds);

Sorting arrays in Laravel following a specific parametre

I have a variable which is an array of arrays
$janvier[]=array( 'type', 'date');
I want to sort it following the date so I used this code
$janvier=> $janvier->sortby($janvier['date'])
but it shows me this error:
call to a member function sortby() on array
Couldn't find what's wrong
I'm so used to low level languages this is my first time using a high level language
You can create a custom function for this case:
array_sort_by_column($array, 'date');
function array_sort_by_column(&$array, $column, $direction = SORT_ASC) {
$reference_array = array();
foreach($array as $key => $row) {
$reference_array[$key] = $row[$column];
}
array_multisort($reference_array, $direction, $array);
}
For more you can check this question
sortBy is a collection method from laravel, you can't use it on a array.
If you want to sort the array by the key data use this code:
$janvier = array_multisort(array_values($janvier), SORT_DESC, array_keys($janvier), SORT_ASC, $janvier);
Look at the array_multisort method for more info

Laravel collection for loops and mappings

I am trying to refactor my code, and remove a for loop.
$result = [];
foreach ($data as $language) {
$result[$language->{$key}] = $language->{$column};
}
This became:
$result = $data->map(function($language) use ($key, $column){
return [$language->{$key} => $language->{$column}];
});
But now instead of:
[
"key":"value",
"key":"value"
]
I am getting
[
{
"key":"value"
},
{
"key":"value"
}
]
Why doesn't it map like an array?
Please refer this URL
For Example:
$emailLookup = $employees->reduce(function ($emailLookup, $employee) {
$emailLookup[$employee['email']] = $employee['name'];
return $emailLookup;
}, []);
Gives you result like:
const emailLookup = {
'john#example.com': 'John',
'jane#example.com': 'Jane',
'dave#example.com': 'Dave',
};
In your case do like:
$result = $data->reduce(function($language, $a){
$language[$a['any_you_want']] = $a['any_you_want'];
return $language;
}, []);
Hope this helps you!
You probably needed to mapWithKeys:
$result = $data->mapWithKeys(function($language) use ($key, $column){
return [$language->{$key} => $language->{$column}];
});
The method has been available since Laravel 5.3
According to the docs:
The mapWithKeys method iterates through the collection and passes each value to the given callback. The callback should return an associative array containing a single key / value pair:
For your simple use case, pluck() is the method you're looking for. It will build a new collection using one column of an existing array. You can also pass in a second field that will be used to key the new collection.
So, in your case, the data column you're selecting is $column, and the column to use as the key for the new collection is $key. Your code would be:
$result = $data->pluck($column, $key);
This says "give me a collection of all of the $column data, and key it by the $key data".
If you want the plain array instead of the collection, just call all() on the result:
$result = $data->pluck($column, $key)->all();
If you need to "pluck" more than one column of data, you will need to use the mapWithKeys() method already mentioned.
Here in loop you need to use as key value pair
$result = [];
foreach ($data as $key => $language) {
$result[$key] = $language;
}

push data in to a multidimensional array in laravel php

I want to create a multidimensional array to save the data according the date and a category as follow. Then i need to display this data in my blade view?what can i do to achieve this.
'2012-05-05' => array(
'suspension' => 52,
'transmission' => '58'
),
'2012-05-05' => array(
'suspension' => 44,
'transmission' => 21
I have done the following in my controller i want a $reportData variable to load the data.
public function loadReports(Request $request)
{
$data = ['2012-05-05','2012-05-06'];
$salesItems = array();
$orderItems = OrderItem::with('spare', 'order')->get();
foreach ($orderItems as $key => $orderItem) {
if ($orderItem->spare->retailer_id == Auth::user()->id) {
array_push($salesItems, $orderItem);
}
}
$categories = App\Categories::all();
foreach ($data as $date) {
foreach ($categories as $category) {
$categoryValue = 0;
foreach ($salesItems as $salesItem) {
if ($date == $salesItem->order->orderDate) {
$categoryValue += $categoryValue + $salesItem->subTotal;
}
}
//error appears as illegal offset type
$reportData[$date][$category]=$categoryValue;
}
}
return View::make('Retailer/reports')->with('categories', $categories)->with('reportData', $reportData);
}
I haven't tested it but looking at your code it seems that you're passing an object as array index key as 2nd level array index:
$reportData[$date][$category] = $categoryValue;
^^^^^^^^^ this is an object
Dump your $category in the foreach loop & check if that is the case: dd($category)
If you're using Eloquent & your Categories Model has a name property, you'll probably want to take each category name as index value:
$reportData[$date][$category->name] = $categoryValue;
The error is occurring due to the fact that you are trying to use an Object as the array's index.
As per the laravel documentation (https://laravel.com/api/4.2/Illuminate/Database/Eloquent/Model.html#method_all) the all method you called here '$categories = App\Category::all();' would have returned an Eloquent Collection.
So when you iterated over the $categories array and referenced $category, you were referencing an object. In PHP an array can only be indexed by either an integer or a string. So you need to change the line of code where the error is to this
$reportData[$date][$category->someVar] = $categoryValue;
Where someVar is the name of a variable on the Eloquent model Category that references its name, such as 'suspension' etc.
While it doesn't answer your question you could use the Eloquent engine to make your life easier:
$orderItems = OrderItem::with('spare', 'order')->get();
foreach ($orderItems as $key => $orderItem) {
if ($orderItem->spare->retailer_id == Auth::user()->id) {
array_push($salesItems, $orderItem);
}
}
can be simplified (and made more efficient) with:
// Store the uid to save the call.
$user_id = Auth::user()->id;
// Apply the condition to the Eloquent query.
$orderItems = OrderItem::with(['spare' => function($query) use ($user_id) {
return $query->where('retailer_id', '=', $user_id);
}, 'order'])->get();
The other answers are correct, but you probably also want to initialise the $reportData array as before you start working with it.

How to use a for loop on a collection pulled from Magento

im trying to use a for loop on products i pulled from Magento.
And it crashes when i want to use the index on a product in the loop.
$collection = Mage::getModel('catalog/product')->getCollection();
$collectionLength = count($collection);
for($j = 0; $j < $collectionLength; $j++)
{
$productFromStore = $collection[$j];//it crashes on this line of code
$sku = $productFromStore->getSku();
}
but when i use a foreach loop i can reach all the products.
foreach($collection as $product)
{
// this code works fine
$sku = $product->getSku();
}
Can someone explain what is going wrong and why?
Thanks.
First of all, You trying to iterate collection object as array
Here is Error :
Fatal error: Cannot use object of type
Mage_Catalog_Model_Resource_Product_Collection as array
, second for loop isn't the best way to iterate collections better is foreach loop becacuse for loop need to count of array emelents foreach dont need it.
Third, the best way is to use magento resource iterator.
Mage::getSingleton('core/resource_iterator')
->walk(
$query->getSelect(),
array(array($this,'callbackFunction')));
here is an example:
public function someGetCollectionMethod()
{
$products = Mage::getModel('catalog/product')->getCollection();
Mage::getSingleton('core/resource_iterator')
->walk(
$products->getSelect(),
array(array($this, 'productsCallback')));
}
public function productsCallback($args)
{
$product = Mage::getModel('catalog/product');
$prod = $product->load($args['row']['entity_id']);
Zend_Debug::dump($prod->getSku());
}
Happy coding,
Adam
Collection classes in Magento's ORM ultimately subclass Varien_Data_Collection which implements IteratorAggregate; this is why you are able to work with the collection object in an array-like fashion (i.e. foreach), but not have it work for the for loop. For one thing, dThere is no direct key-based access to the elements inside the object (_items array members) - unfortunate, given that the key for the _items array is based on the row ID.
Bottom line: working with collection items in a for loop is not very easy, not when compared to the ease of working with collection items via IteratorAggregate and all of its related goodies.
Here's an example of both. If you have an overarching need to work with the collection's items directly then you can use $collection->getItems(), but again realize that the _items array keys may not be sequential as they are based on the data. Also, note that you need to add the name attribute value to collections stored using Magento's EAV pattern:
<?php
header('Content-Type: text/plain');
include('app/Mage.php');
Mage::app();
$collection = Mage::getResourceModel('catalog/product_collection');
$collection->addAttributeToSelect('name');
//for loop - not as much fun
for ($j=0;$j<count($collection);$j++) { //count() triggers $collection->load()
$items = $collection->getItems();
$item = current($items);
echo sprintf(
"%d:\t%s\t%s\n",
$k,
$item->getSku(),
$item->getName()
);
next($items); //advance pointer
}
//foreach - a bit better
foreach ($collection as $k => $product) {
echo sprintf(
"%d:\t%s\t%s\n",
$k,
$product->getSku(),
$product->getName()
);
}
And just in case you are wondering: Performance of FOR vs FOREACH in PHP
$array = array(
"foo" => "bar",
"bar" => "foo",
);
This type of array cannot be accessed by indexes you have to use,
$array["foo"];
If the keys are unpredictable you have to use
`foreach
I'm no expert in magento, but perhaps it's because the collection has different keys other than just numbers? Try printing out the collection with print_r to see what keys does the object have.
If you need iterations with numbers, you can always do something like that:
$i=0;
foreach($collection as $product)
{
$sku = $product->getSku();
$i++;
}
EDIT: Anyway, it seems collections aren't regular arrays, so you cannot use them the way you tried.
That's because you are sending an empty value to the getSku function.
<?php
$collection=array("book1"=>"bat","book2"=>"cat");
$collectionLength = count($collection);
for($j = 0; $j < $collectionLength; $j++)
{
$productFromStore = $collection[$j];
echo $productFromStore; //prints nothing !
}
foreach($collection as $var)
{
echo $var; //prints batcat
}
In magento collection return in form of object. use below code fetch SKU and NAME. Or use print_r($collection->getData()) to get data in array Key=>value format.
foreach($collection as $productCollection){
$sku = $productCollection->getSku();
$name = $productCollection->getName();
}

Categories