Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add proper event for syncing #84

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.DS_Store
/vendor
/.idea
composer.lock
Expand Down
58 changes: 40 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ You can check all eloquent events here: https://laravel.com/docs/5.5/eloquent#e
New events are :

```
pivotSyncing, pivotSynced,
pivotAttaching, pivotAttached
pivotDetaching, pivotDetached,
pivotUpdating, pivotUpdated
Expand All @@ -56,6 +57,14 @@ public static function boot()
{
parent::boot();

static::pivotSyncing(function ($model, $relationName) {
//
});

static::pivotSynced(function ($model, $relationName, $changes) {
//
});

static::pivotAttaching(function ($model, $relationName, $pivotIds, $pivotIdsAttributes) {
//
});
Expand Down Expand Up @@ -115,11 +124,9 @@ Dispatches **one** **pivotUpdating** and **one** **pivotUpdated** event.
You can change only one row in the pivot table with updateExistingPivot.

**sync()**
Dispatches **more** **pivotAttaching** and **more** **pivotAttached** events, depending on how many rows are added in the pivot table. These events are not dispatched if nothing is attached.
Dispatches **one** **pivotDetaching** and **one** **pivotDetached** event, but you can see all deleted ids in the $pivotIds variable. This event is not dispatched if nothing is detached.
E.g. when you call sync() if two rows are added and two are deleted **two** **pivotAttaching** and **two** **pivotAttached** events and **one** **pivotDetaching** and **one** **pivotDetached** event will be dispatched.
If sync() is called but rows are not added or deleted events are not dispatched.

Dispatches **one** **pivotSyncing** and **one** **pivotSynced** event.
*How does it work:* The sync first detaches all associations and then attaches or updates new entries one by one.
Whether a row was attached/detached/updated during sync only **one** event is dispatched for all rows but in that case, you can see all the attached/detached/updated rows in the $changes variables.

## Usage

Expand All @@ -138,6 +145,13 @@ class User extends Model
return $this->belongsToMany(Role::class);
}

static::pivotSynced(function ($model, $relationName, $changes) {
echo 'pivotSynced';
echo get_class($model);
echo $relationName;
print_r($changes);
});

static::pivotAttached(function ($model, $relationName, $pivotIds, $pivotIdsAttributes) {
echo 'pivotAttached';
echo get_class($model);
Expand Down Expand Up @@ -254,28 +268,36 @@ roles

### Syncing:

For sync() method event is dispatched for each pivot row.

Running this code
Running this code
```php
$user = User::first();
$user->roles()->sync([1, 2]);
$user->roles()->attach([
1 => ['pivot_attribut' => 1],
2 => ['pivot_attribut' => 0]
]);
$user->roles()->sync([
1 => ['pivot_attribut' => 0]
3 => ['pivot_attribut' => 1]
]);
```

You will see this output

```
pivotAttached
App\Models\User
roles
[1]
[1 => []]

pivotAttached
pivotSynced
App\Models\User
roles
[2]
[2 => []]
[
"attached" => [
0 => 3
]
"detached" => [
1 => 2
]
"updated" => [
0 => 1
]
]
```

### Detaching:
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
}
],
"require": {
"illuminate/database": "^5.5|^6.0|^7.0|^8.0"
"illuminate/database": "^5.5|^6.0|^7.0|^8.0|^9.0"
},
"require-dev": {
"orchestra/testbench": "*",
Expand Down
24 changes: 24 additions & 0 deletions src/Traits/FiresPivotEventsTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,30 @@

trait FiresPivotEventsTrait
{
/**
* Sync the intermediate tables with a list of IDs or collection of models.
*
* @param mixed $ids
* @param bool $detaching
*
* @return array
*/
public function sync($ids, $detaching = true)
{
if (false === $this->parent->fireModelEvent('pivotSyncing', true, $this->getRelationName())) {
return false;
}

$parentResult = [];
$this->parent->withoutEvents(function () use ($ids, $detaching, &$parentResult) {
$parentResult = parent::sync($ids, $detaching);
});

$this->parent->fireModelEvent('pivotSynced', false, $this->getRelationName(), $parentResult);

return $parentResult;
}

/**
* Attach a model to the parent.
*
Expand Down
11 changes: 11 additions & 0 deletions src/Traits/PivotEventTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public function getObservableEvents()
return array_merge(
parent::getObservableEvents(),
[
'pivotSyncing', 'pivotSynced',
'pivotAttaching', 'pivotAttached',
'pivotDetaching', 'pivotDetached',
'pivotUpdating', 'pivotUpdated',
Expand All @@ -25,6 +26,16 @@ public function getObservableEvents()
);
}

public static function pivotSyncing($callback, $priority = 0)
{
static::registerModelEvent('pivotSyncing', $callback, $priority);
}

public static function pivotSynced($callback, $priority = 0)
{
static::registerModelEvent('pivotSynced', $callback, $priority);
}

public static function pivotAttaching($callback, $priority = 0)
{
static::registerModelEvent('pivotAttaching', $callback, $priority);
Expand Down