Created
November 17, 2012 22:38
-
-
Save asakurayoh/4100877 to your computer and use it in GitHub Desktop.
Single Table Inheritance in Laravel 4 / Illuminate
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; | |
use Illuminate\Database\Eloquent\Builder as BaseBuilder; | |
class Builder extends BaseBuilder{ | |
/** | |
* Override getModels so it send attributes to the newInstance methods (in newExisting) | |
*/ | |
public function getModels($columns = array('*')) | |
{ | |
// First, we will simply get the raw results from the query builders which we | |
// can use to populate an array with Eloquent models. We will pass columns | |
// that should be selected as well, which are typically just everything. | |
$results = $this->query->get($columns); | |
$connection = $this->model->getConnectionName(); | |
$models = array(); | |
// Once we have the results, we can spin through them and instantiate a fresh | |
// model instance for each records we retrieved from the database. We will | |
// also set the proper connection name for the model after we create it. | |
foreach ($results as $result) | |
{ | |
$models[] = $model = $this->model->newExisting((array) $result); | |
$model->setConnection($connection); | |
} | |
return $models; | |
} | |
} |
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 | |
// migration file | |
use Illuminate\Database\Migrations\Migration; | |
class CreateProductsTable extends Migration { | |
/** | |
* Run the migrations. | |
* | |
* @return void | |
*/ | |
public function up() | |
{ | |
Schema::create('products', function($table) | |
{ | |
$table->increments('id'); | |
$table->string('title'); | |
$table->string('product_type'); | |
$table->timestamps(); | |
$table->index('product_type'); | |
}); | |
} | |
/** | |
* Reverse the migrations. | |
* | |
* @return void | |
*/ | |
public function down() | |
{ | |
Schema::drop('products'); | |
} | |
} |
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; | |
use App\Product as BaseProduct; | |
class Merchandise extends BaseProduct { | |
} |
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; | |
use Illuminate\Database\Eloquent\Model; | |
use App\Builder; | |
class Product extends Model { | |
protected $table = 'products'; | |
protected $classField = 'product_type'; | |
public function __construct(array $attributes = array()) | |
{ | |
parent::__construct($attributes); | |
$this->{$this->classField} = get_class($this); | |
} | |
public function newInstance($attributes = array(), $exists = false) | |
{ | |
if($this->classField && isset($attributes[$this->classField])){ | |
$classname = $attributes[$this->classField]; | |
$model = new $classname; | |
}else{ | |
// May never be use / should not be use in this case, as it should never create a Product! | |
$model = new static; | |
} | |
/** | |
* Changed this part, so it use fill or setAttributes, if it come from an existing class or not, not directly via construct (which use fill) | |
*/ | |
if($exists){ | |
$model->setAttributes($attributes); | |
}else{ | |
$model->fill($attributes); | |
} | |
$model->exists = $exists; | |
return $model; | |
} | |
/** | |
* Override newQuery to use own Builder and add where automaticaly if not base class | |
*/ | |
public function newQuery() | |
{ | |
$builder = new Builder($this->newBaseQueryBuilder()); | |
$builder->setModel($this); | |
if($this->classField && get_class(new static) !== get_class(new self)){ | |
$builder->where($this->classField, get_class($this)); | |
} | |
return $builder; | |
} | |
} |
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 | |
// seed file | |
return array( | |
array( | |
'title' => 'Book 1', | |
'product_type' => 'Brainr\Model\Publication', | |
'created_at' => new DateTime, | |
'updated_at' => new DateTime, | |
), | |
array( | |
'title' => 'Magazine 2', | |
'product_type' => 'Brainr\Model\Publication', | |
'created_at' => new DateTime, | |
'updated_at' => new DateTime, | |
), | |
array( | |
'title' => 'Table 1', | |
'product_type' => 'Brainr\Model\Merchandise', | |
'created_at' => new DateTime, | |
'updated_at' => new DateTime, | |
), | |
array( | |
'title' => 'Chair 1', | |
'product_type' => 'Brainr\Model\Merchandise', | |
'created_at' => new DateTime, | |
'updated_at' => new DateTime, | |
), |
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; | |
use App\Product as BaseProduct; | |
class Publication extends BaseProduct { | |
} |
@elimentz it's single table inheritance which means it's only one table.
@asakurayoh any idea about concrete table inheritance? I desperately need this, but couldn't find a way to do it.
i've made a package for laravel 4+ to handle that: https://github.com/intrip/laravel-single-table-inheritance
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Can you elaborate on the table structure of both Publication and Merchandise? Do they each have their own separate database table custom attributes or do you keep the attributes of both models in one single Products table?