laravel-nestedset icon indicating copy to clipboard operation
laravel-nestedset copied to clipboard

502 error with livewire

Open Roywcm opened this issue 4 years ago • 7 comments

I tried to use this package in combination with Livewire. It works great until my tree has child elements. That's when I get a 502 error for some reason.

Strange thing is, it works when I dump the result in Livewire. But when the result is send to the Livewire view, I got this nginx error:

upstream prematurely closed connection while reading response header from upstream

Any idea why this is happening? Or is this a bug in Livewire? Not sure where to look. It happens when the function LinkNodes is fired on this piece of code:

foreach ($children as $child) {
        $child->setRelation('parent', $node);
}

Roywcm avatar Dec 18 '20 11:12 Roywcm

I think this problem is similar #17 fix commit

And maybe need to add something like this to Kalnoy\Nestedset\NodeTrait:

public function getQueueableRelations()
{
    $relations = $this->getRelations();

    if (!isset($relations['parent'])) {
        return parent::getQueueableRelations();
    }

    $parent = $relations['parent'];
    unset($relations['parent']);

    $this->setRelations($relations);
    $result = parent::getQueueableRelations();

    $relations['parent'] = $parent;
    $this->setRelations($relations);

    return $result;
}

Problem: 1. Livewire uses trait \Illuminate\Queue\HydratePublicProperties https://github.com/livewire/livewire/blob/master/src/HydrationMiddleware/HydratePublicProperties.php#L18

method getSerializedPropertyValue() https://github.com/livewire/livewire/blob/master/src/HydrationMiddleware/HydratePublicProperties.php#L152 https://github.com/livewire/livewire/blob/master/src/HydrationMiddleware/HydratePublicProperties.php#L176

  1. method getSerializedPropertyValue() run Model::getQueueableRelations()

And all this goes into a infinite cycle =(

up: or add to livewire component:

public function dehydrate()
{
    $this->model->unsetRelations();
}

kzgzhn avatar Dec 22 '20 17:12 kzgzhn

@kzgzhn solutions didn't work for me, but

After a few hours of debugging I think I found a way to get this done (I needed a collection of categories) using a private Collection $categories; instead of a public and passing it with the render method (return view('livewire.category.index', ['categories' => $this->categories]);) worked for me

This is however something that still should get looked at / documented, specially since most laravel 8 applications will use livewire (or inertia depending on your setup)

If anyone finds a better way, so I can keep my parameter public, please do share :pray:

briavers avatar Apr 05 '21 12:04 briavers

Hi, any solutions to this? I stumble to a problem with infinite loop, though.

sawirricardo avatar Aug 24 '21 11:08 sawirricardo

@kzgzhn solutions didn't work for me, but

After a few hours of debugging I think I found a way to get this done (I needed a collection of categories) using a private Collection $categories; instead of a public and passing it with the render method (return view('livewire.category.index', ['categories' => $this->categories]);) worked for me

This is however something that still should get looked at / documented, specially since most laravel 8 applications will use livewire (or inertia depending on your setup)

If anyone finds a better way, so I can keep my parameter public, please do share pray

Works for me. Thanks :+1:

fer-ri avatar Oct 25 '21 01:10 fer-ri

+1

vildanbina avatar Jan 18 '22 10:01 vildanbina

I have this problem too. Private properties do not persists between requests so it's not working properly for me.

stefanocurnis avatar Aug 13 '22 13:08 stefanocurnis

I had this issue and found an alternative workaround. In my case, my query looks like this:

$categories = Category::select(array_merge($select, ['is_private', 'parent_id']))
            ->with($with)
            ->defaultOrder()
            ->get()
            ->keyBy('id');

The problem I had was with calling toTree() (which in turn calls linkNodes()) on the resulting collection. However, I noticed the collection is already a tree structure, just with nested nodes also appearing at the top level. Removing those nodes seems to give the same result as toTree() without causing an infinite loop when it's serialised:

foreach ($categories as $id => $category) {
    if ($category->parent_id != null) {
        $categories->forget($id);
    }
}

It's not ideal, but none of the other suggestions worked for me.

EDIT: I realised this doesn't work as the nodes are not ordered correctly. I ended up writing a recursive function to null the parent relationships after calling toTree():

function removeParentRelationships(Collection $categories): Collection
{
    $categories->each(function ($category) {
        $category->setRelation('parent', null);
        if ($category->children) {
            $category->children = removeParentRelationships($category->children);
        }
    });

    return $categories;
}

I don't know why, but using makeHidden('parent') / setHidden(['parent']) on the collection (or specifying $hidden = ['parent'] in the model) wouldn't work for me.

Riari avatar Mar 23 '24 12:03 Riari