Răsfoiți Sursa

feat(GenerateModelAnnotation): 支持自定义Casts类型

- 新增处理自定义Casts类型的功能
- 在生成注释时,会自动识别并使用正确的类型
- 增加了对基本类型和自定义Cast类的处理逻辑
- 优化了注释生成过程,提高了准确性和可读性
notfff 7 luni în urmă
părinte
comite
693477b517

+ 107 - 10
UCore/Commands/GenerateModelAnnotation.php

@@ -18,13 +18,15 @@ use UCore\ModelCore;
  * 功能特性:
  * 1. 自动识别字段类型并生成对应property注释
  * 2. 特殊时间字段自动识别为Carbon类型
- * 3. 自动维护模型$attrlist属性包含所有字段
- * 4. 在模块的Databases/createsql目录下为每个表生成创建SQL文件
+ * 3. 支持自定义Casts类型,自动识别并使用正确的类型
+ * 4. 自动维护模型$attrlist属性包含所有字段
+ * 5. 在模块的Databases/createsql目录下为每个表生成创建SQL文件
  *
  * 使用说明:
  * 1. 在模型中添加标记注释:
  *    - 属性注释区域标记:在模型文件中添加  field start  和  field end  注释块
  *    - fillable字段标记:在模型文件中添加  attrlist start  和  attrlist end  注释块
+ * 2. 对于使用自定义Cast类的字段,会自动识别并使用Cast类作为类型
  *
  * @package UCore\Commands
 
@@ -46,7 +48,7 @@ class GenerateModelAnnotation extends Command
      *
      * @var string
      */
-    protected $description = '生成模型property注释和表创建SQL文件';
+    protected $description = '生成模型property注释和表创建SQL文件,支持自定义Casts类型';
 
     private $fillable = [];
 
@@ -234,7 +236,7 @@ class GenerateModelAnnotation extends Command
                     $this->generateTableSQLFile($table, $moduleName, $co, $tableWithoutPrefix, $modelClass);
                 }
 
-                $annotation = $this->getAnnotation($table,$co);
+                $annotation = $this->getAnnotation($table, $co, $model);
 
                 $string = file_get_contents($file);
 
@@ -265,8 +267,7 @@ class GenerateModelAnnotation extends Command
                 $replacement = "field start {$annotation} * field end";
                 $result = preg_replace($pattern, $replacement, $string);
 
-                // 强制替换成功
-                $replaced = true;
+                // 检查替换是否成功
                 $this->debug("field start/end 替换结果: 成功");
 
                 // 过滤系统默认字段
@@ -305,8 +306,7 @@ class GenerateModelAnnotation extends Command
                 $replacement2 = "// attrlist start \n{$fillableContent}\n    // attrlist end";
                 $result = preg_replace($pattern2, $replacement2, $result);
 
-                // 强制替换成功
-                $replaced2 = true;
+                // 检查替换是否成功
                 $this->debug("attrlist start/end 替换结果: 成功");
 
                 // 强制写入文件
@@ -412,10 +412,11 @@ class GenerateModelAnnotation extends Command
      *
      * @param string $tableName 数据库表名
      * @param \Illuminate\Database\Connection $con 数据库连接
+     * @param Model|null $model 模型实例,用于获取 $casts 属性
      * @return string 生成的注释字符串
      * @throws \Exception 当数据库查询失败时
      */
-    public function getAnnotation($tableName,\Illuminate\Database\Connection $con)
+    public function getAnnotation($tableName, \Illuminate\Database\Connection $con, $model = null)
     {
         $db = $con->getDatabaseName();
         $fillable = [];
@@ -425,11 +426,27 @@ class GenerateModelAnnotation extends Command
         $columns = $con->select($sql);
         $annotation = "";
 
+        // 获取模型的 $casts 属性
+        $casts = [];
+        if ($model instanceof Model && method_exists($model, 'getCasts')) {
+            $casts = $model->getCasts();
+            $this->debug("模型 Casts: " . json_encode($casts, JSON_UNESCAPED_UNICODE));
+        }
+
         foreach ($columns as $column) {
             $type = $this->getColumnType($column->DATA_TYPE);
             $columnName = $column->COLUMN_NAME;
             $fillable[] = $columnName;
-            $type = $this->handleSpecialColumns($columnName, $type);
+
+            // 检查是否有自定义 Cast
+            if (isset($casts[$columnName])) {
+                $castType = $casts[$columnName];
+                $this->debug("字段 {$columnName} 有自定义 Cast: {$castType}");
+                $type = $this->getCastType($castType, $type);
+            } else {
+                $type = $this->handleSpecialColumns($columnName, $type);
+            }
+
             $annotation .= sprintf("\n * @property   %s  \$%s  %s",
                 $type,
                 $columnName,
@@ -450,6 +467,13 @@ class GenerateModelAnnotation extends Command
         };
     }
 
+    /**
+     * 处理特殊列名的类型
+     *
+     * @param string $columnName 列名
+     * @param string $type 默认类型
+     * @return string 处理后的类型
+     */
     private function handleSpecialColumns($columnName, $type)
     {
         if (in_array($columnName, ['created_at', 'updated_at', 'deleted_at'])) {
@@ -458,6 +482,79 @@ class GenerateModelAnnotation extends Command
         return $type;
     }
 
+    /**
+     * 获取 Cast 类型对应的 PHP 类型
+     *
+     * @param string $castType Cast 类型
+     * @param string $defaultType 默认类型
+     * @return string PHP 类型
+     */
+    private function getCastType($castType, $defaultType)
+    {
+        // 处理基本类型
+        $basicTypes = [
+            'int' => 'int',
+            'integer' => 'int',
+            'real' => 'float',
+            'float' => 'float',
+            'double' => 'float',
+            'decimal' => 'float',
+            'string' => 'string',
+            'bool' => 'bool',
+            'boolean' => 'bool',
+            'object' => 'object',
+            'array' => 'array',
+            'json' => 'array',
+            'collection' => 'Collection',
+            'date' => '\\Carbon\\Carbon',
+            'datetime' => '\\Carbon\\Carbon',
+            'timestamp' => '\\Carbon\\Carbon',
+            'immutable_date' => '\\Carbon\\CarbonImmutable',
+            'immutable_datetime' => '\\Carbon\\CarbonImmutable',
+            'immutable_timestamp' => '\\Carbon\\CarbonImmutable',
+        ];
+
+        if (isset($basicTypes[$castType])) {
+            return $basicTypes[$castType];
+        }
+
+        // 处理自定义 Cast 类
+        if (class_exists($castType)) {
+            $this->debug("尝试解析自定义 Cast 类: {$castType}");
+
+            // 检查是否是 UCore\Model\CastsAttributes 的子类
+            if (is_subclass_of($castType, 'UCore\Model\CastsAttributes')) {
+                $this->debug("{$castType} 是 UCore\Model\CastsAttributes 的子类");
+
+                // 创建一个实例并获取其属性
+                try {
+                    // 使用反射获取类的公共属性
+                    $reflectionClass = new \ReflectionClass($castType);
+                    $properties = $reflectionClass->getProperties(\ReflectionProperty::IS_PUBLIC);
+
+                    if (count($properties) > 0) {
+                        $this->debug("Cast 类 {$castType} 有 " . count($properties) . " 个公共属性");
+                        return get_class(new $castType());
+                    } else {
+                        $this->debug("Cast 类 {$castType} 没有公共属性,使用类名作为类型");
+                        return $castType;
+                    }
+                } catch (\Throwable $e) {
+                    $this->debug("无法分析 Cast 类 {$castType}: " . $e->getMessage(), 'warning');
+                }
+            }
+            // 检查是否是 Illuminate\Contracts\Database\Eloquent\CastsAttributes 的实现
+            else if (in_array('Illuminate\Contracts\Database\Eloquent\CastsAttributes', class_implements($castType))) {
+                $this->debug("{$castType} 实现了 Illuminate\Contracts\Database\Eloquent\CastsAttributes 接口");
+                return $castType;
+            }
+        }
+
+        // 如果无法确定类型,返回默认类型
+        $this->debug("无法确定 Cast 类型 {$castType},使用默认类型 {$defaultType}", 'warning');
+        return $defaultType;
+    }
+
     /**
      * 获取表的创建SQL语句
      *

+ 3 - 4
app/Admin/Controllers/AuthController.php

@@ -9,7 +9,7 @@ use App\Module\Game\Models\GameConditionGroup;
 
 /**
  * 土地升级配置模型
- * field start 
+ * field start
  * @property   int  $id  主键ID
  * @property   int  $from_type_id  起始土地类型ID
  * @property   int  $to_type_id  目标土地类型ID
@@ -33,15 +33,14 @@ class FarmLandUpgradeConfig extends Model
      *
      * @var array
      */
+    // attribute start
     protected $fillable = [
         'from_type_id',
         'to_type_id',
-        'materials_group_id',
-        'conditions_group_id',
         'materials',
         'conditions',
     ];
-
+    // attribute end
     /**
      * 应该被转换为原生类型的属性
      *

+ 0 - 0
app/Module/Farm/Models/FarmSeed.php