detach laravel paginate object and list items to separate veriables - laravel

hello, is that possible to detach Laravel pagination object (without items) to a another variable and its items to another variable?
eg:
I'm currently working on product list that project that using without pagination (just ->get() ) so I need to inject paginated items to that variable and send pagination Object data in separate variable.. hope you guys can understand.
the current way is:
$products = Products::get();
I just need send pagination items to that variable and pagination object in another variable.
just like this:
$products_paginate = Products::paginate(10);
$paginateObj = $products_paginate ->pagination();
$products = $products_paginate ->items();
items should not in pagination data object.

Related

Best approcah for getting the object in the foreach loop in laravel using eloquent?

I have some properties and i want to get the object for each property, currently, I am using the eloquent in the foreach loop like this as shown in the image that will describe the best..
but it is really not a good approach because if I have 100 published property I will making 100 calls to the DB... and that is not correct?
I need a suggestion and a proper solution to this query?
Thanks in advance
Before foreach you can get all the RentalProperty items from db like this:
$allRentalProperties = RentalProperty::all();
and in foreach loop you can get those items without connecting database like this:
$propertyObj = $allRenatalProperties -> where('id', $property['id']) -> first();
Also, you can use array shorthand.
$newArray = [];
it's much simple and readable.
You can do array pluck before loop:
$propertyIds = Arr::pluck($published_properties, 'id');
Then you can make a whereIn query to get only those data which are in $published_properties object
$propertyObj = RentalProperty::whereIn('id', $propertyIds);
Then you can access that object with id if you change array key with record id.

Laravel append overall total value on pagination result

I have a Laravel query using pagination.
I want to be able to return the result based on the pagination but also get the overall total of the query and append this to the return. So for example the pagination is set to 5 but the overall total might be 20.
$query = Model::paginate(5);
$queryTotal = $query->total();
$query->append($queryTotal);
return $query;
The Laravel Paginator does this already.
You can see that when serializing results to JSON there is a total key which represents all rows matching that query.
You can also see there is a total method available from the paginator:
$results->total()
Along side other methods that can be found in the Pagination Docs
$query = Model::paginate(5);
return $query;
You can access overall total using
{{ $query->total() }}
For more Info read Paginator instance
The paginate function returns a LengthAwarePaginator object. It simply not possible to add another field to this object.
Your best option is to manually create a new collection in which you merge the LengthAwarePaginator with your newly added data.
An example would be:
$query = Model::paginate(5);
$addition = collect(['totalResult' => $query->total()]);
$queryData = $addition->merge($query);
return $queryData;
Naturally, if you just return the LengthAwarePaginator object, you can simply call the total() function, if you use it in your blade files for example.
Hope this helps!

Laravel retrieve only specific fields from each item of collection

I may be missing something extremely trivial, but is it possible to retrieve specific columns/fields from models when grabbing a collection rather then returning the entire item's fields?
Here is my query:
$items = Items::where('visible', true)->take(10)->get();
This obviously returns each item in there entirety, including unique id's, and other fields i dont want to be fetched... how can i refine this query to just select specific fields from the models?
Laravel Query Builder get() function receives array of columns which you need to fetch.
$items = Items::where('visible', true)->take(10)->get(['column_1', 'column_2']);
Use select() method to do this:
$items = Items::select(['column_1', 'column_2']'])->where('visible', true)->take(10)->get();
Source: Latavel Database Query Builder
Laravel Query Builder gives a huge flexibility to write this types of query.
You can use select(), get(), all() methods.
Items::where('visible', true)->take(10)->get('col_1', 'col_2');
OR
Items::select('col_1', 'col_2')->where('visible', true)->take(10)->get();
Items::select(['col_1', 'col_2'])->where('visible', true)->take(10)->get();

Laravel, how to convert a collection object into a builder object

I need to use paginate and simplepaginate on a collection, so i'm trying to convert the collection into a builder object.
To do so I am thinking of creating a function that gets the id of every item in the collection and then builds a query with it, but that seemed to me like a lot of resources waisted,
Is there a simpler way ?
A better way to do this is to build paginator object manually using the existing collection.
From the docs:
Sometimes you may wish to create a pagination instance manually, passing it an array of items. You may do so by creating either an Illuminate\Pagination\Paginator or Illuminate\Pagination\LengthAwarePaginator instance, depending on your needs.
The Paginator class does not need to know the total number of items in the result set; however, because of this, the class does not have methods for retrieving the index of the last page. The LengthAwarePaginator accepts almost the same arguments as the Paginator; however, it does require a count of the total number of items in the result set.
In other words, the Paginator corresponds to the simplePaginate method on the query builder and Eloquent, while the LengthAwarePaginator corresponds to the paginate method.
Building on what Alexey said, as alternative, you can build a Paginator from a collection manually. This is a simpler way without the waste of an additional query. e.g.
// Collection $collection
$perPage = 10;
$currentPage = Illuminate\Pagination\Paginator::resolveCurrentPage() ?? 1;
$itemsOnPage = $collection->skip(10 * ($currentPage-1))->take($perPage);
$paginatorPath = Illuminate\Pagination\Paginator::resolveCurrentPath();
$paginator = new \Illuminate\Pagination\LengthAwarePaginator(
$itemsOnPage,
$collection->count(),
$perPage,
$currentPage,
['path' => $paginatorPath]
);
Then in your view,
{!! $paginator->render() !!}

Laravel 5.1 eloquent query orderby external data and paginated

I'm trying to get data from an Eloquent query (that works), then order the data, then paginate the data.
I had the code ordering by date, then paginating, but now I want to order by facebook API obtained data (I get the data correctly).
The thing is I don't know what I should do first (paginate or ordering):
If I paginate first, I don't know how to order the data since the object is LengthAwarePaginator and doesn't have any orderBy method.
If I order first, I get a collection object and can't use ->paginate($perPage) to do the pagination.
This is the code:
$posts = Post::with('User')->
where('created_at', '<', new \DateTime)->
paginate($perPage);
$counter = 0;
foreach ($posts as $post) {
$url = 'http://myweb.com/' . $post['id'];
$fb_stuff = json_decode(file_get_contents('https://api.facebook.com/method/links.getStats?urls=' . $url . '&format=json'), true);
$posts[$counter]['share_count'] = $fb_stuff[0]['share_count'];
$counter++;
}
If you need to sort by some value that is not stored in the database then the only option is to fetch all records from the database, fetch the sorting data from external source (Facebook API), sort it by user defined function (see http://php.net/manual/en/function.usort.php) and then paginate.
Once you have your data sorted you can easily get the paginated version by creating a Paginator object:
$paginator = new \Illuminate\Pagination\Paginator($posts, $perPage, $currentPage);
Anyway, this solution will be quite heavy as you'll need to fetch data from Facebook API every time you want a sorted list of posts. I doubt you need real time data so I suggest to store share_count in your posts table and refresh it on regular basis, e.g. by running a scheduled laravel command.

Resources