Skip to content

Commit

Permalink
Change some implementations and update documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
calebporzio committed Jun 28, 2018
1 parent c22dcc9 commit ad1ed40
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 8 deletions.
38 changes: 38 additions & 0 deletions readme.md
Expand Up @@ -88,3 +88,41 @@ User::all();

### What's happening?
Before, when we just added the `HasParentModel`, we got half-way there. That enabled us to find, retreive, and use the `Admin` model, instead of the `User` model. However, this is only one side of the equation. Before, if we ran: `User::first()` we would only get back `User` models. By simply adding the `ReturnsChildModels` to the `User` model, now running `User::first()` will return an instance of whatever model, that `User` is supposed to be. To accomplish this sort polymorphic behavior, we need to use a `type` column on the `users` table to keep track of what model instance to return from User queries.

## Type Aliases
If for some reason you don't want to store raw class names in the type column, you can override them using the `$childTypeAliases` property.

```php
use Tightenco\Parental\ReturnsChildModels;

class User extends Model
{
use ReturnsChildModels;

protected $childTypeAliases = [
'admin' => App\Admin::class,
];
}
```

Now, running `Admin::create()` will set the `type` column in the `users` table to `admin` instead of `App\Admin`.

This feature is useful for those who are already using a type column with a different naming scheme, or those who don't want to store application classes directly in the database.

## Custom Type Column
You can override the default type column by setting the `$childTypeColumn` property on the parent model.

```php
use Tightenco\Parental\ReturnsChildModels;

class User extends Model
{
use ReturnsChildModels;

protected $childTypeColumn = 'parental_type';
}
```

---

Thanks to @sschoger for the sick logo design, and @DanielCoulbourne for helping brainstorm the idea on [Twenty Percent Time](http://twentypercent.fm/).
4 changes: 2 additions & 2 deletions src/HasParentModel.php
Expand Up @@ -14,7 +14,7 @@ public static function bootHasParentModel()
static::creating(function ($model) {
if ($model->parentHasReturnsChildModelsTrait()) {
$model->forceFill(
[$model->getInhertanceColumn() => get_class($model)]
[$model->getInhertanceColumn() => $model->classToAlias(get_class($model))]
);
}
});
Expand All @@ -23,7 +23,7 @@ public static function bootHasParentModel()
$instance = new static;

if ($instance->parentHasReturnsChildModelsTrait()) {
$query->where($instance->getInhertanceColumn(), get_class($instance));
$query->where($instance->getInhertanceColumn(), $instance->classToAlias(get_class($instance)));
}
});
}
Expand Down
28 changes: 23 additions & 5 deletions src/ReturnsChildModels.php
Expand Up @@ -74,19 +74,37 @@ public function getClassNameForRelationships()

public function getInhertanceColumn()
{
return $this->inheritanceColumn ?: 'type';
return $this->childTypeColumn ?: 'type';
}

protected function getChildModel(array $attributes)
{
$className = $attributes[$this->getInhertanceColumn()];
$className = $this->classFromAlias(
$attributes[$this->getInhertanceColumn()]
);

return new $className((array)$attributes);
}

protected function classFromAlias($aliasOrClass)
{
if (property_exists($this, 'childTypeAliases')) {
if (isset($this->childTypeAliases[$className])) {
$className = $this->childTypeAliases[$className];
if (isset($this->childTypeAliases[$aliasOrClass])) {
return $this->childTypeAliases[$aliasOrClass];
}
}

return new $className((array)$attributes);
return $aliasOrClass;
}

protected function classToAlias($className)
{
if (property_exists($this, 'childTypeAliases')) {
if (in_array($className, $this->childTypeAliases)) {
return array_search($className, $this->childTypeAliases);
}
}

return $className;
}
}
31 changes: 31 additions & 0 deletions tests/Features/TypeColumnCanBeAliased.php
@@ -0,0 +1,31 @@
<?php

namespace Tightenco\Parental\Tests\Features;

use Tightenco\Parental\Tests\Models\Car;
use Tightenco\Parental\Tests\Models\Plane;
use Tightenco\Parental\Tests\Models\Vehicle;
use Tightenco\Parental\Tests\TestCase;

class TypeColumnCanBeAliased extends TestCase
{
/** @test */
function type_column_values_can_accept_type_aliases()
{
Car::create(['type' => 'car']);
Plane::create(['type' => Plane::class]);

$vehicles = Vehicle::all();

$this->assertInstanceOf(Car::class, $vehicles[0]);
$this->assertInstanceOf(Plane::class, $vehicles[1]);
}

/** @test */
function type_aliases_are_set_on_creation()
{
$car = Car::create();

$this->assertEquals('car', $car->fresh()->type);
}
}
2 changes: 1 addition & 1 deletion tests/Models/Trip.php
Expand Up @@ -9,7 +9,7 @@ class Trip extends Model
{
use ReturnsChildModels;

protected $inheritanceColumn = 'trip_type';
protected $childTypeColumn = 'trip_type';

protected $guarded = [];

Expand Down

0 comments on commit ad1ed40

Please sign in to comment.