diff --git a/packages/database/src/Builder/ModelInspector.php b/packages/database/src/Builder/ModelInspector.php index 22a14bc15..89db10c89 100644 --- a/packages/database/src/Builder/ModelInspector.php +++ b/packages/database/src/Builder/ModelInspector.php @@ -196,7 +196,7 @@ public function getBelongsTo(string $name): ?BelongsTo $singularizedName = $name->singularizeLastWord(); - if (! $singularizedName->equals($name)) { + if (! $singularizedName->equals($name) && $this->reflector->hasProperty($singularizedName)) { return $this->getBelongsTo($singularizedName); } @@ -264,7 +264,7 @@ public function getHasOne(string $name): ?HasOne $singularizedName = $name->singularizeLastWord(); - if (! $singularizedName->equals($name)) { + if (! $singularizedName->equals($name) && $this->reflector->hasProperty($singularizedName)) { return $this->getHasOne($singularizedName); } @@ -343,7 +343,7 @@ public function getHasOneThrough(string $name): ?HasOneThrough $singularizedName = $name->singularizeLastWord(); - if (! $singularizedName->equals($name)) { + if (! $singularizedName->equals($name) && $this->reflector->hasProperty($singularizedName)) { return $this->getHasOneThrough($singularizedName); } diff --git a/packages/intl/src/Pluralizer/InflectorPluralizer.php b/packages/intl/src/Pluralizer/InflectorPluralizer.php index e72009f07..93b823d33 100644 --- a/packages/intl/src/Pluralizer/InflectorPluralizer.php +++ b/packages/intl/src/Pluralizer/InflectorPluralizer.php @@ -70,7 +70,7 @@ private function extractLastWord(string $value, ?string &$prefix = null, ?string ? array_pop(array: $parts) : ''; - if (count(value: $parts) === 0) { + if ($parts === []) { return null; } diff --git a/tests/Integration/Database/ModelInspector/LatinPluralRelationTest.php b/tests/Integration/Database/ModelInspector/LatinPluralRelationTest.php new file mode 100644 index 000000000..5baa287d2 --- /dev/null +++ b/tests/Integration/Database/ModelInspector/LatinPluralRelationTest.php @@ -0,0 +1,127 @@ +getRelation(name: 'product_metadata'); + + $this->assertInstanceOf( + expected: BelongsTo::class, + actual: $relation, + ); + + $this->assertSame( + expected: 'LEFT JOIN metadata ON metadata.id = products.metadata_id', + actual: $relation + ->getJoinStatement() + ->compile(dialect: DatabaseDialect::SQLITE), + ); + } + + #[Test] + public function has_one_with_latin_plural_property_name(): void + { + $model = inspect(model: LatinPluralMetadataModel::class); + $relation = $model->getRelation(name: 'extra_data'); + + $this->assertInstanceOf( + expected: HasOne::class, + actual: $relation, + ); + } + + #[Test] + public function has_one_through_with_latin_plural_property_name(): void + { + $model = inspect(model: LatinPluralMetadataModel::class); + $relation = $model->getRelation(name: 'product_criteria'); + + $this->assertInstanceOf( + expected: HasOneThrough::class, + actual: $relation, + ); + } + + #[Test] + public function latin_plural_belongs_to_uses_fk_in_select_fields(): void + { + $model = inspect(model: LatinPluralProductModel::class); + $fields = $model->getSelectFields()->toArray(); + + $this->assertContains( + needle: 'metadata_id', + haystack: $fields, + ); + $this->assertNotContains( + needle: 'product_metadata', + haystack: $fields, + ); + } +} + +#[Table(name: 'products')] +final class LatinPluralProductModel +{ + public PrimaryKey $id; + + #[BelongsTo] + public ?LatinPluralMetadataModel $product_metadata = null; + + public string $name; +} + +#[Table(name: 'metadata')] +final class LatinPluralMetadataModel +{ + public PrimaryKey $id; + + public string $value; + + #[HasOne] + public ?LatinPluralExtraDataModel $extra_data = null; + + #[HasOneThrough(through: LatinPluralIntermediateModel::class)] + public ?LatinPluralCriteriaModel $product_criteria = null; +} + +#[Table(name: 'extra_data')] +final class LatinPluralExtraDataModel +{ + public PrimaryKey $id; + + public string $info; +} + +#[Table(name: 'intermediate')] +final class LatinPluralIntermediateModel +{ + public PrimaryKey $id; + + public LatinPluralMetadataModel $metadata; + + public string $link; +} + +#[Table(name: 'criteria')] +final class LatinPluralCriteriaModel +{ + public PrimaryKey $id; + + public string $label; +}