Created
July 19, 2017 13:07
-
-
Save TsuiAnthonYVR/1435e18ee76f095e2c348affa1dc060b to your computer and use it in GitHub Desktop.
How to get Laravel to fire model attach/detach events
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php namespace App\Relations; | |
use Illuminate\Database\Eloquent\Builder; | |
use Illuminate\Database\Eloquent\Model; | |
class BelongsToMany extends \Illuminate\Database\Eloquent\Relations\BelongsToMany { | |
/** | |
* Attach a model to the parent. | |
* | |
* @param mixed $id | |
* @param array $attributes | |
* @param bool $touch | |
* @return void | |
*/ | |
public function attach($id, array $attributes = array(), $touch = true) { | |
// Process the actual functionality first. | |
parent::attach($id, $attributes, $touch); | |
if ($id instanceof Model) { | |
$id = $id->getKey(); | |
} | |
// Fire an event | |
$parentId = $this->parent->id; | |
$childId = $id; | |
$pivotInfo = [ | |
// e.g. "user_team" | |
'table' => $this->table, | |
// e.g. "user_id" => 123 | |
$this->foreignKey => $this->parent->id, | |
// e.g. "team_id" => 456 | |
$this->otherKey => $id, | |
]; | |
// Fire the event. | |
\Event::fire(new \App\Events\PivotWasCreated($pivotInfo)); | |
} | |
/** | |
* Detach models from the relationship. | |
* | |
* @param int|array $ids | |
* @param bool $touch | |
* @return int | |
*/ | |
public function detach($ids = array(), $touch = true) { | |
// Process the actual functionality first. | |
$ids = (is_array($ids))?:[$ids]; | |
$result = parent::detach($ids, $touch); | |
// Fire an event for each deleted pivot. | |
foreach($ids as $id) { | |
$parentId = $this->parent->id; | |
$childId = $id; | |
$pivotInfo = [ | |
// e.g. "user_team" | |
'table' => $this->table, | |
// e.g. "user_id" => 123 | |
$this->foreignKey => $this->parent->id, | |
// e.g. "team_id" => 456 | |
$this->otherKey => $id, | |
]; | |
\Event::fire(new \App\Events\PivotWasDeleted($pivotInfo)); | |
} | |
return $result; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php namespace App\Handlers\Event; | |
class HandlePivotEvent { | |
/** | |
* handlePivotEvent function. | |
* | |
* @param \App\Events\Event $pivotEvent | |
*/ | |
public function handle(\App\Events\Event $pivotEvent) | |
{ | |
// Determine whether this is an attach or detach event. | |
switch (get_class($pivotEvent)) { | |
case 'App\Events\PivotWasCreated': | |
$eventName = 'attach'; | |
break; | |
case 'App\Events\PivotWasDeleted': | |
$eventName = 'detach'; | |
break; | |
default: | |
// Unknown event | |
return; | |
} | |
// Get a list of all attributes that are foreign keys. | |
$modelKeys = $this->extractModelKeys($pivotEvent->pivotInfo); | |
// do your useful work here | |
} | |
/** | |
* extractModelKeys function. | |
* | |
* @param array $fieldNames | |
* | |
* @return array | |
*/ | |
protected function extractModelKeys(array $fieldNames) | |
{ | |
$modelKeys = []; | |
foreach ($fieldNames as $fieldName => $value) { | |
if (preg_match('/([^_]+)_id/', $fieldName, $matches)) { | |
// This field is a key | |
$modelKeys[strtolower($matches[1])] = $value; | |
} | |
} | |
// Ensure our model keys are always in the same order. | |
ksort($modelKeys); | |
return $modelKeys; | |
} // function extractModelKeys | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php namespace app\Traits; | |
/** | |
* ManagedCacheTrait Trait. | |
* | |
* Provides managed cache in the parent model. | |
* | |
*/ | |
trait PivotTrait | |
{ | |
/** | |
* Define a many-to-many relationship. | |
* | |
* @param string $related | |
* @param string $table | |
* @param string $foreignKey | |
* @param string $otherKey | |
* @param string $relation | |
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany | |
*/ | |
public function belongsToMany($related, $table = null, $foreignKey = null, $otherKey = null, $relation = null, $farKey = null) | |
{ | |
// copied from https://github.com/illuminate/database/blob/master/Eloquent/Model.php#L963 | |
if (is_null($relation)) { | |
$relation = $this->getBelongsToManyCaller(); | |
} | |
$foreignKey = $foreignKey ?: $this->getForeignKey(); | |
$instance = new $related; | |
if ($farKey) { | |
$instance = $instance->setKeyName($farKey); | |
} | |
$otherKey = $otherKey ?: $instance->getForeignKey(); | |
if (is_null($table)) { | |
$table = $this->joiningTable($related); | |
} | |
$query = $instance->newQuery(); | |
return new \App\Relations\BelongsToMany($query, $this, $table, $foreignKey, $otherKey, $relation); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php namespace App\Events; | |
use App\Events\Event; | |
use Illuminate\Queue\SerializesModels; | |
class PivotWasCreated extends Event { | |
use SerializesModels; | |
public $pivotInfo; | |
/** | |
* Create a new event instance. | |
* | |
* @return void | |
*/ | |
public function __construct(array $pivotInfo) { | |
$this->pivotInfo = $pivotInfo; | |
} | |
} // PivotWasCreated Event |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php namespace App\Events; | |
use App\Events\Event; | |
use Illuminate\Queue\SerializesModels; | |
class PivotWasDeleted extends Event { | |
use SerializesModels; | |
public $pivotInfo; | |
/** | |
* Create a new event instance. | |
* | |
* @return void | |
*/ | |
public function __construct(array $pivotInfo) { | |
$this->pivotInfo = $pivotInfo; | |
} | |
} // PivotWasDeleted Event |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment