-
Notifications
You must be signed in to change notification settings - Fork 3
[203]: add model relations property annotations #208
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds model relations property annotations to Laravel models by generating @property annotations for relationships. The implementation adds support for both single and collection-based relationships with appropriate type hints.
- Adds
@propertyannotations for model relationships in generated models - Imports
Illuminate\Database\Eloquent\Collectionwhen collection-type relations are present - Generates proper type hints for singular (
Model|null) and plural (Collection|Model) relationships
Reviewed Changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| stubs/model.blade.php | Adds conditional import for Collection class when collection-type relations exist |
| src/Generators/ModelGenerator.php | Implements logic to generate relation annotations and determine Collection import necessity |
| tests/fixtures/ModelGeneratorTest/*.php | Test fixtures showing expected output with relation property annotations |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
src/Generators/ModelGenerator.php
Outdated
| foreach ($relations as $relation) { | ||
| $relation = class_basename($relation); | ||
|
|
||
| $result[$this->getRelationName($relation, $type)] = $this->getRelationType($relation, $type); |
Copilot
AI
Oct 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method getRelationName() is being called but is not defined in this class. This will cause a fatal error when the code is executed.
src/Generators/ModelGenerator.php
Outdated
| protected function getRelationType(string $relation, string $type): string | ||
| { | ||
| if (in_array($type, self::PLURAL_NUMBER_REQUIRED)) { | ||
| return "Collection|$relation"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| return "Collection|$relation"; | |
| return "Collection<{$relation}>"; |
src/Generators/ModelGenerator.php
Outdated
| $relation = class_basename($relation); | ||
|
|
||
| $result[$this->getRelationName($relation, $type)] = $this->getRelationType($relation, $type); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's try to refactor it to prevent code duplication (the same logic already exists in the prepareRelations)
refs: #203
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| 'User.php' => file_get_contents(getcwd() . '/tests/Support/Models/WelcomeBonus.php'), | ||
| 'Forum/Author.php' => file_get_contents(getcwd() . '/tests/Support/Models/WelcomeBonus.php'), | ||
| ]; | ||
| if (!empty ($models)) { |
Copilot
AI
Oct 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the space between !empty and the opening parenthesis. The correct syntax is !empty($models).
| if (!empty ($models)) { | |
| if (!empty($models)) { |
src/Generators/ModelGenerator.php
Outdated
| 'entity' => $this->model, | ||
| ]); | ||
|
|
||
| // TODO: use ronasit/larabuilder instead |
Copilot
AI
Oct 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the extra spaces before the TODO comment. Use consistent indentation with // followed by a single space.
| // TODO: use ronasit/larabuilder instead | |
| // TODO: use ronasit/larabuilder instead |
src/Generators/ModelGenerator.php
Outdated
| $import = "use {$import};"; | ||
|
|
||
| if (!Str::contains($classContent, $import)) { | ||
| // TODO: use ronasit/larabuilder instead |
Copilot
AI
Oct 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the extra spaces before the TODO comment. Use consistent indentation with // followed by a single space.
| // TODO: use ronasit/larabuilder instead | |
| // TODO: use ronasit/larabuilder instead |
src/Generators/ModelGenerator.php
Outdated
| { | ||
| $annotation = "* @property {$propertyDataType} \${$propertyName}"; | ||
|
|
||
| // TODO: use ronasit/larabuilder instead |
Copilot
AI
Oct 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the extra spaces before the TODO comment. Use consistent indentation with // followed by a single space.
| // TODO: use ronasit/larabuilder instead | |
| // TODO: use ronasit/larabuilder instead |
src/Generators/ModelGenerator.php
Outdated
| protected function getRelationType(string $model, string $relation): string | ||
| { | ||
| if (in_array($relation, self::PLURAL_NUMBER_REQUIRED)) { | ||
| return "Collection<int, $model>"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| return "Collection<int, $model>"; | |
| return "Collection<{$model}>"; |
| * @property Carbon $published_at | ||
| * @property array $meta | ||
| * @property Comment|null $comment | ||
| * @property Collection<int, User> $users |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| * @property Collection<int, User> $users | |
| * @property Collection<User> $users |
|
|
||
| //TODO: add @property annotation for each model's field | ||
| /** | ||
| * @property Collection<int, User> $users |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| * @property Collection<int, User> $users | |
| * @property Collection<User> $users |
|
|
||
| /** | ||
| * @property string $title | ||
| * @property Collection<int, Author> $authors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| * @property Collection<int, Author> $authors | |
| * @property Collection<Author> $authors |
| * @property Carbon $published_at | ||
| * @property array $meta | ||
| * @property Comment|null $comment | ||
| * @property Collection<int, User> $users |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| * @property Collection<int, User> $users | |
| * @property Collection<User> $users |
|
|
||
| //TODO: add @property annotation for each model's field | ||
| /** | ||
| * @property Collection<int, Category> $categories |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| * @property Collection<int, Category> $categories | |
| * @property Collection<Category> $categories |
tests/ModelGeneratorTest.php
Outdated
| public function testAddPropertyAnnotationToRelatedModel() | ||
| { | ||
| $this->mockFilesystem([ | ||
| 'Post.php' => $this->getFixture('new_model_without_fields.php'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
may we just add the Post model to the mockFilesystem method?
| } | ||
|
|
||
| public function mockFilesystem(): void | ||
| public function mockFilesystem(array $models = []): void |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's implement it as separate methods
public function mockFilesystem(array $models = []): voidpublic function mockDefaultFilesystem(): void
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| public function mockFilesystem(): void | ||
| public function mockFilesystem(array $models = []): void | ||
| { | ||
| $fileSystemMock = new FileSystemMock; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| $fileSystemMock = new FileSystemMock; | |
| $fileSystemMock = new FileSystemMock(); |
ref: https://www.php-fig.org/psr/psr-12/#4-classes-properties-and-methods
| public function mockDefaultFilesystem(): void | ||
| { | ||
| $fileSystemMock = new FileSystemMock(); | ||
| $fileSystemMock = new FileSystemMock; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| $fileSystemMock = new FileSystemMock; | |
| $fileSystemMock = new FileSystemMock(); |
ref: https://www.php-fig.org/psr/psr-12/#4-classes-properties-and-methods
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @foreach($anotationProperties as $key => $value) | ||
| * @property {{ $value }} ${{ $key }} | ||
| @foreach($annotationProperties as $key => $value) | ||
| * @property {!! $value !!} ${{ $key }} |
Copilot
AI
Nov 3, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Using unescaped output {!! !!} for the property value could be a security concern if the value contains malicious content. However, since this is a code generator and values come from controlled sources (the generator itself), this is acceptable. Consider adding a comment explaining why unescaped output is necessary here (to preserve type syntax like Collection<Model>).
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
refs: #203