diff --git a/src/VirtualColumn.php b/src/VirtualColumn.php index 82de5aa..d2f5d8e 100644 --- a/src/VirtualColumn.php +++ b/src/VirtualColumn.php @@ -45,7 +45,10 @@ trait VirtualColumn } foreach ($model->getAttributes() as $key => $value) { - if (! in_array($key, static::getCustomColumns())) { + + if ((static::getVirtualColumns() && in_array($key, static::getVirtualColumns(), true)) + || ! in_array($key, static::getCustomColumns()) + ) { $current = $model->getAttribute(static::getDataColumn()) ?? []; $model->setAttribute(static::getDataColumn(), array_merge($current, [ @@ -133,6 +136,13 @@ trait VirtualColumn return 'data'; } + public static function getVirtualColumns(): array + { + return [ + // + ]; + } + public static function getCustomColumns(): array { return [ diff --git a/tests/VirtualColumnTest.php b/tests/VirtualColumnTest.php index 247b189..88d89bd 100644 --- a/tests/VirtualColumnTest.php +++ b/tests/VirtualColumnTest.php @@ -57,6 +57,49 @@ class VirtualColumnTest extends TestCase $this->assertSame(null, $model->data); } + /** @test */ + public function keys_defined_in_the_virtual_columns_function_go_into_data_json_column() + { + $model = VirtualModel::create([ + 'id' => 1, + 'foo' => 'bar', + ]); + + // Test that model works correctly + $this->assertSame(1, $model->id); + $this->assertSame('bar', $model->foo); + $this->assertSame(null, $model->data); + + // Low level test to assert database structure + $this->assertSame(['foo' => 'bar'], json_decode(DB::table('virtual_models')->where('id', $model->id)->first()->data, true)); + $this->assertSame(null, DB::table('virtual_models')->where('id', $model->id)->first()->foo ?? null); + + // Model has the correct structure when retrieved + $model = VirtualModel::first(); + $this->assertSame('bar', $model->foo); + $this->assertSame('bar', $model->getOriginal('foo')); + $this->assertSame(null, $model->data); + + // Model can be updated + $model->update([ + 'foo' => 'baz', + 'abc' => 'xyz', + ]); + + $this->assertSame('baz', $model->foo); + $this->assertSame('baz', $model->getOriginal('foo')); + $this->assertSame('xyz', $model->abc); + $this->assertSame('xyz', $model->getOriginal('abc')); + $this->assertSame(null, $model->data); + + // Model can be retrieved after update & is structure correctly + $model = VirtualModel::first(); + + $this->assertSame('baz', $model->foo); + $this->assertSame('xyz', $model->abc); + $this->assertSame(null, $model->data); + } + /** @test */ public function model_is_always_decoded_when_accessed_by_user_event() { @@ -125,6 +168,24 @@ class MyModel extends Model } } +class VirtualModel extends Model +{ + use VirtualColumn; + + protected $guarded = []; + public $timestamps = false; + + public static function getVirtualColumns(): array + { + return [ + 'foo', + 'abc', + 'baz', + 'xyz', + ]; + } +} + class FooModel extends Model { use VirtualColumn; diff --git a/tests/etc/migrations/2022_10_24_000001_create_virtual_models_table.php b/tests/etc/migrations/2022_10_24_000001_create_virtual_models_table.php new file mode 100644 index 0000000..8cbcb81 --- /dev/null +++ b/tests/etc/migrations/2022_10_24_000001_create_virtual_models_table.php @@ -0,0 +1,29 @@ +increments('id'); + + $table->json('data'); + }); + } + + public function down() + { + Schema::dropIfExists('foo_models'); + } +}