Splitting Paginated Blade - php

Below is my controller code
$category_ids = array();
foreach($categories as $category){
$category_ids[] = $category->id;
}
$paginated_products = Product::where('status',1)->whereIn('category_id',$category_ids)->latest()->paginate(30);
Below is my blade view code
$first_ten_products = array_slice($paginated_products,0,9);
But am getting the error below how can i fix it. Thanks
array_slice(): Argument #1 ($array) must be of type array, Illuminate\Pagination\LengthAwarePaginator given

Your error is saying that $paginated_products is not an Array, and array_slice requires an Array to function. You can use ->toArray() as suggested in the comments/your answer, but there are also Laravel Collection methods for this:
$paginatedProducts = Product::where('status', 1)
->whereIn('category_id', $categories->pluck('id'))
->latest()
->paginate(30);
$chunkedProducts = $paginatedProducts->getCollection()->chunk(10);
Some changes:
Use ->pluck('id') instead of foreach()
The pluck() Method returns a Collection of the speicified values, and is a short-hand for what your foreach($models as $model) { $array[] = $model->id } accomplishes.
Define $chunkedProducts from your Paginated Product Models
->paginate(30) returns an instance of a LengthAwarePaginator, which has a method getCollection(), which can then be chained to the chunk() method. chunk(10) will return a Collection with X elements. In your case:
$firstTenProducts = $chunkedProducts[0];
$secondTenProducts = $chunkedProducts[1];
$thirdTenProducts = $chunkedProducts[2];
It would probably make more sense to pass these to the Frontend and loop them, like:
#foreach($chunkedProducts as $chunkOfTen)
<!-- Do something with each group of 10 Products -->
#endforeach
But you can use the chunks however you see fit, and however works with your project.

If I have refactored my code as below and it worked
$first_ten_products = array_slice($paginated_products->toArray(),0,9);
dd($first_ten_products['data']);
I just added the data property as above in the dd method and it worked

Related

how to take custom amount of data from foreach loop php laravel

So in Eloquent there is a take() and skip() functions works like this:
$users = DB::table('users')->skip(10)->take(5)->get();
But now I'm reading data from a json file:
$path = storage_path() . "/app/public/userexam.json";
json_decode(file_get_contents($path), true);
So after reading data, I want to use a foreach loop:
foreach($json as $js){
...
}
But I do need to take custom amount of records of $json.
Something like this:
foreach($json->take(5) as $js){
...
}
But this thing obviously does not work and returns Call to a member function take() on array.
So how can I use take and skip eloquent functions in a foreach loop in this case (or something equivalent to them).
I would really appreciate if you share any idea or suggestion about this...
Thanks.
You might need collect() method as the docs.
collect(json_decode(file_get_contents($path), true));
After that you might able to use take() or skip() method.
You can use array_slice on the JSON array to implement skip and take. For example:
$skip = 10;
$take = 5;
foreach (array_slice($json, $skip, $take) as $js) {
// ... do what is necessary on the data
}
Demo on 3v4l.org

how to make an eloquent result into an array Laravel

I want to combine two data search results into one array, I use array_merge but there is an array_merge() error:
Argument # 1 is not an array
How to turn $vendor's eloquent results into an array and combine it with $plucked?
$vendor = Vendor::find($id);
$vendor_detail = VendorDetail::where('vendor_id',$id)->get();
$plucked = $vendor_detail->pluck('vendor_profile_value','vendor_profile_name');
$coba = array_merge($vendor,$plucked);
$plucked already an array
I think the problem here is that $vendor is not yet an array
You could do it like this:
$vendor = Vendor::find($id);
$vendor_details = VendorDetail
::select('vendor_profile_value', 'vendor_profile_name')
->where('vendor_id', $id)
->get()
->toArray();
$coba = array_merge($vendor,$vendor_details);
The get() method execute the query returning a Collection instance, in which you can call the toArray() method.
Side note
As far as I can see, you could make use of relationships and eager loading.
If you have a one-to-many relationship defined like this in your Vendor model:
public function details()
{
return $this->hasMany(VendorDetails::class);
}
Then, you could eager load the relationship like this:
$vendor = Vendor::with('details')->find($id);
// ^^^^^^^^^^^^^^
You could even just load the wanted fields:
$vendor = Vendor::with('details:vendor_profile_value,vendor_profile_name')
->find($id);
Then, your object will have a new attribute called "details" containing the related objects (or a collection of the limited selected fields).
You can convert the $vendor to an Array like below.
$vendor = Vendor::find($id)->toArray();

Operetion on child collection

I have code like this
$tag = Tag::where('slug' = $slug)->first();
$posts = $tag->posts;
It works correctly but I want to use limit, orderBy, offset and other operation on posts. So it works
$posts = $tag->posts->where('accept', 1);
But it doesn't works
$posts-> $tag->posts->orderBy('created_at', 'desc');
//or
$posts-> $tag->posts
->offset($offset)
->limit($limit);
I must use offset and limit into query from var.
How I can do that?
When you set up your initial query Tag::where('slug' = $slug)->first(); you're using Query Builder and it's methods. But when Laravel returns the results, they're returned as a collction object -- those have very similar but slightly different methods available. https://laravel.com/docs/5.8/collections#available-methods
On a collection or its children, instead of orderBy() you would use sortBy() or sortByDesc(). Those will return an instance of the collection, sorted by your specified key. $results = $posts->sortBy($sorting);
The same idea with limit, in this case you can use the splice method. (Collections are basically php arrays on steroids) Splice accepts two parameters, a starting index and a limit. So, to get only the first 10 items, you could do this: $results = $posts->splice(0, 10);
And of course, you can also chain those togeather as $results = $tag->posts->sortBy('id')->splice(0, 10);
When you use child, Eloquent create another subquery, then result is added to parent, thats way its not sorting properly.
A solution could be join tables:
$tags = Tag::where('tags.slug' = $slug)
->join('tags', 'tag.post_id', '=', 'posts.id')
->orderBy('posts.created_at', 'desc')
->select('tags.*')
->get();

How to Merge Two Eloquent Collections?

I have a questions table and a tags table. I want to fetch all questions from tags of a given question. So, for example, I may have the tags "Travel," "Trains" and "Culture" attached to a given question. I want to be able to fetch all questions for those three tags. The tricky, so it seems, is that questions and tags relationship is a many-to-many defined in Eloquent as belongsToMany.
I thought about trying to merge the questions Collections as below:
foreach ($question->tags as $tag) {
if (!isset($related)) {
$related = $tag->questions;
} else {
$related->merge($tag->questions);
}
}
It doesn't seem to work though. Doesn't seem to merge anything. Am I attempting this correctly? Also, is there perhaps a better way to fetch a row of rows in a many-to-many relationship in Eloquent?
The merge method returns the merged collection, it doesn't mutate the original collection, thus you need to do the following
$original = new Collection(['foo']);
$latest = new Collection(['bar']);
$merged = $original->merge($latest); // Contains foo and bar.
Applying the example to your code
$related = new Collection();
foreach ($question->tags as $tag)
{
$related = $related->merge($tag->questions);
}
The merge() method on the Collection does not modify the collection on which it was called. It returns a new collection with the new data merged in. You would need:
$related = $related->merge($tag->questions);
However, I think you're tackling the problem from the wrong angle.
Since you're looking for questions that meet a certain criteria, it would probably be easier to query in that manner. The has() and whereHas() methods are used to generate a query based on the existence of a related record.
If you were just looking for questions that have any tag, you would use the has() method. Since you're looking for questions with a specific tag, you would use the whereHas() to add the condition.
So, if you want all the questions that have at least one tag with either 'Travel', 'Trains', or 'Culture', your query would look like:
$questions = Question::whereHas('tags', function($q) {
$q->whereIn('name', ['Travel', 'Trains', 'Culture']);
})->get();
If you wanted all questions that had all three of those tags, your query would look like:
$questions = Question::whereHas('tags', function($q) {
$q->where('name', 'Travel');
})->whereHas('tags', function($q) {
$q->where('name', 'Trains');
})->whereHas('tags', function($q) {
$q->where('name', 'Culture');
})->get();
$users = User::all();
$associates = Associate::all();
$userAndAssociate = $users->merge($associates);
Merge two different eloquent collections into one and some objects happen to have the same id, one will overwrite the other. Use push() method instead or rethink your approach to the problem to avoid that.
Refer to web
Creating a new base collection for each eloquent collection the merge works for me.
$foo = collect(Foo::all());
$bar = collect(Bar::all());
$merged = $foo->merge($bar);
In this case don't have conflits by its primary keys.
I have faced some issue by using merge. So I used concat. You can used it like below.
$users = User::all();
$associates = Associate::all();
$userAndAssociate = $users->concat($associates);
All do not work for me on eloquent collections, laravel eloquent collections use the key from the items I think which causes merging issues, you need to get the first collection back as an array, put that into a fresh collection and then push the others into the new collection;
public function getFixturesAttribute()
{
$fixtures = collect( $this->homeFixtures->all() );
$this->awayFixtures->each( function( $fixture ) use ( $fixtures ) {
$fixtures->push( $fixture );
});
return $fixtures;
}
I'm sorry about that, but since PHP 7.4 you're available to do like this (better use merge).
$foo = Foo::all();
$bar = Bar::all();
/** $foo will contain $foo + $bar */
$foo->push(...$bar);
I would like to add that, i found that the concat method does not seem to override based on ID, while the merge method does. concat seems to work for me, while merge caused issues.

How to merge Laravel objects in controller

I have a controller where I want to combine data from multiple tables with parallel structures. What I want to end up with in the end is one object I can return from the controller so I can parse it in Backbone.
I want to do something like this:
public function index()
{
$mc = MainContact::where('verified', '=', '1')->get();
$sm = SendMessage::where('verified', '=', '1')->get();
$obj = (object) array_merge((array) $mc, (array) $sm);
return $obj;
}
I'm told by another post on StackOverflow that this works in PHP 5.3+. However, this returns the following error in Laravel:
UnexpectedValueException: The Response content must be a string or object implementing
__toString(), "object" given.
How do I implement this method in Laravel? Both $mc and sm return valid objects in Laravel.
Nowadays you can use
$new_collection = $collection->merge($other_collection).
This works in Laravel 4 and seems to handle both arrays and collections.
What you can do here is merge the arrays of the two query result and then use the Response with json output like shown below.
$array = array_merge($mc->toArray(), $sm->toArray());
return Response::json($array);
We can use collection as below
$admins = User::where('type', '=', 'admin')->get();
$authors = User::where('type', '=', 'author')->get();
$admin_author_collection = $admins->merge($authors);
Also, Please refer the various collection methods to below link
http://laravel.com/api/4.2/Illuminate/Database/Eloquent/Collection.html
Route::get('test', function(){
$rank = Rank::get();
$policy = Policy::get();
$obj = (object)array_merge_recursive((array)$rank , (array)$policy);
var_dump($obj);
});
This is working for me. Instead of array_merge use array_merge_recursive().
You could simply use array_merge(firstObject,secondObject) function.
$obj = array_merge($mc, $sm);
return $obj;

Categories