How to paginate an array - php

It seems that the standard pagination component in CakePHP 3 only allows the pagination of database queries. How can I adjust/overwrite pagination in order to display pagination of an array of data?

you can use Collection to manipulate array data
http://book.cakephp.org/3.0/en/core-libraries/collections.html
Cake\Collection\Collection::take(int $size, int $from)
Whenever you want to take a slice of a collection use the take() function, it will create a new collection with at most the number of values you specify in the first argument, starting from the position passed in the second argument:
$topFive = $collection->take(5);
// Take 5 data from the collection starting from position 4
$nextTopFive = $collection->sortBy('age')->take(5, 4);
Positions are zero-based, therefore the first position number is 0.

Related

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.

Laraver FindOrNew with multiple parameters

I'm using laravel FindOrNew() to get an entry with two parameters, or create a new one:
$option = \App\Option::findOrNew(['user_id' => $this->id , 'option_name' => $optionName]);
I want to get an option for a user that has the name in $optionName. The problem is that it just checks for the user_id, and does not create a new one when option_name does not exist.. instead it "finds" one which does not match the $optionName value..
Can someone say what I'm doing wrong? How can I achieve this?
TL;DR:
You're using the wrong method. You're looking for the firstOrNew() method, not findOrNew().
Explanation:
The findOrNew() is an extension of the find() method, which works on ids only. It takes two parameters, the first being the id (or array of ids) to find, and the second being the columns to retrieve. It's treating the array you've passed in as an array of ids to find.
The firstOrNew() method takes one parameter: an array of attributes to search for. It will turn the array into a where clause, and then call first() on the query builder. If no results are returned, it returns a new instance with those attributes filled in.

Retrieve Laravel Model results based on multiple ID's

I have implemented ZendSearch into my Laravel application. I am using it as my search engine where users will type a search word, and then ZendSearch will return me an array of results ordered by relevance. However, the array that ZendSearch returns, only returns my record ID's (it doesn't return any of the actual record information).
What would next be the correct way to query my Model to retrieve the results based on the ZendSearch array results which is just an array of ID's ordered based on relevance.
I know of Model::find(1) which would return my record with an ID of 1, but how can I feed that find() method an array of ID's that I want to be returned in the order I am giving it.
That's simple. Use findMany:
$models = Model::findMany([1, 2, 3]);
By the way, you can also pass an array to find() and it will internally call findMany:
$models = Model::find([1, 2, 3]);
Under the hood it just does a whereIn so you could do that too:
$models = Model::whereIn('id', [1, 2, 3])->get();
Just use ->find($ids)
$ids = [1,2,3,4]
$model = Model::find($ids);
in my case, i use query like this
$ids = [1,2,3,4]
$model = Model::query()->find($ids);
I used that in Lumen.

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();

Magento collection : field occurrence counting

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.

Categories