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
}
?>
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