talleu/php-redis-om
Composer 安装命令:
composer require talleu/php-redis-om
包简介
A PHP object mapper library for Redis
README 文档
README
php-redis-om 🗄️
A PHP object mapper for Redis.
An Object Mapper for Redis®, designed to providing an intuitive and familiar interface for PHP developers to interact with Redis.
Features 🛠️
- Doctrine-like methods and architecture
- Symfony bundle integration
- Easy integration with existing PHP applications
- High performance and scalability with Redis®
- Support for Redis JSON module
- Automatic schema generation
- Search and query capabilities with range filters
- Auto-expiration of your objects
- PHP enum support (backed enums)
- Identity map and dirty tracking with partial updates
- Atomic transactions (MULTI/EXEC)
- Unique constraints (single-field and composite)
- Pagination with total count
- Memory-efficient streaming of large collections
- Bulk delete and update without loading objects into memory
- GEO queries (radius search)
- Pipeline batch reads
- API Platform support (beta)
Requirements ⚙️
- PHP 8.2 or higher
- Redis 4.0 or higher
- Redisearch module (available by default with Redis >8 or in redis-stack distribution) (installation)
- php-redis extension OR Predis library
- Redis JSON module (optional, include in redis-stack)
- Composer
Supported types ✅
- scalar (string, int, float, bool, double)
- PHP backed enums (string and int)
- timestamp
- json
- null
- DateTimeImmutable
- DateTime
- array and nested arrays
- object and nested objects
- stdClass
Installation 📝
Install the library via Composer:
composer require talleu/php-redis-om
Depending on your configuration, use phpredis or Predis
Symfony bundle 🎵
In a Symfony application, you may need to add this line to config/bundles.php
Talleu\RedisOm\Bundle\TalleuRedisOmBundle::class => ['all' => true],
And that's it, your installation is complete ! 🚀
API Platform support 🕷️
For API Platform users, a basic implementation is provided here: API Platfom X Redis
Basic Usage 🎯
Add the RedisOm attribute to your class to map it to a Redis schema:
<?php use Talleu\RedisOm\Om\Mapping as RedisOm; #[RedisOm\Entity] class User { #[RedisOm\Id] #[RedisOm\Property] public int $id; #[RedisOm\Property(index:true)] public string $name; #[RedisOm\Property] public \DateTimeImmutable $createdAt; }
After add the RedisOm attribute to your class,
you have to run the following command to create the Redis schema for your classes (default path is ./src):
For Symfony users:
bin/console redis-om:migrate
For others PHP applications:
vendor/bin/redisMigration <YOUR DIRECTORY PATH>
Then you can use the ObjectManager to persist your objects from Redis ! 💪
For Symfony users, just inject the RedisObjectManagerInterface in the constructor:
<?php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Talleu\RedisOm\Om\RedisObjectManagerInterface; use App\Entity\Book; class MySymfonyController extends AbstractController { public function __construct(private RedisObjectManagerInterface $redisObjectManager) {} #[Route('/', name: 'app_home')] public function index(): Response { $book = new Book(); $book->name = 'Martin Eden'; $this->redisObjectManager->persist($book); $this->redisObjectManager->flush(); //.. } }
For others PHP applications:
<?php use Talleu\RedisOm\Om\RedisObjectManager; $user = new User() $user->id = 1; $user->name = 'John Doe'; // Persist the object in redis $objectManager = new RedisObjectManager(); $objectManager->persist($user); $objectManager->flush();
🥳 Congratulations, your PHP object is now registered in Redis !
You can now retrieve your user wherever you like using the repository provided by the Object Manager (or the object manager directly):
// Retrieve the object from redis $user = $this->redisObjectManager->find(User::class, 1); $user = $this->redisObjectManager->getRepository(User::class)->find(1); $user = $this->redisObjectManager->getRepository(User::class)->findOneBy(['name' => 'John Doe']); // Retrieve a collection of objects $users = $this->redisObjectManager->getRepository(User::class)->findAll(); $users = $this->redisObjectManager->getRepository(User::class)->findBy(['name' => 'John Doe'], ['createdAt' => 'DESC'], 10);
Enum Support 🏷️
PHP backed enums are natively supported:
enum Status: string { case ACTIVE = 'active'; case INACTIVE = 'inactive'; } #[RedisOm\Entity] class Task { #[RedisOm\Id] #[RedisOm\Property] public int $id; #[RedisOm\Property(index: true)] public Status $status; }
Search by enum value:
$activeTasks = $repository->findBy(['status' => 'active']);
Range Queries 🔢
Use MongoDB-style operators for numeric range searches:
// Age between 18 and 65 $users = $repository->findBy(['age' => ['$gte' => 18, '$lte' => 65]]); // Price greater than 100 $products = $repository->findBy(['price' => ['$gt' => 100]]); // Score less than 50 $results = $repository->findBy(['score' => ['$lt' => 50]]); // Combine with exact match $results = $repository->findBy(['name' => 'John', 'age' => ['$gte' => 18]]);
Supported operators: $gte (>=), $gt (>), $lte (<=), $lt (<).
Note: Range queries work automatically with HASH format (NUMERIC index is auto-generated for int/float). For JSON format, you must explicitly declare a NUMERIC index:
#[Property(index: ['age' => 'NUMERIC'])].
Pagination 📄
$paginator = $repository->paginate( criteria: ['status' => 'active'], page: 2, itemsPerPage: 20, orderBy: ['createdAt' => 'DESC'] ); $paginator->getItems(); // Current page items $paginator->getTotalItems(); // Total matching count $paginator->getTotalPages(); // Total number of pages $paginator->getCurrentPage(); // Current page number $paginator->hasNextPage(); // bool $paginator->hasPreviousPage(); // bool // Iterable foreach ($paginator as $item) { // ... }
Partial Updates (Merge) ⚡
Instead of re-persisting the entire object, use merge() to only update changed fields:
$user = $objectManager->find(User::class, 1); $user->name = 'New Name'; // Only this field changed $objectManager->merge($user); // Detects change, updates only 'name' $objectManager->flush();
For new objects (not loaded via find()), merge() falls back to a full persist().
Batch Reads (Pipeline) 🚀
Load multiple objects by ID in a single Redis pipeline call:
$users = $repository->findMultiple([1, 2, 3, 4, 5]);
GEO Queries 🌍
Search objects within a geographic radius (requires a GEO-indexed property):
#[RedisOm\Property(index: ['location' => 'GEO'])] public string $location; // Format: "longitude,latitude" $nearby = $repository->findByGeoRadius('location', 2.3522, 48.8566, 10, 'km');
Unique Constraints 🔒
Enforce uniqueness on one or more fields using #[Unique].
Single field:
#[RedisOm\Entity] class User { #[RedisOm\Id] #[RedisOm\Property] public int $id; #[RedisOm\Property(index: true)] #[RedisOm\Unique] public string $email; }
Composite (combination of fields must be unique):
#[RedisOm\Entity] #[RedisOm\Unique(properties: ['username', 'tenantId'])] class User { #[RedisOm\Id] #[RedisOm\Property] public int $id; #[RedisOm\Property] public string $username; #[RedisOm\Property] public int $tenantId; }
flush() throws UniqueConstraintViolationException on conflict. Violations within the same flush() call are detected before hitting Redis. Concurrent writes are protected via Redis WATCH/MULTI/EXEC.
use Talleu\RedisOm\Exception\UniqueConstraintViolationException; try { $objectManager->persist($user); $objectManager->flush(); } catch (UniqueConstraintViolationException $e) { // $e->getMessage() describes the conflicting field(s) and value(s) }
Bulk Operations ⚡
Delete or update large numbers of objects without loading them into PHP memory.
$repository = $objectManager->getRepository(User::class); // Delete all inactive users — unique-constraint keys are cleaned up automatically $deleted = $repository->bulkDelete(['status' => 'inactive']); // Update a scalar field on many objects at once $updated = $repository->bulkUpdate(['country' => 'FR'], ['currency' => 'EUR']);
bulkUpdate() throws BulkOperationException when $changes targets a #[Unique] field. Use stream() + merge() + flush() instead for those cases.
Streaming Large Collections 🌊
findAll() loads everything into memory. stream() fetches objects in batches and yields them one by one, keeping memory bounded regardless of collection size.
// Via repository — full control foreach ($repository->stream(['status' => 'active'], batchSize: 500) as $user) { // process $user — break works normally } // Via object manager — identity map is cleared automatically between batches foreach ($objectManager->stream(User::class, ['status' => 'active']) as $user) { // process $user }
Advanced documentation 📚
talleu/php-redis-om 适用场景与选型建议
talleu/php-redis-om 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 15.22k 次下载、GitHub Stars 达 200, 最近一次更新时间为 2024 年 06 月 05 日, 在 PHP 生态内属于活跃度较高的组件。
我们在过去多个企业项目中使用过 talleu/php-redis-om 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 talleu/php-redis-om 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
统计信息
- 总下载量: 15.22k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 201
- 点击次数: 15
- 依赖项目数: 1
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2024-06-05