E
E
EVOSandru62019-12-15 23:15:11
nested set
EVOSandru6, 2019-12-15 23:15:11

How to get all unique related attributes, own and descendants in hierarchical NestedSet model in eloquent?

Good afternoon.
There are 2 models:
Service (name, parent_id) + binding from lazychaser/laravel-nestedset

class Service extends Model
{
    use NodeTrait;

    protected $table = 'services';

    public function parent()
    {
        return $this->belongsTo(Service::class, 'parent_id');
    }
    public function attributes()
    {
        return $this->belongsToMany(Attribute::class, 'service_attribute');
    }

     public function allAttributesUp()
    {
        $ids = $this->ancestors->pluck('id')->merge($this->id)->toArray(); // ->toArray() [0]

        $parentAttributes = Attribute::whereHas('services', function ($q) use ($ids) {
            $q->whereIn('services.id', $ids);
        })->groupBy('id')->get();

        return $parentAttributes;
    }

}

and
class Attribute extends Model
{
    protected $table = 'attributes';
}

Entities are united at the database level by a link table service_attribute .
It is necessary in the child element to pull out all the attributes of its own and all of the parents, categorically without repetitions.
I wrote a test with the missing link for this case:
class AttributeValueTest extends TestCase

{

    public function test_check_services_hierarchy_by_node()
    {
        $parentService = factory(Service::class)->create();

        $childService = new Service();
        $childService->name = $this->faker->colorName;

        $parentService->appendNode($childService);
        $this->assertNotNull($childService->id);

        $qtyParentAttributes = 2;
        $parrentAttributes = factory(Attribute::class, $qtyParentAttributes)->create();
        $parentService->attributes()->sync($parrentAttributes->pluck('id'));

        $qtyChildAttributes = 3;
        $childAttributes = factory(Attribute::class, $qtyChildAttributes)->create();
        $childService->attributes()->sync($childAttributes->pluck('id'));

        self::assertEquals($parentService->attributes()->count(), $qtyParentAttributes);
        self::assertEquals($childService->attributes()->count(), $qtyChildAttributes);

        // self::assertEquals($childService->allAttributesUp()->count(), $qtyParentAttributes + $qtyChildAttributes);
    }
 }

How can the allAttributesUp method be implemented in a Service without recursion?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
E
EVOSandru6, 2019-12-16
@EVOSandru6

Added a method to Service:

public function allAttributesUp()
    {
        $ids = $this->ancestors->pluck('id')->merge($this->id)->toArray();

        $parentAttributes = Attribute::whereHas('services', function ($q) use ($ids) {
            $q->whereIn('services.id', $ids);
        })->groupBy('id')->get();

        return $parentAttributes;
    }

But I don’t like this option, I would like to know how in this case you can access attributes through something like $this->ancestors->attributes ?

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question