tarantool / mapper
Tarantool 的 PHP 对象映射器。
Requires
- php: >=8.0
- psr/cache: ^2.0
- tarantool/client: >=0.10.0
Requires (Dev)
- monolog/monolog: ^2.9.3
- phpunit/phpunit: ^9.5
- symfony/cache: ^5.4.38
- dev-master
- 6.2.2
- 6.2.1
- 6.2.0
- 6.1.9
- 6.1.8
- 6.1.7
- 6.1.6
- 6.1.5
- 6.1.4
- 6.1.3
- 6.1.2
- 6.1.1
- 6.1.0
- 6.0.7
- 6.0.6
- 6.0.5
- 6.0.4
- 6.0.3
- 6.0.2
- 6.0.1
- 6.0.0
- 5.0.14
- 5.0.13
- 5.0.12
- 5.0.11
- 5.0.10
- 5.0.9
- 5.0.8
- 5.0.7
- 5.0.6
- 5.0.5
- 5.0.4
- 5.0.3
- 5.0.2
- 5.0.1
- 5.0.0
- 4.6.19
- 4.6.18
- 4.6.17
- 4.6.16
- 4.6.15
- 4.6.14
- 4.6.13
- 4.6.12
- 4.6.11
- 4.6.10
- 4.6.9
- 4.6.8
- 4.6.7
- 4.6.6
- 4.6.5
- 4.6.4
- 4.6.3
- 4.6.2
- 4.6.1
- 4.6.0
- 4.5.21
- 4.5.20
- 4.5.19
- 4.5.18
- 4.5.17
- 4.5.16
- 4.5.15
- 4.5.14
- 4.5.13
- 4.5.12
- 4.5.11
- 4.5.10
- 4.5.9
- 4.5.8
- 4.5.7
- 4.5.6
- 4.5.5
- 4.5.4
- 4.5.3
- 4.5.2
- 4.5.1
- 4.5.0
- 4.4.5
- 4.4.4
- 4.4.3
- 4.4.2
- 4.4.1
- 4.4.0
- 4.3.22
- 4.3.21
- 4.3.20
- 4.3.19
- 4.3.18
- 4.3.17
- 4.3.16
- 4.3.15
- 4.3.14
- 4.3.13
- 4.3.12
- 4.3.11
- 4.3.10
- 4.3.9
- 4.3.8
- 4.3.7
- 4.3.6
- 4.3.5
- 4.3.4
- 4.3.3
- 4.3.2
- 4.3.1
- 4.3.0
- 4.2.23
- 4.2.22
- 4.2.21
- 4.2.10
- 4.2.9
- 4.2.8
- 4.2.7
- 4.2.6
- 4.2.5
- 4.2.4
- 4.2.3
- 4.2.2
- 4.2.1
- 4.2.0
- 4.1.2
- 4.1.1
- 4.1.0
- 4.0.7
- 4.0.6
- 4.0.5
- 4.0.4
- 4.0.3
- 4.0.2
- 4.0.1
- 4.0.0
- 3.6.12
- 3.6.11
- 3.6.10
- 3.6.9
- 3.6.8
- 3.6.7
- 3.6.6
- 3.6.5
- 3.6.4
- 3.6.3
- 3.6.2
- 3.6.1
- 3.6.0
- 3.5.9
- 3.5.8
- 3.5.7
- 3.5.6
- 3.5.5
- 3.5.4
- 3.5.3
- 3.5.2
- 3.5.1
- 3.5.0
- 3.4.9
- 3.4.8
- 3.4.7
- 3.4.6
- 3.4.5
- 3.4.4
- 3.4.3
- 3.4.2
- 3.4.1
- 3.4.0
- 3.3.12
- 3.3.11
- 3.3.10
- 3.3.9
- 3.3.8
- 3.3.7
- 3.3.6
- 3.3.5
- 3.3.4
- 3.3.3
- 3.3.2
- 3.3.1
- 3.3.0
- 3.2.6
- 3.2.5
- 3.2.4
- 3.2.3
- 3.2.2
- 3.2.1
- 3.2.0
- 3.1.2
- 3.1.1
- 3.1.0
- 3.0.2
- 3.0.1
- 3.0.0
- 2.7.8
- 2.7.7
- 2.7.6
- 2.7.5
- 2.7.4
- 2.7.3
- 2.7.2
- 2.7.1
- 2.7.0
- 2.6.1
- 2.6.0
- 2.5.0
- 2.4.0
- 2.3.3
- 2.3.2
- 2.3.1
- 2.3.0
- 2.2.6
- 2.2.5
- 2.2.4
- 2.2.3
- 2.2.2
- 2.2.1
- 2.2.0
- 2.1.7
- 2.1.6
- 2.1.5
- 2.1.4
- 2.1.3
- 2.1.2
- 2.1.1
- 2.1.0
- 2.0.3
- 2.0.2
- 2.0.1-beta
- 2.0.0-alpha
- v1.0.9
- v1.0.8
- v1.0.7
- v1.0.6
- v1.0.5
- v1.0.4
- v1.0.3
- v1.0.2
- v1.0.1
- v1.0.0
- dev-v.1
This package is auto-updated.
Last update: 2024-09-10 15:51:59 UTC
README
入门
支持的版本是 php 8+ 和 tarantool 2+。
安装库的推荐方式是通过 Composer
composer require tarantool/mapper
通常,您在服务提供者中管理依赖项。
要开始使用,您应该创建客户端实例并将其传递给映射器构造函数。
在此示例中,我们使用 PurePacker 和 StreamConnection。
要查看其他实现,请查看 客户端文档
use Tarantool\Client\Client; use Tarantool\Mapper\Mapper; $client = Client::fromDefaults(); $mapper = new Mapper($client); // internaly mapper wraps client with special middleware assert($mapper->client !== $client);
模式管理
要开始,您应该描述您的空间、它们的格式和索引。
$person = $mapper->createSpace('person', [ 'engine' => 'memtx', 'if_not_exists' => true, ]); // add properties - name, type and options $person->addProperty('id', 'unsigned'); $person->addProperty('name', 'string'); $person->addProperty('birthday', 'unsigned'); $person->addProperty('gender', 'string', [ 'default' => 'male' ]); // indexes are created using fields array and optional index configuration $person->addIndex(['name']); $person->addIndex(['birthday'], ['unique' => true]); // index name is fields based, but you can specify any preffered one $person->addIndex(['name', 'birthday'], [ 'type' => 'hash', 'name' => 'name_with_birthday', ]); /** * define format using properties */ class Tracker { public int $id; public int $reference; public string $status; public static function initSchema(\Tarantool\Mapper\Space $space) { $space->addIndex(['reference']); } } $tracker = $mapper->createSpace('tracker'); $tracker->setClass(Tracker::class); $tracker->migrate(); /** * define format using constructor promotion */ class Policy { public function __construct( public int $id, public string $nick, public string $status, ) { } public static function initialize(\Tarantool\Mapper\Space $space) { $space->addIndex(['nick'], ['unique' => true]); } } $policy = $mapper->createSpace('policy'); $policy->setClass(Policy::class, 'initialize'); // use custom initialize method $policy->migrate();
与数据交互
现在您可以使用映射器实例从 tarantool 存储中存储和检索数据。
// get space instance $persons = $mapper->getSpace('person'); // create new entity $dmitry = $persons->create([ 'id' => 1, 'name' => 'Dmitry' ]); // create entities using mapper wrapper. // this way entity will be created and saved in the tarantool $vasily = $mapper->create('person', [ 'id' => 2, 'name' => 'Vasily' ]); // retreive entites by id using space $helloWorld = $mapper->getSpace('post')->findOne(['id' => 3]); // or using mapper wrapper $helloWorld = $mapper->findOne('post', ['id' => 3]); // pass client criteria object as well $criteria = Criteria::index('age')->andKey([18])->andGeIterator(); $adults = $mapper->find('user', $criteria); // updates are easy $posts = $mapper->getSpace('post'); $helloWorld = $posts->update($helloWorld, [ 'title' => 'Hello world' ]); // if you use instance classes, instance would be updated $policy = $mapper->findOrFail('policy', ['id' => 3]); $policy = $mapper->get('policy', 3); // getter shortcut $mapper->update('policy', $policy, [ 'title' => 'updated title', ]); echo $policy->title; // updated title // use client operations as well use Tarantool\Client\Schema\Operations; $mapper->getSpace('policy')->update($policy, Operations::add('counter', 1)); var_dump($policy->counter); // actual value
模式缓存
任何新的映射器实例都会从 tarantool 获取模式,这可能会对数据库产生一些负载。
使用您喜欢的 psr/cache
实现来在应用程序端持久化模式。
例如,我们使用来自 symfony/cache
包的 apcu 适配器。
如果新的模式版本未在缓存中持久化,映射器将获取它
use Symfony\Component\Cache\Adapter\ApcuAdapter; $cache = new ApcuAdapter(); $mapper = new Mapper(Client::fromDefaults()); $mapper->cache = $cache; $mapper->getSpace('_vspace'); // schema is fetched now $mapper = new Mapper(Client::fromDefaults()); $mapper->cache = $cache; $mapper->getSpace('_vspace'); // no new requests are made
查询缓存
如果您不想重复选择查询,可以向空间注入缓存接口实现。
使用您喜欢的 psr/cache 实现来在应用程序端持久化模式。
例如,我们使用来自 symfony/cache
包的数组适配器。
use Symfony\Component\Cache\Adapter\ArrayAdapter; $mapper = new Mapper(Client::fromDefaults()); $mapper->getSpace('_vspace')->cache = new ArrayAdapter(); // feel free to set default ttl $mapper->find('_vspace'); // query is executed $mapper->find('_vspace'); // results are fetched from cache $mapper->find('_vspace'); // results are fetched from cache
变更注册
在某些情况下,您可能想要获取当前会话期间所做的所有更改。
默认情况下,spy 配置设置为 false,这会略微提高性能。
$mapper->spy = true; $nekufa = $mapper->create('user', ['login' => 'nekufa']); $firstPost = $mapper->create('post', [ 'user_id' => $nekufa->id, 'title' => 'hello world', ]); $mapper->update('post', $firstPost, ['title' => 'Final title']); // now there are two changes [$first, $second] = $mapper->getChanges(); echo $first->type; // insert echo $first->space; // user echo $first->data; // ['login' => 'nekufa'] // all changes would be merged by space and key // this reduces changes duplicates echo $second->type; // insert echo $second->space; // post echo $second->data; // ['user_id' => 1, 'title' => 'Final title'] // of course you can flush all changes and start registration from scratch $mapper->flushChanges();
多连接
如果您将数据分散在多个 tarantool 实例中,可以使用基于前缀的数据 API。
API 与之前相同,但您需要在连接前缀前加上空间名称。
$pool = new Pool(function (string $prefix) { return new Mapper(Client::fromDsn('tcp://' . $prefix)); }); // connect to tarantool instance `volume` and find all timelines. $trackers = $pool->findOne('volume.timeline'); $nekufa = $pool->findOrCreate('guard.login', ['username' => 'nekufa']); $pool->update('guard.login', $nekufa, ['locked_at' => time()]); // pool also wraps changes with the prefixes echo $pool->getChanges()[0]->space; // guard.login // all expressions do the same behind the scenes $pool->find('flow.tracker', ['status' => 'active']); $pool->getMapper('flow')->find('tracker', ['status' => 'active']); $pool->getMapper('flow')->getSpace('tracker')->find(['status' => 'active']);
Lua 代码交付
iProto 的使用非常强大,但有时可能不够。
您可以使用关联数组轻松执行 Lua 代码并传递局部变量。
此外,如果您不想在每次请求中都传递它,可以使用神奇的 call
方法。
当您使用 call 方法时,映射器会生成唯一的函数名称,并在不存在时创建它。
// this method will always deliver and parse lua code on the tarantool side $mapper->evaluate('return a + b', ['a' => 2, 'b' => 7]); // 9 // first call a function would be created with name evaluate_{BODYHASH} // there would be two requests - create function and call it $mapper->call('return a + b', ['a' => 2, 'b' => 7]); // 9 // second call will produce single request with function name and arguments $mapper->call('return a + b', ['a' => 2, 'b' => 7]); // 9
迁移
使用基本迁移类在创建模式前后实现一些逻辑。
将迁移传递给映射器迁移方法,这样就完成了。
use Tarantool\Mapper\Migration;
use Tarantool\Mapper\Space;
class DropLegacySpaces extends Migration
{
public function beforeSchema(Mapper $mapper)
{
$mapper->call(<<<LUA
if box.space.legacy then
box.space.legacy:drop()
box.space.legacy_detail:drop()
end
LUA);
}
}
class InitializeData extends Migration
{
public function afterSchema(Mapper $mapper)
}
$mapper = $container->get(Mapper::class);
// also migrate accepts migration instance, or migration class arrays
$mapper->migrate(DropLegacySpaces::class, InitializeData::class);
性能
我们可以使用每个实例调用的 getInstance 方法来计算映射器开销。
如果您不使用缓存,则每次连接和模式升级时都会进行单个模式检索。
性能测试在 (AMD Ryzen 5 3600X),Ubuntu 23.10 上使用 PHP 8.3.6 进行。