Skip to content

Commit d30d885

Browse files
committed
class-based api
1 parent f546313 commit d30d885

File tree

4 files changed

+104
-10
lines changed

4 files changed

+104
-10
lines changed

README.md

+22-1
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,30 @@ class Policy
101101
}
102102
}
103103

104-
$policy = $mapper->createSpace('policy');
104+
$policy = $mapper->createSpace('policy', ['if_not_exists' => true]);
105105
$policy->setClass(Policy::class, 'initialize'); // use custom initialize method
106106
$policy->migrate();
107+
108+
/**
109+
* mapper access using class name
110+
*/
111+
class Login
112+
{
113+
public function __construct(
114+
public int $id,
115+
public string $username,
116+
public string $password,
117+
) {
118+
}
119+
120+
public static function initSchema(\Tarantool\Mapper\Space $space)
121+
{
122+
$space->addIndex(['username'], ['unique' => true]);
123+
}
124+
}
125+
126+
$nekufa = $mapper->findOrCreate(Login::class, ['username' = 'nekufa']);
127+
$mapper->update(Login::class, $nekufa, ['password' => password_hash("secret")]);
107128
```
108129

109130
## Working with the data

src/Mapper.php

+49-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Tarantool\Mapper;
66

77
use Psr\Cache\CacheItemPoolInterface;
8+
use ReflectionClass;
89
use Tarantool\Client\Client;
910
use Tarantool\Client\Exception\RequestFailed;
1011
use Tarantool\Client\Schema\Criteria;
@@ -14,6 +15,7 @@ class Mapper
1415
{
1516
use Api;
1617

18+
private array $classNames = [];
1719
private array $spaceId = [];
1820
private array $spaces = [];
1921
private int $schemaId = 0;
@@ -40,6 +42,7 @@ public function call(string $query, array $params = [])
4042

4143
public function createSpace(string $space, array $options = []): Space
4244
{
45+
$space = $this->getClassSpace($space);
4346
$this->client->evaluate('box.schema.space.create(...)', $space, $options);
4447
return $this->getSpace($space);
4548
}
@@ -128,13 +131,33 @@ public function getChanges(): array
128131
return $this->middleware->getChanges();
129132
}
130133

134+
public function getClassSpace(int|string $class): int|string
135+
{
136+
if (!is_integer($class) && class_exists($class)) {
137+
if (!array_key_exists($class, $this->classNames)) {
138+
$this->registerClass($class);
139+
}
140+
return $this->classNames[$class];
141+
}
142+
143+
return $class;
144+
}
145+
131146
public function getSpace(int|string $id): Space
132147
{
133148
if (!count($this->spaces)) {
134149
$this->setSchemaId(0);
135150
}
136151

137-
return is_string($id) ? $this->getSpace($this->spaceId[$id]) : $this->spaces[$id];
152+
$space = $this->getClassSpace($id);
153+
if ($space !== $id) {
154+
if (!$this->hasSpace($space)) {
155+
$spaceInstance = $this->createSpace($space);
156+
$spaceInstance->setClass($id);
157+
$spaceInstance->migrate();
158+
}
159+
}
160+
return is_string($space) ? $this->getSpace($this->spaceId[$space]) : $this->spaces[$space];
138161
}
139162

140163
public function getSpaces(): array
@@ -144,7 +167,7 @@ public function getSpaces(): array
144167

145168
public function hasSpace(string $space): bool
146169
{
147-
return array_key_exists($space, $this->spaceId);
170+
return array_key_exists($this->getClassSpace($space), $this->spaceId);
148171
}
149172

150173
public function migrate(array $migrations = []): void
@@ -163,6 +186,26 @@ public function migrate(array $migrations = []): void
163186
array_map(fn(Migration $migration) => $migration->afterSchema($this), $instances);
164187
}
165188

189+
public function registerClass(string $class)
190+
{
191+
if (!array_key_exists($class, $this->classNames)) {
192+
if (method_exists($class, 'getSpaceName')) {
193+
$space = call_user_func([$class, 'getSpaceName']);
194+
} else {
195+
$space = preg_replace(
196+
['/(?<=[^A-Z])([A-Z])/', '/(?<=[^0-9])([0-9])/'],
197+
'_$0',
198+
(new ReflectionClass($class))->getShortName(),
199+
);
200+
$space = strtolower($space);
201+
}
202+
if (array_key_exists($space, $this->spaceId)) {
203+
$this->spaces[$this->spaceId[$space]]->setClass($class);
204+
}
205+
$this->classNames[$class] = strtolower($space);
206+
}
207+
}
208+
166209
public function setSchemaId(int $schemaId)
167210
{
168211
if (!$this->schemaId || $this->schemaId !== $schemaId) {
@@ -186,6 +229,10 @@ public function setSchemaId(int $schemaId)
186229
$this->spaces[$row['id']]->setFormat($row['format']);
187230
}
188231
$this->spaceId[$row['name']] = $row['id'];
232+
233+
if (array_search($row['name'], $this->classNames)) {
234+
$this->spaces[$row['id']]->setClass(array_search($row['name'], $this->classNames));
235+
}
189236
}
190237

191238
foreach (array_keys($this->spaces) as $id) {

tests/MapperTest.php

+28-7
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,19 @@ public function createMapper(
3535
return $mapper;
3636
}
3737

38+
public function testClassBased()
39+
{
40+
$mapper = $this->createMapper();
41+
42+
$row = $mapper->findOrCreate(TypedConstructor::class, []);
43+
$this->assertEquals($row, $mapper->findOne('constructor'));
44+
45+
$mapper = $this->createMapper(dropUserSpaces: false);
46+
$mapper->registerClass(TypedConstructor::class);
47+
$this->assertInstanceOf(TypedConstructor::class, $mapper->findOne('constructor'));
48+
$this->assertEquals($row, $mapper->findOne('constructor'));
49+
}
50+
3851
public function testUpdateStringPrimaryKey()
3952
{
4053
$mapper = $this->createMapper();
@@ -323,19 +336,27 @@ public function testSpaces()
323336

324337

325338
$userTypes = [
326-
'constructor' => TypedConstructor::class,
327-
'properties' => TypedProperties::class,
339+
'constructor' => TypedConstructor::class, // static space name
340+
'typed_properties' => TypedProperties::class, // class basd space name
328341
];
329342

330343
foreach ($userTypes as $name => $type) {
344+
foreach ([$name, $type] as $target) {
345+
$space = $mapper->createSpace($target);
346+
$space->setClass($type);
347+
$space->migrate();
348+
$space->migrate();
349+
$this->assertSame($space->getName(), $name);
350+
351+
$this->assertSame($space, $mapper->createSpace($target, ['if_not_exists' => true]));
352+
$this->assertSame($space, $mapper->getSpace($space->getId()));
353+
$this->assertCount(2, $mapper->find('_vindex', ['id' => $space->getId()]));
354+
$space->drop();
355+
}
356+
331357
$space = $mapper->createSpace($name);
332358
$space->setClass($type);
333359
$space->migrate();
334-
$space->migrate();
335-
336-
$this->assertSame($space, $mapper->createSpace($name, ['if_not_exists' => true]));
337-
$this->assertSame($space, $mapper->getSpace($space->getId()));
338-
$this->assertCount(2, $mapper->find('_vindex', ['id' => $space->getId()]));
339360
}
340361

341362
$space = $mapper->createSpace('array');

tests/TypedConstructor.php

+5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ public function __construct(
1515
) {
1616
}
1717

18+
public static function getSpaceName(): string
19+
{
20+
return 'constructor';
21+
}
22+
1823
public static function initSchema(Space $space)
1924
{
2025
$space->addIndex(['name'], ['unique' => false]);

0 commit comments

Comments
 (0)