简体   繁体   中英

Laravel 5: how to update items (remove+add) in relation many to many

I'm using Laravel 5. There is a many to many relation

class Visit extends Model 
{
    public function visitors(): HasMany
    {
        return $this->hasMany(Visitor::class);
    }
}

From the request I get data in json format about all visitors, that bellong to the visit

[
    {
        "visitor_id": 111,
        "type": "owner"
    },
    {
        "visitor_id": 222,
        "type": "seller"
    },
    {
        "visitor_id": 444,
        "type": "buyer"
    },
]

Visit can have intially visitors

[
    {
        "visitor_id": 111,
        "type": "owner"
    },
    {
        "visitor_id": 222,
        "type": "seller"
    },
    {
        "visitor_id": 333,
        "type": "buyer"
    },
]

I need to update visitors: remove visitors, that have been gone, add new visitors and ignore existing. Notice, that visitor has also additional flag - "type", that I should take into account. So as a result it should be as in the 1st example

I didn't find any other solution then make 2 actions: one for delete and another for insert.

class VisitController
{
    private function updateVisitors(Visit $visit, Collection $newVisitors): void
    {
        $newVisitorsPluck = [];
        foreach ($newVisitors as $visitor) {
            $newVisitorsPluck[$visitor->getId()] = $visitor->getType();
        }

        $existingVisitors = $visit->Visitors()->pluck('visitor_type', 'visitor_id')->toArray();

        $this->deleteRemovedVisitors($visit, $newVisitorsPluck, $existingVisitors);

        $this->addNewVisitors($visit, $newVisitorsPluck, $existingVisitors);
    }

    private function deleteRemovedVisitors(Visit $visit, array $newVisitors, array $existingVisitors): void
    {
        $deleteItems = array_diff_assoc($existingVisitors, $newAVisitors);

        foreach ($deleteItems as $visitorId => $visitorType) {
            DB::table('visitors_table')
                ->where('visit_id', '=', $visit->getKey())
                ->where('visitor_id', '=', $visitorId)
                ->where('visitor_type', '=', $visitorType)
                ->delete();
        }
    }

    private function addNewVisitors(Visit $visit, array $newVisitors, array $existingVisitors): void
    {
        $addItems = array_diff_assoc($newVisitors, $existingVisitors);

        foreach ($addItems as $visitorId => $visitorType) {
            $visit->Visitors()->save(
                new Visitvisitor([
                ...
                ])
            );
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM