Skip to content

Add relationships - #7

Merged
GromNaN merged 1 commit into
doctrine:0.1.xfrom
GromNaN:relations
Feb 24, 2026
Merged

Add relationships#7
GromNaN merged 1 commit into
doctrine:0.1.xfrom
GromNaN:relations

Conversation

@GromNaN

@GromNaN GromNaN commented Feb 3, 2026

Copy link
Copy Markdown
Member

There are 4 types of relationships: EmbedOne, EmbedMany, ReferenceOne, ReferenceMany

@GromNaN
GromNaN force-pushed the relations branch 2 times, most recently from 9f01777 to e55b47c Compare February 11, 2026 23:08
@GromNaN
GromNaN marked this pull request as ready for review February 11, 2026 23:38
@GromNaN
GromNaN force-pushed the relations branch 2 times, most recently from 74d1380 to efa32f6 Compare February 11, 2026 23:46

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds MongoDB ODM relationship support (EmbedOne, EmbedMany, ReferenceOne, ReferenceMany) to the maker workflow, including source manipulation utilities and tests.

Changes:

  • Introduces relation modeling classes and extends ClassSourceManipulator to generate ODM relation attributes/properties (including constructor initialization for collections).
  • Updates MakeDocument interactive flow to prompt for relation details and write inverse-side mappings when requested.
  • Adds unit snapshot tests and functional maker tests to exercise relationship generation.

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
tests/MongoDB/snapshots/reference_one.php Snapshot for generated ReferenceOne property/attribute output.
tests/MongoDB/snapshots/reference_many.php Snapshot for generated ReferenceMany collection + constructor init.
tests/MongoDB/snapshots/multiple_collections.php Snapshot ensuring multiple collections are all initialized once in constructor.
tests/MongoDB/snapshots/field.php Snapshot for adding a basic ODM field.
tests/MongoDB/snapshots/embed_one.php Snapshot for generated EmbedOne property/attribute output.
tests/MongoDB/snapshots/embed_many.php Snapshot for generated EmbedMany collection + constructor init.
tests/MongoDB/ClassSourceManipulatorTest.php Adds snapshot-based unit tests for field + relation generation.
tests/Maker/MakeDocumentTest.php Adds functional scenarios for creating documents with relations (currently with TODO assertions).
src/MongoDB/StaticReflectionService.php Adds replacement reflection service for disconnected metadata loading.
src/MongoDB/RelationReferenceOne.php Adds relation mapping object for ReferenceOne metadata.
src/MongoDB/RelationReferenceMany.php Adds relation mapping object for ReferenceMany metadata.
src/MongoDB/RelationEmbedOne.php Adds relation mapping object for EmbedOne metadata.
src/MongoDB/RelationEmbedMany.php Adds relation mapping object for EmbedMany metadata.
src/MongoDB/MongoDBHelper.php Refactors metadata discovery/autocomplete to use metadata factory and supports disconnected mode.
src/MongoDB/DocumentRelation.php Introduces interactive relation model used by the maker flow.
src/MongoDB/ClassSourceManipulator.php Adds APIs to generate ODM relation attributes/properties and init collections in constructors.
src/MongoDB/BaseRelation.php Adds base relation value object used by relation types.
src/MongoDB/BaseCollectionRelation.php Adds base class for collection relations (uses custom return type Collection).
src/Maker/MakeDocument.php Extends maker prompts + generation logic to handle relations and inverse-side updates.
phpstan.neon.dist Ignores class-not-found errors for snapshot fixtures.
phpcs.xml.dist Relaxes an alignment sniff rule (likely due to new formatting).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +75 to +86
public function getOwningRelation(): RelationReferenceOne|RelationEmbedOne
{
return match ($this->getType()) {
self::REFERENCE_ONE => new RelationReferenceOne(
propertyName: $this->owningProperty,
targetClassName: $this->inverseClass,
targetPropertyName: $this->inverseProperty,
isSelfReferencing: $this->isSelfReferencing,
mapInverseRelation: $this->mapInverseRelation,
isOwning: true,
isNullable: $this->isNullable,
),

Copilot AI Feb 12, 2026

Copy link

Choose a reason for hiding this comment

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

$this->inverseProperty is a typed property that is not always initialized (e.g. when mapInverseRelation is false). Accessing it here will trigger a fatal error (Typed property ... must not be accessed before initialization). Fix by making $inverseProperty nullable (and defaulting to null) and/or only passing targetPropertyName when it is actually set.

Copilot uses AI. Check for mistakes.
Comment on lines +156 to +163
public function setMapInverseRelation(bool $mapInverseRelation): void
{
if ($mapInverseRelation && isset($this->inverseProperty)) {
throw new Exception('Cannot set setMapInverseRelation() to true when the inverse relation property is set.');
}

$this->mapInverseRelation = $mapInverseRelation;
}

Copilot AI Feb 12, 2026

Copy link

Choose a reason for hiding this comment

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

The guard condition is inverted: setting mapInverseRelation to true when inverseProperty is set should be valid, while setting it to false after inverseProperty is set is what creates an inconsistent state. Adjust the condition (and exception message) accordingly.

Copilot uses AI. Check for mistakes.
Comment thread src/Maker/MakeDocument.php
Comment on lines +157 to +166
$attributeOptions = ['targetDocument' => new ClassNameValue($typeHint, $targetClass)];

// Add inversedBy or mappedBy if provided
if (isset($options['inversedBy'])) {
$attributeOptions['inversedBy'] = $options['inversedBy'];
}

if (isset($options['mappedBy'])) {
$attributeOptions['mappedBy'] = $options['mappedBy'];
}

Copilot AI Feb 12, 2026

Copy link

Choose a reason for hiding this comment

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

ReferenceOne should not be configured with both inversedBy and mappedBy at the same time (they represent owning vs inverse concerns). Consider validating the $options combination and throwing an InvalidArgumentException (or picking one deterministically) to avoid generating invalid ODM mapping.

Copilot uses AI. Check for mistakes.
Comment thread src/MongoDB/ClassSourceManipulator.php
Comment on lines +99 to +103
foreach ($this->registry->getManagers() as $dm) {
assert($dm instanceof DocumentManager);
$cmf = $dm->getMetadataFactory();
assert($cmf instanceof AbstractClassMetadataFactory);

Copilot AI Feb 12, 2026

Copy link

Choose a reason for hiding this comment

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

Relying on assert() for runtime type safety is fragile because assertions may be disabled, which could lead to hard failures later. Prefer a real runtime guard (e.g. if (! $dm instanceof DocumentManager) { continue; }) and similarly for the metadata factory type.

Copilot uses AI. Check for mistakes.
Comment on lines +20 to +24
/** @return string[] */
public function getParentClasses(string $class): array
{
return [];
}

Copilot AI Feb 12, 2026

Copy link

Choose a reason for hiding this comment

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

These ReflectionService methods currently return hard-coded values ([] / true) that don't reflect the real class structure. This can cause incorrect metadata behavior in disconnected mode (e.g. treating non-existent methods as present, ignoring inheritance). Implement them using ReflectionClass (and matching visibility checks) to return accurate results.

Copilot uses AI. Check for mistakes.
Comment on lines +58 to +61
public function hasPublicMethod(string $class, string $method): bool
{
return true;
}

Copilot AI Feb 12, 2026

Copy link

Choose a reason for hiding this comment

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

These ReflectionService methods currently return hard-coded values ([] / true) that don't reflect the real class structure. This can cause incorrect metadata behavior in disconnected mode (e.g. treating non-existent methods as present, ignoring inheritance). Implement them using ReflectionClass (and matching visibility checks) to return accurate results.

Copilot uses AI. Check for mistakes.
Comment on lines +115 to +117
yield 'it_creates_document_with_reference_one_relation' => [
self::createMakeDocumentTest()
->run(static function (MakerTestRunner $runner): void {

Copilot AI Feb 12, 2026

Copy link

Choose a reason for hiding this comment

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

These newly added functional scenarios don't assert that the generated document code actually contains the expected relationship mapping (they contain TODO markers). Add concrete assertions (e.g., verify the generated files contain the expected ODM attributes, properties, and constructor initialization) so relation support is exercised end-to-end.

Copilot uses AI. Check for mistakes.
Comment on lines +147 to +149
// TODO: Add relation assertions
}),
];

Copilot AI Feb 12, 2026

Copy link

Choose a reason for hiding this comment

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

These newly added functional scenarios don't assert that the generated document code actually contains the expected relationship mapping (they contain TODO markers). Add concrete assertions (e.g., verify the generated files contain the expected ODM attributes, properties, and constructor initialization) so relation support is exercised end-to-end.

Copilot uses AI. Check for mistakes.
@GromNaN
GromNaN merged commit 2a8f195 into doctrine:0.1.x Feb 24, 2026
7 checks passed
@GromNaN
GromNaN deleted the relations branch February 24, 2026 13:11
@GromNaN GromNaN added this to the 0.1.0 milestone Mar 20, 2026
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