Skip to content

Instantly share code, notes, and snippets.

@kapv89
Last active December 20, 2015 08:29
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kapv89/6100725 to your computer and use it in GitHub Desktop.
Save kapv89/6100725 to your computer and use it in GitHub Desktop.
Single Table inheritance model
use Illuminate\Database\Eloquent;
use Illuminate\Database\Eloquent\Builder;
abstract class AbstractEloquent extends Eloquent\Model {
protected $isSuperType = false; // set true if super-class model
protected $isSubType = false; // set true in inherited models
protected $typeField = 'type'; //override as needed, only set on the super-class model
/**
* Provide an attributes to object map
*
* @return Model
*/
public function mapData(array $attributes)
{
if(! $this->isSuperType)
{
return $this->newInstance();
}
else
{
if(! isset($attributes[$this->typeField]))
{
throw new \DomainException($this->typeField . ' not present in the records of a Super Model');
}
else
{
$class = $attributes[$this->typeField];
return new $class;
}
}
}
/**
* Create a new model instance requested by the builder.
*
* @param array $attributes
* @return Illuminate\Database\Eloquent\Model
*/
public function newFromBuilder($attributes = array())
{
$m = $this->mapData((array) $attributes)->newInstance(array(), true);
$m->setRawAttributes((array) $attributes);
return $m;
}
/**
* Get a new query builder for the model's table.
*
* @return Reposed\Builder
*/
public function newRawQuery()
{
$builder = new Builder($this->newBaseQueryBuilder());
// Once we have the query builders, we will set the model instances
// so the builder can easily access any information it may need
// from the model while it is constructing and executing various
// queries against it.
$builder->setModel($this)->with($this->with);
return $builder;
}
/**
* Get a new query builder for the model.
* set any type of scope you want on this builder in a child class, and it'll
* keep applying the scope on any read-queries on this model
*
* @return Reposed\Builder
*/
public function newQuery($excludeDeleted = true)
{
$builder = $this->newRawQuery();
if ($excludeDeleted and $this->softDelete)
{
$builder->whereNull($this->getQualifiedDeletedAtColumn());
}
return $builder;
}
/**
* Save the model to the database.
*
* @return bool
*/
public function save(array $options = array())
{
if($this->isSubType)
{
$this->attributes[$this->typeField] = get_class($this);
}
$query = $this->newRawQuery();
// If the "saving" event returns false we'll bail out of the save
// and return false, indicating that the save failed.
// This gives an opportunities to listeners to cancel save operations
// if validations fail or whatever.
if ($this->fireModelEvent('saving') === false)
{
return false;
}
// If the model already exists in the database we can just update
// our record that is already in this database using the current IDs
// in this "where" clause to only update this model.
// Otherwise, we'll just insert them.
if ($this->exists)
{
$saved = $this->performUpdate($query);
}
// If the model is brand new, we'll insert it into our database
// and set the ID attribute on the model to the value of the newly
// inserted row's ID which is typically an auto-increment value
// managed by the database.
else
{
$saved = $this->performInsert($query);
$this->exists = $saved;
}
if ($saved) $this->finishSave($options);
return $saved;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment