1
0
Fork 0
mirror of https://github.com/archtechx/virtualcolumn.git synced 2025-12-12 06:44:05 +00:00
This commit is contained in:
Nick 2025-12-06 23:21:40 -08:00 committed by GitHub
commit 316a8241cc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 44 additions and 2 deletions

1
.gitignore vendored
View file

@ -2,3 +2,4 @@
composer.lock
.phpunit.result.cache
.php-cs-fixer.cache
.idea/

View file

@ -31,9 +31,11 @@ trait VirtualColumn
*/
public bool $dataEncoded = false;
public bool $dataNotLoaded = false;
protected function decodeVirtualColumn(): void
{
if (! $this->dataEncoded) {
if (! $this->dataEncoded || ! $this->dataNotLoaded) {
return;
}
@ -65,6 +67,10 @@ trait VirtualColumn
return;
}
if ($this->dataNotLoaded) {
throw new \Exception('Data column was not loaded from the database. Make sure the data column is selected in the query.');
}
$dataColumn = static::getDataColumn();
$customColumns = static::getCustomColumns();
$attributes = array_filter($this->getAttributes(), fn ($key) => ! in_array($key, $customColumns), ARRAY_FILTER_USE_KEY);
@ -107,7 +113,14 @@ trait VirtualColumn
return [
'retrieved' => [
function () {
// Always decode after model retrieval
// If the data column wasn't retrieved, don't decode it
if (($this->attributes[static::getDataColumn()] ?? null) === null) {
$this->dataNotLoaded = true;
return;
}
// Mark the data as encoded so that it doesn't get encoded again
$this->dataEncoded = true;
$this->decodeVirtualColumn();

View file

@ -129,6 +129,34 @@ class VirtualColumnTest extends TestCase
$this->assertSame($encodedBar->bar, 'bar');
}
/** @test */
public function model_doesnt_overwrite_when_selectively_fetching() {
$this->expectExceptionMessage('Data column was not loaded from the database. Make sure the data column is selected in the query.');
FooModel::create([
'id' => 1,
'foo' => 'bar'
]);
$foo = FooModel::query()->first(['id']);
$foo->bar = 'baz';
$foo->save();
}
/** @test */
public function decoding_works_with_strict_mode_enabled() {
FooModel::shouldBeStrict();
FooModel::create([
'id' => 1,
'foo' => 'bar'
]);
$id = FooModel::query()->pluck('id')->first();
$this->assertSame(1, $id);
}
// maybe add an explicit test that the saving() and updating() listeners don't run twice?
#[Test]