October CMS resources and help articles

Simple and to the point. Optimized by the community.

Bidirectional Belongs To Many Relationship

6
by seanthepottingshed, last modified on August 12th, 2019
<?php

namespace ThePottingShed\Relationships\Classes;

/**
 * Bidirectional Belongs To Many Relationship.
 */
class BidirectionalBelongsToManyRelationship
{
    /**
     * Attach.
     *
     * @param  October\Rain\Database\Model $model
     * @param  integer $insertedData
     * @param  string  $relationName
     * @param  string  $keyName
     * @param  string  $otherKeyName
     *
     * @return void
     */
    public static function attach($model, $insertedData, $relationName, $keyName, $otherKeyName)
    {
        if (!empty($insertedData)) {
            $record      = $insertedData[0];
            $key         = $record[$keyName];
            $otherKey    = $record[$otherKeyName];
            $otherRecord = $model::find($otherKey);
            $otherRecord->{$relationName}()->syncWithoutDetaching($key);
        }
    }

    /**
     * Detach.
     *
     * @param  October\Rain\Database\Model $model
     * @param  integer $attachedIdList
     * @param  string $relationName
     *
     * @return void
     */
    public static function detach($model, $attachedIdList, $relationName)
    {
        if (!empty($attachedIdList)) {
            $key = $model->id;
            foreach ($attachedIdList as $otherKey) {
                $otherRecord = $model::find($otherKey);
                $otherKeys   = collect($otherRecord->{$relationName}->lists('id'))->reject(function ($otherKey) use ($key) {
                    return $otherKey === $key;
                });
                $otherRecord->{$relationName}()->sync($otherKeys);
            }
        }
    }
}

Usage from Plugin.php boot method:

/**
 * Boot.
 *
 * @return void
 */
public function boot()
{
    \RainLab\Blog\Models\Post::extend(function ($model) {
        $model->belongsToMany += [
            'related_blog_posts' => [
                'RainLab\Blog\Models\Post',
                'table'    => 'tps_blog_posts_blog_posts',
                'key'      => 'bp_id',
                'otherKey' => 'rbp_id',
                'order'    => 'title',
                'scope'    => 'isPublished',
            ],
        ];
        $model->bindEvent('model.relation.afterAttach', function ($relationName, $attachedIdList, $insertData) use ($model) {
            if ($relationName === 'related_blog_posts') {
                BidirectionalBelongsToManyRelationship::attach($model, $insertData, $relationName, $keyName = 'bp_id', $otherKeyName = 'rbp_id');
            }
        });
        $model->bindEvent('model.relation.afterDetach', function ($relationName, $attachedIdList) use ($model) {
            if ($relationName === 'related_blog_posts') {
                BidirectionalBelongsToManyRelationship::detach($model, $attachedIdList, $relationName);
            }
        });
    });
}

Discussion

0 comments

We use cookies to measure the performance of this website. Do you want to accept these cookies?