Magento collection : field occurrence counting - php

Say I have the following entity called inventory:
I would like to know if there are database, sql or magento actions or any other methods to produce:
I have solved this by iterating through the entire collection and inserting into a temporary table : i.e
$inventorySet = Mage::getModel('custom/module')->getCollection(*);
foreach($inventorySet as $item)
{
$this->insertItem($item->getSku());
}
}
public function insertItem($sku)
{
//insert sku if it does not exist in the temp set
// if it does exists add one to the QTY field
}
I can then retrieve what I want. I don't see an issue with it, but my entity is a lot larger than the example as well as the set of data containing anything between 2000 - 15 000 rows. is there not a more efficient way of doing this?
EDIT: In words, I would like to search the collection for occurrences of the "sku" field and return an array of unique sku's and the number of times it was found in the initial collection.

To get a particular set of column values from a collection you can use the getColumnValues() method.
For example, using a Magento product collection, this would return an array containing the sku attribute value for every product:
$collection = Mage::getResourceModel('catalog/product_collection')
->addAttributeToSelect('sku');
$skus = $collection->getColumnValues('sku');
Finally, to answer the second part of your question, to count the occurence of each unique value:
array_count_values($skus);
This will give you a nice associative array of sku => occurrence count.

Related

yii2 returning records from a database table

I have the following table which has a column with values saved by being separated by a comma
That is
1,2,3,4,5
So at the end i achieve something like this
first row 1,2,3,4
second row 2,3,5
third row 1,4,5
The rows have an attribute category
So i would like to return all rows having a particular value like 1
This is what i have tried
public function actionChecklist($categoryval) //category is the integer value eg 1
{
$checklistitems= TblChecklist::find()->where(
[
"category"=>in_array("category",[$categoryval])
]
)->all();
var_dump($checklistitems);
die();
}
The above code always returns empty where am i going wrong
You can use LIKE provided that every single category is surrounded by two delimiters in your case commas i.e. ,1,2,3,4,5, instead of 1,2,3,4,5. Without these commas a search for say 1 will return everything with a 1 in it including stuff like 10,2,3.
Your search parameter will also require to be surrounded by these commas:
$checklistitems= TblChecklist::find()
->where(["like", "category", ",".$categoryval.","])
->all();
However, you should probably denormalize your table by creating a junction table between checklists and categories. You should then create a relation between your checklist model and your categories model. The code above will then look something like:
$checklistitems= TblChecklist::find()
->joinWith("categories")
->where(["categories.id" => $categoryval])
->all();

Laravel Eloquent outputting array Collection instead single value

I am trying to access a SINGLE VALUE from a row but the dd(); is getting the whole row and showing it in the Collection array. The code:
$last_id = \App\Cat::limit(1)->orderBy('cat_id','desc')->get(['cat_id']);
dd($last_id);
So when I need the JUST "55" value I get :
"cat_id" => "55"
Same happens with others columns, when I need JUST the "Eletronics" I get:
"cat_name" => "Eletronics"
I have already tried lots of stuff like Limit, List, First and nothing happens, when I try to call something like dd($lastId->cat_id ); it gives me a "Undefined property" error. SO now I am really out of options since I am using the documentation example and even that way it does not works fine. So any help would be great, thank you.
I think you don't understand that the Model represents entire row of table.
That means that $last_id in your code:
$last_id = \App\Cat::limit(1)->orderBy('cat_id','desc')->get(['cat_id']);
represents entire row of cats table. If you want to get id, you have to do this:
$cat = \App\Cat::first(1)->orderBy('cat_id','desc')->get();
dd($cat->id);
What more, if you write
$cat = \App\Cat::first();
you will get first cat from cats table, and then you can access every column of this row as property of $cat object
If Laravel says you that property cat_id is undefined, propably your table don't contain cat_id column.
Already got it, i change the get for the "value" method.
\App\Cat::orderBy("id","desc")->value("id");

Laravel - Get the most recently created rows for a variety of IDs, from an array

I need a Laravel query that returns the most recently created row of various site_id rows please. At the moment, I have this query:
Score::whereIn('site_id', $sites)->where('type', 2)->select('score')->get();
But it's returning all of the scores for the sites, where type = 2.
At the moment, the $sites array only contains 1,2, so it will exclude the site_ids that are 3 and 4.
Database structure:
My intended result that the query returns would be the following rows:
ID: 1, 2. - As in, they are the most recently created rows of the IDs within the array.
Update:
If I use:
Score::whereIn('site_id', $sites)->where('type', 2)
->select('score')
->groupBy('site_id')
->get();
a groupBy method, it returns the two scores that I want, but I'm not sure why it would return them? I thought it would just group all of the site's scores by site_id?
Thank you for your help.
Here's what you need: https://softonsofa.com/tweaking-eloquent-relations-how-to-get-latest-related-model/
With that you can easily do this:
$sites = Site::with('latestScore')->find($siteIds); // Collection
// now for each site:
$site->latestScore // what you wanted
however, if you want a collection of scores instead of accessing them via site, then use collection methods:
$sites = Site::with('latestScore')->find($siteIds); // Collection
$scores = $sites->pluck('latestScore') // get nested elements from collection
->filter() // filter out null items
I sounds to me like you just need an orderBy("created_at") chained to the end of your eloquent query.

Laravel : How to take last n(any number) rows after ordered in ascending order?

I have 3 columns id, msg and created_at in my Model table. created_at is a timestamp and id is primary key.
I also have 5 datas, world => time4, hello => time2,haha => time1,hihio => time5 and dunno => time3 and these datas are arranged in ascending order (as arranged here) based on their id.
In laravel 4, I want to fetch these data, arrange them in ascending order and take the last n(in this case, 3) number of records. So, I want to get dunno,world and hihio rows displayed like this in a div :
dunno,time3
world,time4
hihio,time5
What I have tried
Model::orderBy('created_at','asc')->take(3);
undesired result :
haha,time1
hello,time2
dunno,time3
Also tried
Model::orderBy('created_at','desc')->take(3);
undesired result :
hihio,time5
world,time4
dunno,time3
I have also tried the reverse with no luck
Model::take(3)->orderBy('created_at','asc');
This problem seems fairly simple but I just can't seem to get my logic right. I'm still fairly new in Laravel 4 so I would give bonus points to better solutions than using orderBy() and take() if there is. Thank you very much!
You are very close.
It sounds like you want to first order the array by descending order
Model::orderBy('created_at','desc')->take(3);
but then reverse the array. You can do this one of two ways, either the traditional PHP (using array_reverse).
$_dates = Model::orderBy('created_at','desc')->take(3);
$dates = array_reverse($_dates);
Or the laravel way, using the reverse function in Laravel's Collection class.
$_dates = Model::orderBy('created_at','desc')->take(3)->reverse();
Check out Laravel's Collection documentation at their API site at http://laravel.com/api/class-Illuminate.Support.Collection.html
Now $dates will contain the output you desire.
dunno,time3
world,time4
hihio,time5
You're pretty close with your second attempt. After retrieving the rows from the database, you just need to reverse the array. Assuming you have an instance of Illuminate\Support\Collection, you just need to the following:
$expectedResult = $collection->reverse();
To get last three rows in ascending order:
$_dates = Model::orderBy('created_at','desc')->take(3)->reverse();
Now, the json output of $_dates will give you a object of objects.
To get array of objects use:
$_dates = Model::orderBy('created_at','desc')->take(3)->reverse()->values();
$reverse = Model::orderBy('created_at','desc')->take(3);
$show = $reverse->reverse();

Array fill with the Id´s of a SELECT

I have to make an array with the POSTED value of one SELECT. The SELECT selects the products ONE BY ONE. First I choose one product and POST it then another product and I POST the SECOND ONE and so on.....
I want to create an array of the ID of the products that are posted by the SELECT but this array has to grow while I introduce more and more products.
I have use this but It makes the array with only the last product I have choosen.
foreach($_POST['idproducto'] as $key => $val) {
$cadenaides = $cadenaides . "$val,";
}
$cadenaides = $cadenaides . 1;
I would like the array to have all the ID of the products I choose ONE BY ONE in the SELECT.
Seems to me like you want to assign a number to each posted value. You can do this like so:
foreach(...) {
$cadenaides[] = $val;
}
Your values will the be stored in an array. You can check your array with print_r($cadenaides);.
Reading the comments above and assuming that you use MySQL I would suggest the following:
SELECT GROUP_CONCAT(id_producto SEPARATOR ',') FROM producto WHERE .... put your conditions here ..;
This will concatinate all IDs in a single string like that 1,2,3,5,8,9... in a single result, after that you can do just one POST request. Very usefull in many cases BTW.
The result is truncated to the maximum length that is given by the group_concat_max_len system variable, which has a default value of 1024. Could be very large - max: 4294967295 for 32-bit system.

Categories