From 392d5cfc8039e405c6054a648dd5c4d6bc23bce1 Mon Sep 17 00:00:00 2001 From: isaackaara Date: Wed, 4 Mar 2026 12:52:03 +0300 Subject: [PATCH] fix: place PHPDoc before class attributes when writing to models (#1765) When using --write/-W with models that have PHP 8 attributes (e.g. #[ObservedBy(...)]), the generated PHPDoc block was inserted between the attribute and the class declaration: #[ObservedBy([ImageObserver::class])] /** * @property string $name */ final class Image extends Model This breaks PHPStan/Larastan because the docblock must come before the attributes. The fix scans backward from the class declaration to find any preceding PHP 8 attributes and inserts the docblock before them: /** * @property string $name */ #[ObservedBy([ImageObserver::class])] final class Image extends Model Fixes #1734 --- src/Console/ModelsCommand.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Console/ModelsCommand.php b/src/Console/ModelsCommand.php index b26c84c..757c3d7 100644 --- a/src/Console/ModelsCommand.php +++ b/src/Console/ModelsCommand.php @@ -1202,6 +1202,14 @@ class ModelsCommand extends Command $replace = "{$modelDocComment}\n"; $pos = strpos($contents, "final class {$classname}") ?: strpos($contents, "class {$classname}"); if ($pos !== false) { + // If PHP 8 attributes (e.g. #[ObservedBy(...)]) precede the class + // declaration, insert the docblock before the first attribute so that + // the resulting order is: docblock → attributes → class. + $before = substr($contents, 0, $pos); + if (preg_match('/(\s*(?:#\[.+?\]\s*)+)$/s', $before, $matches)) { + $pos -= strlen($matches[1]); + $replace = "{$modelDocComment}\n"; + } $contents = substr_replace($contents, $replace, $pos, 0); } }