Skip to content

Commit 8453b8e

Browse files
committed
Add support for query results and instantiation
1 parent c457ed7 commit 8453b8e

File tree

1 file changed

+133
-5
lines changed

1 file changed

+133
-5
lines changed

src/Inheritance.php

Lines changed: 133 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace ProAI\Inheritance;
44

55
use Illuminate\Support\Str;
6+
use Exception;
67

78
trait Inheritance
89
{
@@ -20,14 +21,35 @@ trait Inheritance
2021
*/
2122
public static $inheritanceType;
2223

24+
/**
25+
* Create a new Eloquent model instance.
26+
*
27+
* @param array $attributes
28+
* @return void
29+
*/
30+
public function __construct(array $attributes = [])
31+
{
32+
$type = $attributes[static::$inheritanceColumn] ?? null;
33+
34+
if (static::isRootModel() && $type) {
35+
[$one, $caller] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
36+
37+
if (! isset($caller['class']) || ! $caller['class'] || ! $this instanceof $caller['class']) {
38+
throw new Exception('Model cannot be instantiated. Please use '.static::class.'::new instead.');
39+
}
40+
}
41+
42+
parent::__construct($attributes);
43+
}
44+
2345
/**
2446
* Bootstrap the inheritance trait.
2547
*
2648
* @return void
2749
*/
2850
protected static function bootInheritance()
2951
{
30-
if (! static::modelInherited()) {
52+
if (static::isRootModel()) {
3153
return;
3254
}
3355

@@ -41,13 +63,13 @@ protected static function bootInheritance()
4163
}
4264

4365
/**
44-
* Check if model is inherited.
66+
* Check if model is root model.
4567
*
4668
* @return bool
4769
*/
48-
protected static function modelInherited()
70+
protected static function isRootModel()
4971
{
50-
return self::class !== static::class;
72+
return self::class === static::class;
5173
}
5274

5375
/**
@@ -61,7 +83,88 @@ protected static function getInheritanceType()
6183
return static::$inheritanceType;
6284
}
6385

64-
return static::$inheritanceType = static::class;
86+
$class = static::class;
87+
$flippedMap = array_flip(static::$inheritanceMap ?? []);
88+
89+
if (isset($flippedMap[$class])) {
90+
$type = $flippedMap[$class];
91+
} else {
92+
$type = $class;
93+
}
94+
95+
return static::$inheritanceType = $type;
96+
}
97+
98+
/**
99+
* Create a new instance of the model by type.
100+
*
101+
* @param array $attributes
102+
* @return static
103+
*/
104+
public static function new($attributes = [])
105+
{
106+
$class = static::getChildClass($attributes);
107+
108+
if ($class) {
109+
return new $class($attributes);
110+
}
111+
112+
return new static($attributes);
113+
}
114+
115+
/**
116+
* Create a new instance of the model by type.
117+
*
118+
* @param array $attributes
119+
* @param bool $exists
120+
* @return static
121+
*/
122+
public function newInstance($attributes = [], $exists = false)
123+
{
124+
$class = static::getChildClass($attributes);
125+
126+
// This method just provides a convenient way for us to generate fresh model
127+
// instances of this current model. It is particularly useful during the
128+
// hydration of new objects via the Eloquent query builder instances.
129+
$model = $class ? new $class : new static;
130+
131+
$model->exists = $exists;
132+
133+
$model->setConnection(
134+
$this->getConnectionName()
135+
);
136+
137+
$model->setTable($this->getTable());
138+
139+
$model->mergeCasts($this->casts);
140+
141+
$model->fill((array) $attributes);
142+
143+
return $model;
144+
}
145+
146+
/**
147+
* Create a new model instance that is existing.
148+
*
149+
* @param array $attributes
150+
* @param string|null $connection
151+
* @return static
152+
*/
153+
public function newFromBuilder($attributes = [], $connection = null)
154+
{
155+
$attributes = (array) $attributes;
156+
157+
$type = $attributes[static::$inheritanceColumn] ?? null;
158+
159+
$model = $this->newInstance([static::$inheritanceColumn => $type], true);
160+
161+
$model->setRawAttributes($attributes, true);
162+
163+
$model->setConnection($connection ?: $this->getConnectionName());
164+
165+
$model->fireModelEvent('retrieved', false);
166+
167+
return $model;
65168
}
66169

67170
/**
@@ -93,4 +196,29 @@ protected function getRootClass()
93196
{
94197
return self::class;
95198
}
199+
200+
/**
201+
* Get the class name of the child class.
202+
*
203+
* @param array $attributes
204+
* @return ?string
205+
*/
206+
protected static function getChildClass($attributes)
207+
{
208+
if (! static::isRootModel()) {
209+
return null;
210+
}
211+
212+
if (! isset($attributes[static::$inheritanceColumn])) {
213+
return null;
214+
}
215+
216+
$type = $attributes[static::$inheritanceColumn];
217+
218+
if (! isset(static::$inheritanceMap)) {
219+
return $type;
220+
}
221+
222+
return static::$inheritanceMap[$type] ?? $type;
223+
}
96224
}

0 commit comments

Comments
 (0)