Skip to content

Commit 6ee606c

Browse files
nikophilclaude
andcommitted
feat: support UUID-based entity ids in ObjectRegistry
Add AbstractUid support via toRfc4122() conversion for entities using UUID/ULID identifiers. Add unit test and Behat functional scenario. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent c61be69 commit 6ee606c

File tree

4 files changed

+83
-2
lines changed

4 files changed

+83
-2
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
Feature: Test accessing Uuid-based entity ids
2+
3+
Scenario: Can create and reference Uuid entity
4+
Given there is an "entity with uid" named "the object"
5+
Then "entity with uid" "the object" should exist
6+
7+
Scenario: Can access last id for Uuid entity via lastId transform
8+
Given there is an "entity with uid" named "A"
9+
# The <lastId> transform resolves the Uuid to its RFC 4122 string format.
10+
# We just need to verify the transform doesn't throw, the 404 is expected.
11+
When I am on "/<lastId>"
12+
Then the response status code should be 404
13+
14+
Scenario: Can access last id for specific Uuid entity type
15+
Given there is an "entity with uid" named "B"
16+
When I am on "/<lastId(entity with uid)>"
17+
Then the response status code should be 404
18+
19+
Scenario: Can access id from reference for Uuid entity
20+
Given there is an "entity with uid" named "my-uid-entity"
21+
When I am on "/<id(entity with uid, my-uid-entity)>"
22+
Then the response status code should be 404

src/Test/Behat/src/ObjectRegistry.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Zenstruck\Foundry\Test\Behat;
1313

14+
use Symfony\Component\Uid\AbstractUid;
1415
use Zenstruck\Foundry\Persistence\Event\AfterPersist;
1516
use Zenstruck\Foundry\Persistence\PersistenceManager;
1617
use Zenstruck\Foundry\Story\Event\StateAddedToStory;
@@ -162,8 +163,13 @@ private function coerceIdToScalar(array $ids): int|string
162163
}
163164

164165
$id = array_first($ids);
166+
167+
if ($id instanceof AbstractUid) {
168+
return $id->toRfc4122();
169+
}
170+
165171
if (!\is_int($id) && !\is_string($id)) {
166-
throw new \InvalidArgumentException(\sprintf('Wrong type for the id: expected int or string, got "%s".', \get_debug_type($id)));
172+
throw new \InvalidArgumentException(\sprintf('Wrong type for the id: expected int, string or Uid, got "%s".', \get_debug_type($id)));
167173
}
168174

169175
return $id;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the zenstruck/foundry package.
5+
*
6+
* (c) Kevin Bond <kevinbond@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Zenstruck\Foundry\Test\Behat\Tests\Fixture\Factories;
13+
14+
use Zenstruck\Foundry\Persistence\PersistentObjectFactory;
15+
use Zenstruck\Foundry\Test\Behat\Attribute\FactoryShortName;
16+
use Zenstruck\Foundry\Tests\Fixture\Entity\EntityWithUid;
17+
18+
/**
19+
* @extends PersistentObjectFactory<EntityWithUid>
20+
*/
21+
#[FactoryShortName(shortName: 'entity with uid', pluralName: 'entities with uid')]
22+
final class EntityWithUidFactory extends PersistentObjectFactory
23+
{
24+
public static function class(): string
25+
{
26+
return EntityWithUid::class;
27+
}
28+
29+
protected function defaults(): array
30+
{
31+
return [];
32+
}
33+
}

src/Test/Behat/tests/Unit/ObjectRegistryTest.php

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use PHPUnit\Framework\Attributes\Test;
1515
use PHPUnit\Framework\TestCase;
16+
use Symfony\Component\Uid\Uuid;
1617
use Zenstruck\Foundry\ObjectFactory;
1718
use Zenstruck\Foundry\Persistence\Event\AfterPersist;
1819
use Zenstruck\Foundry\Persistence\PersistenceManager;
@@ -145,6 +146,25 @@ public function it_stores_string_id_from_after_persist_event(): void
145146
self::assertSame('uuid-123', $this->registry->lastId());
146147
}
147148

149+
#[Test]
150+
public function it_stores_uuid_from_after_persist_event(): void
151+
{
152+
$uuid = Uuid::v7();
153+
154+
$persistenceManager = $this->createStub(PersistenceManager::class);
155+
$persistenceManager->method('getIdentifierValues')->willReturn(['id' => $uuid]);
156+
157+
$registry = new ObjectRegistry($this->resolver, $persistenceManager);
158+
$registry->reset();
159+
160+
$user = new User(id: 1, name: 'John');
161+
$event = new AfterPersist($user, [], $this->createStub(PersistentObjectFactory::class));
162+
163+
$registry->storeLastId($event);
164+
165+
self::assertSame($uuid->toRfc4122(), $registry->lastId());
166+
}
167+
148168
#[Test]
149169
public function it_throws_when_no_last_id_available(): void
150170
{
@@ -252,7 +272,7 @@ public function it_throws_when_id_type_is_invalid(): void
252272
$registry->storeLastId($event);
253273

254274
$this->expectException(\InvalidArgumentException::class);
255-
$this->expectExceptionMessage('Wrong type for the id: expected int or string, got "array".');
275+
$this->expectExceptionMessage('Wrong type for the id: expected int, string or Uid, got "array".');
256276

257277
$registry->lastId();
258278
}

0 commit comments

Comments
 (0)