Laravel push to collection, changes prepend values to array - php

I'm following a tutorial to add infinity scroll with livewire, there's other approaches that's working but this one is different because it's using cursorPaginate and pushes the data to a collection. so instead of querying all the data each time you push new data to a collection.
class HomePage extends Component
{
public $posts; // holds are list of posts.
public $nextCursor; // holds our current page position.
public $hasMorePages;
/**
* Initialize data
* #return void
*/
public function mount()
{
$this->posts = collect(); // initialize the data
$this->loadPosts(); // load the data
}
/**
* Load data and maintain cursor state
*
*/
public function loadPosts()
{
if ($this->hasMorePages !== null && !$this->hasMorePages) {
return;
}
$posts = Post::cursorPaginate(
5,
['*'],
'cursor',
Cursor::fromEncoded($this->nextCursor)
);
$this->posts->push(...$posts->items());
$this->hasMorePages = $posts->hasMorePages();
if ($this->hasMorePages === true) {
$this->nextCursor = $posts->nextCursor()->encode();
}
}
}
the first call is woking as expected and returning the collection below:
Illuminate\Support\Collection {#1190 ▼
#items: array:5 [▼
0 => App\Models\Post {#1742 ▶}
1 => App\Models\Post {#1740 ▶}
2 => App\Models\Post {#1739 ▶}
3 => App\Models\Post {#1738 ▶}
4 => App\Models\Post {#1737 ▶}
]
#escapeWhenCastingToString: false
}
but when I scroll or do the second call. the old values are changed to array and then appending the new collection, the second call returns like that:
^ Illuminate\Support\Collection {#1178 ▼
#items: array:10 [▼
0 => array:18 [▶]
1 => array:18 [▶]
2 => array:18 [▶]
3 => array:18 [▶]
4 => array:17 [▶]
5 => App\Models\Post {#1760 ▶}
6 => App\Models\Post {#1758 ▶}
7 => App\Models\Post {#1757 ▶}
8 => App\Models\Post {#1756 ▶}
9 => App\Models\Post {#1755 ▶}
]
#escapeWhenCastingToString: false
}
what I have tried so far:
1- instead of pushing all the items I iterate through each item and then push it to the collection:
foreach($posts->items() as $item){
$this->posts->push($item);
}
2- instead of using collection using array:
public $posts = [];
foreach($posts->items() as $item){
array_push($this->posts, $item);
}
and others that I don't remember.
the strange thing is they are all returning the same thing for the first call and the second call, I have debugged the $posts variable for the first call and the second call they both return collections without issues.
the change happens only when pushing for the second time.
and the blade of course is like that:
#foreach($posts as $post)
<livewire:post-card :post="$post" :loop_index="$loop->index" wire:key="{{$loop->index}}"/>
#endforeach
#if($hasMorePages)
<div
x-data="{
init () {
let observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
#this.call('loadPosts')
}
})
}, {
root: null
});
observer.observe(this.$el);
}
}"
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 mt-4"
>
#foreach(range(1, 4) as $x)
#include('components.skeleton')
#endforeach
</div>
#endif

Related

Property [id] does not exist on this collection instance in laravel

store a query in array and call the result in view page show Property [id] does not exist on this collection
in controller
foreach($carvalue as $row){
$products[]=DB::table('products')->where('id',$row['product_id'] )->get();
}
and pass the products variable to view page and print the value like
foreach($products as $prod){
if($prod->id==$rows['product_id']){
//code
}
}
show the error and i dd($produts) the result is
array:2 [▼
0 => Illuminate\Support\Collection {#491 ▼
#items: array:1 [▼
0 => {#503 ▼
+"id": "130"
+"title": "Rfdfd"
+"sku": "vbff"
+"sub_title": "RC10 Matte Graphite"
}
]
}
1 => Illuminate\Support\Collection {#505 ▶}
]
why show this type error and how to solve it ?
In your query, replace get() with first()
$products[]=DB::table('products')->where('id',$row['product_id'] )->first();
OR
reference the first (and only) $products as $products[0], so it gets the id from the FIRST (and only, in your case) product
foreach($products[0] as $prod){
if($prod->id==$rows['product_id']){
//code
}
}

Merge 2 Collections or Arrays by Key

I'm trying my best to prevent from looping over a collection to get more data that I need for a data table. I need a way to combine these 2 collections or arrays.
I have 2 functions inside a model that calls an API that gives me an array of data that I convert into a collection.
Orders()
public function orders(){
$orders_array = $this->api()->request('orders.json');
return collect($orders_array);
}
Returns:
Collection {#274 ▼
#items: array:2 [▼
0 => {#282 ▼
+"id": 628602961977
}
1 => {#270 ▶}
order_meta()
public function order_meta($order_id){
$order_metafields_array = $this->api()->request('meta.json');
return collect($order_metafields_array);
}
Returns:
Collection
#items: [
+"name": "meta_data"
]
What I am wanting to do is inject the order_meta() into each order using the order ID.
I guess I am wanting to do something like this:
public function orders_detailed(){
$orders = $this->orders();
$keyed = $orders->mapWithKeys(function ($item) {
return [$item['meta'] => $this->order_metafields($item['id'])];
});
}
In hopes it will return:
Collection {#274 ▼
#items: array:2 [▼
0 => {#282 ▼
+"id": 628602961977
+meta => {
+"name":"meta_data"
}
}
1 => {#270 ▶}
Is something like this possible? I'm also open to merging it in as an array first, then creating a collection.

DB Laravel get and first in same time

I want to show only one result from "links, tags, pages", "->first()", but, I want to show multiple results from "comments", "->get()", separate it in one array, and send to view, how can I do this?
$link = DB::table('links')
->join('tags', 'tags.id', 'links.tag')
->join('pages', 'pages.id', '=', 'links.page_id')
->leftJoin('comments', 'comments.link_id', '=', 'links.id')
->select('links.photo', 'links.id', 'links.description', 'links.country', 'links.url', 'links.suggestions', 'links.shares', 'links.friendly_url', 'links.page_id', 'links.sponsored', 'links.clicks', 'links.title', 'tags.color', 'tags.id as tag_id', 'tags.name', 'pages.name as p_name', 'pages.description as p_description', 'pages.id as p_id', 'pages.followers', 'pages.links', 'pages.friendly_url as p_friendly_url', 'pages.photo as p_photo')
->where('links.friendly_url', $id)
->first();
return view('site.link', compact('link'));
DD($link);
0 => Link {#291 ▼
#relations: array:3 [▼
"page" => Page {#295 ▶}
"tag" => Tag {#289 ▶}
"comments" => Collection {#292 ▼
#items: array:2 [▼
0 => Comment {#299 ▶}
1 => Comment {#301 ▶}
]
}
]
You could use Eloquent. Define relationships:
public function page()
{
return $this->belongsTo(Page::class);
}
public function tag()
{
return $this->belongsTo(Tag::class, 'tag');
}
public function comments()
{
return $this->hasMany(Comment::class);
}
And do this:
Link::with('page', 'tag', 'comments')->where('friendly_url', $id)->first()

How to array_values laravel collection?

I have a search result from image model and $photo saved the data which $photo->type == 'photo'.
$photo = $image->filter(function($photo,$key) use($path){
if($photo->type == 'photo'){
$photo->url = $path.$photo->image;
return $photo;
}
});
Here is the $photo collection and is there any way to array_values() the items data?
Collection {#352 ▼
#items: array:3 [▼
2 => ImageBanquet {#349 ▶}
3 => ImageBanquet {#350 ▶}
4 => ImageBanquet {#351 ▶}
]
}
Check values() collection helper.
$values = $collection->values();

want to show separate data on monthly base

collection is obtrained like this
Collection {#241 ▼
#items: array:2 [▼
"Oct-2016" => Collection {#225 ▼
#items: array:1 [▼
0 => Event {#243 ▶}
]
}
"Nov-2016" => Collection {#236 ▼
#items: array:2 [▼
0 => Event {#244 ▶}
1 => Event {#245 ▶}
]
}
]
}
i want to show data like .
Oct 2016
event 1
Nov 2016
event 1
event 2
i am new in laravel kindly help me how to show collection key in title Oct-2016 and list of each key collection in blade
Laravel collections implement php's iterable functionality. In other words, you can just use foreach loops. This will give you the basic idea.
foreach ($collection as $month => $events)
{
var_dump($month);
foreach ($events as $event)
{
var_dump($event);
}
}

Categories