athenea/mongo-lib 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

athenea/mongo-lib

Composer 安装命令:

composer require athenea/mongo-lib

包简介

Mongo utilities for Athenea Solutions

README 文档

README

PHP library for BSON serialization/deserialization with MongoDB. Provides a Base model class that implements MongoDB\BSON\Serializable and MongoDB\BSON\Unserializable, automatically converting typed PHP objects to and from BSON documents.

Installation

composer require athenea/mongo-lib

Requirements

Dependency Version Purpose
PHP ≥ 8.1 Runtime
mongodb/mongodb ^1.0 || ^2.0 MongoDB driver
phpdocumentor/reflection-docblock ^5.3 @var docblock parsing for collection types
symfony/property-info ^5.0 || ^6.0 || ^7.0 || ^8.0 Property type introspection
symfony/property-access ^5.0 || ^6.0 || ^7.0 || ^8.0 Private property read/write

Note: symfony/serializer is not a direct dependency. Discriminator maps use our own #[BsonDiscriminator] attribute (Symfony's #[DiscriminatorMap] is also supported as a fallback).

Quick Start

Define a model

use Athenea\MongoLib\Attribute\BsonSerialize;
use Athenea\MongoLib\Model\Base;
use MongoDB\BSON\ObjectId;
use DateTime;

class Person extends Base
{
    #[BsonSerialize(name: '_id')]
    private ?ObjectId $id = null;

    #[BsonSerialize]
    private ?string $name = null;

    #[BsonSerialize]
    private ?DateTime $createdAt = null;

    // Getters and setters required for private properties
    public function getName(): ?string { return $this->name; }
    public function setName(?string $name): void { $this->name = $name; }
    public function getCreatedAt(): ?DateTime { return $this->createdAt; }
    public function setCreatedAt(?DateTime $createdAt): void { $this->createdAt = $createdAt; }
    public function getId(): ?ObjectId { return $this->id; }
    public function setId(?ObjectId $id): void { $this->id = $id; }
}

Serialize to BSON

$person = new Person();
$person->setName('Alice');
$person->setCreatedAt(new DateTime());

$bson = $person->bsonSerialize();
// { "_id": null, "name": "Alice", "created_at": UTCDateTime(...) }

Deserialize from BSON

$person = new Person();
$person->bsonUnserialize([
    '_id' => new ObjectId(),
    'name' => 'Bob',
    'created_at' => new UTCDateTime(),
]);

Compute diffs for partial updates

$changes = $oldPerson->bsonChanges($newPerson);
// ['$set' => ['name' => 'Bob'], '$unset' => ['deleted_at' => '']]

Use with MongoDB collection

$doc = $collection->findOne(
    ['_id' => new ObjectId('6240de600000000000000000')],
    ['typeMap' => ['root' => Person::class]]
);
// $doc is a hydrated Person instance

Architecture

src/
├── Attribute/
│   ├── BsonSerialize.php           # Marks properties for BSON serialization
│   └── BsonDiscriminator.php       # Polymorphic discriminator (replaces Symfony's)
├── Metadata/
│   ├── BsonMetadata.php            # Value object: serializable + deserializable props
│   ├── BsonSerializableProperty.php
│   ├── BsonDeserializableProperty.php
│   ├── BsonPropertyType.php       # Value object: className, isCollection, isNullable
│   ├── BsonDiscriminatorMap.php    # Value object: typeProperty + mapping
│   ├── BsonMetadataResolverInterface.php
│   ├── AbstractBsonMetadataResolver.php  # Base resolver (uses PropertyInfoExtractor)
│   └── Symfony/
│       ├── Symfony62MetadataResolver.php  # SF 5.x / 6.x type resolution
│       └── Symfony7MetadataResolver.php   # SF 7.x / 8.x type resolution
├── PropertyAccess/
│   ├── BsonPropertyAccessorInterface.php
│   └── SymfonyPropertyAccessor.php        # Delegates to Symfony PropertyAccess
├── Serializer/
│   ├── BsonSerializer.php          # Core serializer (zero Symfony imports)
│   └── BsonSerializerInterface.php # Public contract
├── Model/
│   └── Base.php                    # Abstract base class
├── Aggregation/
│   ├── AbstractAggregation.php
│   └── MongoAggregation.php
├── Utils.php
└── bson.php                        # oid() helper function

Framework-agnostic core

The Serializer/BsonSerializer.php has zero Symfony imports. All framework coupling is isolated in adapter files:

Concern Interface Symfony Adapter
Property access BsonPropertyAccessorInterface SymfonyPropertyAccessor
Metadata resolution BsonMetadataResolverInterface Symfony62MetadataResolver / Symfony7MetadataResolver
Type introspection AbstractBsonMetadataResolver (uses PropertyInfoExtractor)

The serializer auto-detects the Symfony version at runtime and instantiates the correct resolver.

Reference

#[BsonSerialize] attribute

Marks a property for BSON serialization/deserialization.

#[BsonSerialize]                    // uses snake_case of property name as BSON field
#[BsonSerialize(name: '_id')]      // explicit BSON field name

Rules:

  • Private/protected properties require a getter (for serialization) and a setter (for deserialization), or be public.
  • The name parameter is the BSON field name. If omitted, the property name is converted to snake_case.
  • DateTime properties are automatically converted to/from UTCDateTime.
  • BackedEnum properties are automatically converted to/from their scalar value.

#[BsonDiscriminator] attribute

Declares a discriminator map on an abstract class for polymorphic deserialization.

use Athenea\MongoLib\Attribute\BsonDiscriminator;

#[BsonDiscriminator('type', [
    'cat' => CatModel::class,
    'dog' => DogModel::class,
])]
abstract class AbstractAnimal extends Base
{
    #[BsonSerialize]
    private ?string $type = null;
}

class CatModel extends AbstractAnimal
{
    #[BsonSerialize]
    private ?int $lives = null;
}

When deserializing, the serializer reads $data['type'] and instantiates the matching concrete class.

Symfony #[DiscriminatorMap] fallback: If your project already uses Symfony's serializer with #[DiscriminatorMap], it works too — no changes needed.

Supported types

PHP type BSON representation Example
string, int, float, bool Direct name: 'Alice'
?string (nullable) Direct or skip name: null → property skipped
DateTime, DateTimeInterface UTCDateTime Automatic conversion
ObjectId ObjectId Preserved as-is
BackedEnum scalar value Status::Active1
array, stdClass Recursive Nested serialization
Base subclass Recursive bsonSerialize() Nested models
array<SubModel> Recursive with @var See collection types below

Collection types with @var

PHP type hints don't express generic arrays (array<SubModel>). Use @var docblocks:

#[BsonSerialize]
/** @var SimpleModel[] */
private array $items = [];

The metadata resolver reads @var annotations via phpdocumentor/reflection-docblock (through symfony/property-info) and deserializes each element as SimpleModel.

ObjectId helper

use function Athenea\MongoLib\BSON\oid;

$document = $collection->findOne(['_id' => oid('6240de600000000000000000')]);

Testing

# Run tests (requires Symfony 8.0 by default)
vendor/bin/phpunit

# Test across all supported Symfony versions
php bin/test-all-symfony-versions.php

The cross-version script temporarily installs each Symfony version, runs the test suite, and restores the original composer.json.

License

MIT License. See LICENSE for details.

athenea/mongo-lib 适用场景与选型建议

athenea/mongo-lib 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 5.95k 次下载、GitHub Stars 达 0, 最近一次更新时间为 2022 年 03 月 30 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 athenea/mongo-lib 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 athenea/mongo-lib 我们能提供哪些服务?
定制开发 / 二次开发

基于 athenea/mongo-lib 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 5.95k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 0
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: Unknown
  • 更新时间: 2022-03-30