Skip to content

Fix mongo relationships#812

Merged
abnegate merged 14 commits intomainfrom
fix-mongo-relationships
Feb 14, 2026
Merged

Fix mongo relationships#812
abnegate merged 14 commits intomainfrom
fix-mongo-relationships

Conversation

@abnegate
Copy link
Member

@abnegate abnegate commented Feb 14, 2026

Summary by CodeRabbit

  • New Features

    • MongoDB adapter now supports relationship management and operations.
  • Bug Fixes

    • Improved null field handling and special character escaping in MongoDB for better data integrity.
  • Chores

    • Updated PHP runtime to version 8.4 with latest dependencies (Alpine 3.22, Redis 6.3.0, Swoole 6.1.6, MongoDB driver updates).

Copilot AI and others added 12 commits February 13, 2026 00:59
…nd deleteRelationship

- Change getSupportForRelationships() to return true, enabling all relationship tests
- Fix deleteRelationship() ONE_TO_ONE to handle side parameter correctly (matching MariaDB)
- Fix deleteRelationship() ONE_TO_MANY/MANY_TO_ONE to unset correct fields per side
- Fix deleteRelationship() MANY_TO_MANY to use sequence-based junction collection naming and side parameter (matching MariaDB pattern)

Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
- Fix updateRelationship: pass raw collection ID to getDocument for M2M metadata lookup
- Fix updateRelationship: add guards to prevent $rename when old key == new key
- Fix deleteRelationship: pass raw collection ID to getDocument for M2M metadata lookup
- Fix replaceChars: handle all $-prefixed user field names, not just known attributes
- Fix castingAfter: ensure null relationship attributes exist in documents returned from MongoDB

Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
- Escape $ prefix and dots in MongoDB field names (replaceChars, buildFilter, deleteRelationship, updateRelationship)
- Fix renameIndex to search by $id instead of key field
- Add ensureRelationshipDefaults to set null for missing stored relationship attributes
- Add escapeMongoFieldName helper for consistent field name escaping

Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
…attributes

- Fix endsWith/startsWith regex: remove double-escaping of backslashes from preg_quote
- Add escapeQueryAttributes to handle dots in query attributes vs nested object paths
- Only escape $-prefixed attributes in buildFilter (not nested object paths)
- Add collection-aware attribute escaping in find() and count() methods
- All 606 MongoDB tests now pass (0 failures, 0 errors, 4 skips from @Depends)

Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
Move the $index null check before deleteIndex() call to prevent
deleting an index that wasn't found in metadata.

Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
Skip the test when getSupportForAttributes() is false (schemaless mode)
because schemaless databases allow unknown attributes by design, so
Structure validation won't reject the 'name' attribute.

Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
The null check for $index at line 1125 guarantees it's non-null,
making the $index && condition at line 1134 always true.
PHPStan level 7 flagged this as "Left side of && is always true".

Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 14, 2026

📝 Walkthrough

Walkthrough

This PR upgrades the Docker environment from PHP 8.3 to 8.4 with updated extensions (Redis, Swoole) and implements MongoDB driver build fallback. The primary change enables relationship support in the MongoDB adapter with comprehensive update/delete logic, field escaping for Mongo compatibility, and null population for missing relationship fields.

Changes

Cohort / File(s) Summary
Docker Environment
Dockerfile
Bumps base image to php:8.4.18-cli-alpine3.22, updates extensions (Redis 6.3.0, Swoole v6.1.6), adds MongoDB driver pecl fallback with source build, replaces postgresql-dev with libpq-dev, updates extension paths to new hashed directories (no-debug-non-zts-20240924), and adjusts cleanup operations.
MongoDB Adapter Relationship Support
src/Database/Adapter/Mongo.php
Enables relationship support (getSupportForRelationships returns true). Adds collection name variables, field escaping (escapeMongoFieldName, escapeQueryAttributes), guards for rename operations, metadata-driven junction naming for many-to-many relationships, projection-based query handling, and ensureRelationshipDefaults for null population of missing relationship fields.
Test Capability Guard
tests/e2e/Adapter/Scopes/RelationshipTests.php
Adds adapter capability check in testStructureValidationAfterRelationsAttribute to skip assertions when adapter lacks attribute support.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • fogelito

Poem

🐰 With Mongo's heart now bound by ties,
Relations bloom before our eyes—
Fields escape, nulls find their place,
While Docker builds in cyberspace,
PHP 8.4 leads the way,
Relationships flourish, hooray, hooray! 🌟

🚥 Pre-merge checks | ✅ 3 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix mongo relationships' directly and specifically describes the main changes in the pull request, which focus on fixing relationship handling in the MongoDB adapter.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-mongo-relationships

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
src/Database/Adapter/Mongo.php (1)

797-807: $renameKey and $renameTwoWayKey are built with potentially null values.

When $newKey or $newTwoWayKey is null, $escapedNewKey / $escapedNewTwoWayKey will be null, creating ['$rename' => ['someKey' => null]]. These are guarded before use (e.g., line 811), so this doesn't cause a runtime issue today, but it's a latent risk if future code paths use these arrays without the guard.

Consider building rename operations lazily
-        $renameKey = [
-            '$rename' => [
-                $escapedKey => $escapedNewKey,
-            ]
-        ];
-
-        $renameTwoWayKey = [
-            '$rename' => [
-                $escapedTwoWayKey => $escapedNewTwoWayKey,
-            ]
-        ];

         // Build rename operations only when needed (inside each case branch)

Then inline them where used:

if (!\is_null($newKey) && $key !== $newKey) {
    $this->getClient()->update($collectionName, updates: ['$rename' => [$escapedKey => $escapedNewKey]], multi: true);
}

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @.gitignore:
- Line 1: The .gitignore was stripped to only "vendor/" which can cause
accidental commits of IDE and OS artifacts; restore the common ignore entries by
adding back .idea/, .DS_Store, mock.json, and data-tests.php (or explicitly
document that relying on a global gitignore is intentional) so contributors
don't commit editor or macOS metadata; update the .gitignore file to include
those patterns and commit the change.

In `@src/Database/Adapter/Mongo.php`:
- Around line 828-845: The many-to-many branch in updateRelationship (in
src/Database/Adapter/Mongo.php) builds the junction name as
collectionDoc.sequence + relatedCollectionDoc.sequence but ignores the $side
parameter, causing wrong junction selection when called from the child side;
modify the junction computation in updateRelationship to mirror
deleteRelationship / Database::getJunctionCollection logic by swapping the order
of collectionDoc and relatedCollectionDoc (or their sequences) when $side
indicates the child/context flip so the $junction variable matches the same
naming convention used elsewhere before performing the update/rename operations.
🧹 Nitpick comments (1)
Dockerfile (1)

36-45: Good resilience pattern for the MongoDB driver build.

The pecl-first-then-source-fallback approach is solid for handling Alpine compatibility issues. Minor note: the --recurse-submodules flag on git clone already initializes submodules, so the subsequent git submodule update --init --recursive on line 39 is redundant (but harmless).

Optional: remove redundant submodule init
  || (git clone --depth 1 --branch $PHP_MONGODB_VERSION --recurse-submodules https://github.com/mongodb/mongo-php-driver.git /tmp/mongodb \
       && cd /tmp/mongodb \
-      && git submodule update --init --recursive \
       && phpize \

@abnegate abnegate merged commit 5c89b39 into main Feb 14, 2026
32 of 33 checks passed
@abnegate abnegate deleted the fix-mongo-relationships branch February 14, 2026 09:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants