Skip to content

Instantly share code, notes, and snippets.

@andy-berry-dev
Last active July 9, 2019 18:52
Show Gist options
  • Save andy-berry-dev/be3c45380568fc359cb61e00c4249704 to your computer and use it in GitHub Desktop.
Save andy-berry-dev/be3c45380568fc359cb61e00c4249704 to your computer and use it in GitHub Desktop.
Changes required to Laravel to allow observing attached/detached events (https://github.com/laravel/framework/pull/14988#issuecomment-267717423)
<?php
use App\Extensions\Relations\BelongsToMany;
abstract class AbstractModel extends Model
{
/*
* This is copied AS IS from \Illuminate\Database\Eloquent\Model@belongsToMany but instead uses our own BelongsToMany class
*/
public function belongsToMany($related, $table = null, $foreignKey = null, $otherKey = null, $relation = null)
{
if (is_null($relation)) {
$relation = $this->getBelongsToManyCaller();
}
$foreignKey = $foreignKey ?: $this->getForeignKey();
$instance = new $related;
$otherKey = $otherKey ?: $instance->getForeignKey();
if (is_null($table)) {
$table = $this->joiningTable($related);
}
$query = $instance->newQuery();
return new BelongsToMany($query, $this, $table, $foreignKey, $otherKey, $relation);
}
/*
* Override Model@observe and add replace . with _ for the observer callback
*/
public static function observe($class, $priority = 0)
{
$instance = new static;
$className = is_string($class) ? $class : get_class($class);
foreach ($instance->getObservableEvents() as $event) {
$methodName = str_replace('.', '_', $event);
if (method_exists($class, $methodName)) {
static::registerModelEvent($event, $className.'@'.$methodName, $priority);
}
}
}
}
?>
<?php
namespace App\Extensions\Relations;
use Exception;
use Illuminate\Support\Collection;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany as LaravelBelongsToMany;
class BelongsToMany extends LaravelBelongsToMany {
public function attach($ids, array $attributes = [], $touch = true)
{
$returnVal = parent::attach($ids, $attributes, $touch);
if ($ids instanceof EloquentCollection)
{
$ids = $ids->modelKeys();
}
else
{
$ids = [$ids];
}
foreach($ids as $id)
{
$attached = $id instanceof Model ? $this->find($id = $id->getKey()) : $this->find($id);
if ($attached)
{
$this->fireParentEvent("attached.{$this->relationName}", $attached, false);
}
}
return $returnVal;
}
public function detach($ids = [], $touch = true)
{
$results = parent::detach($ids, $touch);
if ($ids instanceof EloquentCollection)
{
$ids = $ids->modelKeys();
}
else
{
$ids = [$ids];
}
foreach($ids as $id)
{
$id = $id instanceof Model ? $id->getKey() : $id;
$this->fireParentEvent("detached.{$this->relationName}", $id, false);
}
return $results;
}
protected function fireParentEvent($event, $records, $halt = true)
{
$dispatcher = $this->getParent()->getEventDispatcher();
if (! $dispatcher)
{
return true;
}
$event = "eloquent.{$event}: ".get_class($this->getParent());
$method = $halt ? 'until' : 'fire';
return $dispatcher->$method($event, [$this->getParent(), $records]);
}
}
<?php
class MyModel extends AbstractModel
{
protected $observables = [
'attached.someRelationship',
'detached.someRelationship',
];
public function boot()
{
MyModel::attached_some_relationship(function ($model) {
// do something
});
}
// the rest of your model
}
?>
@marceux
Copy link

marceux commented Feb 22, 2017

You should update MyModel.php because detached is misspelled.

Copy link

ghost commented Mar 22, 2017

so that is working)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment