stevema/laravel-relations

laravel的模型关系管理 项目中一堆模型的关系 管理起来很不舒服 写个插件专门做关系管理

v1.0.0 2023-11-15 15:56 UTC

This package is not auto-updated.

Last update: 2024-05-29 18:16:49 UTC


README

介绍

laravel的模型关系管理 项目中一堆模型的关系 管理起来很不舒服 写个插件专门做关系管理

软件架构

软件架构说明

安装教程


# 安装

$ composer require stevema/laravel-relations

使用说明

# 1、生成配置文件
$ php artisan vendor:publish --tag="relations"

# 2、修改配置文件 /config/relations.php
return [
    /*
    |--------------------------------------------------------------------------
    | Relations Config
    |--------------------------------------------------------------------------
    |
    |   直接把关系文件放到下面的数组中就行
    |
    */

    // 模型的别名 - 多态关系也会使用到模型的别名
    'alias' => [
        // '别名' => 模型::class,
    ],
    // 模型的主键 没有特殊可以不定义 默认就是id
    'primarys' => [
        // '别名/模型:class' => '主键'
    ],
    'relations' => [
        
    ],
];

目录说明

├─ src
│   ├─ Config           # 配置文件目录
│   │   └─ config.php   # 配置文件
│   ├─ Consoles         # 命令行目录
│   │   └─ Commands     # 命令文件目录
│   │   └─ Stubs        # 生成文件模板目录
│   ├─ Traits           # 引用文件
│   │   └─ MorphClassName.php   # 模型引用它 可以控制关系别名
│   └─ ManyToMany.php   # 多对多关系
│   └─ MorphManyToMany.php      # 多态多对多关系
│   └─ MorphOneToMany.php       # 多态一对多关系
│   └─ MorphOneToOne.php        # 多态一对一关系
│   └─ OneToMany.php            # 一对多关系
│   └─ OneToManyThrough.php     # 远程一对多关系
│   └─ OneToOne.php             # 一对一关系
│   └─ OneToOneThrough.php      # 远程一对一关系
│   └─ Relations.php            # 关系总管理
│   └─ RelationsProvider.php    # 服务者-里面只做了config获取配置后自动注册别名
└─ composer.json        # 配置

MorphClassName 说明

use Illuminate\Database\Eloquent\Relations\Relation;
// 多态关联的时候 model use这个可以自定义 type 的 别名
trait MorphClassName
{
    // 配置多态的关联关系后 其中的able_type竟然是 App\Models\User 这种
    // 很长不说 还把我的命名空间给暴露了 - 不能忍
    
    // 没配置别名的话 使用表明当做别名
    public bool $useTableNameToMorphName = false;
    
    // 如果没配置别名还不想用表名的话 可以分割命名空间直到获取到模型名
    public bool $classBasename = True;
    
    // 模型都会有这个方法 我这里重写它 按我想要的规则去找别名
    public function getMorphClass()
    {   
        // 获取别名
        $morphMap = Relation::morphMap();
        // 查找别名 找到就返回
        if (! empty($morphMap) && in_array(static::class, $morphMap)) {
            return array_search(static::class, $morphMap, true);
        }
        // 输出表名
        if($this->useTableNameToMorphName){
            return $this->getTable();
        }
        // 输出类名 去掉命名空间后的
        if($this->classBasename){
            return class_basename(self::class);
        }
        // 最不能忍的就是这个输出带命名空间的类名
        return self::class;
    }
}

使用说明 - 从零开始使用

# 1安装

$ composer require stevema/laravel-morphmap

# 2、生成配置文件
$ php artisan vendor:publish --tag="relations"

# 3、修改配置文件 /config/relations.php 先加别名
return [
    /*
    |--------------------------------------------------------------------------
    | Relations Config
    |--------------------------------------------------------------------------
    |
    |   直接把关系文件放到下面的数组中就行
    |
    */

    // 模型的别名 - 多态关系也会使用到模型的别名
    'alias' => [
        // '别名' => 模型::class,
        'badge' => \App\Models\api\Badge::class,
        'user' => \App\Models\User::class,
        'post' => \App\Models\api\Post::class,
        'tag' => \App\Models\api\Tag::class,
        'file' => \App\Models\api\File::class,
        'category' => \App\Models\api\Category::class,
    ],
    // 模型的主键 没有特殊可以不定义 默认就是id
    'primarys' => [
        // '别名/模型:class' => '主键'
    ],
    'relations' => [
        
    ],
];

# 4、 执行命令 生成关系模型 UserProfile
$ php artisan make:relation UserProfile

 请选择您的关系类型? [OneToOne[一对一]]:
  [0] OneToOne[一对一]
  [1] OneToMany[一对多]
  [2] ManyToMany[多对多]
  [3] OneToOneThrough[远程一对一]
  [4] OneToManyThrough[远程一对多]
  [5] MorphOneToOne[多态一对一]
  [6] MorphOneToMany[多态一对多]
  [7] MorphManyToMany[多态多对多]

# 选择一个后 生成 app/Relations/UserProfile.php 模型 根据注释来修改一下
# 里面的别名\模型:class 尽量用别名
# 生成表的时候如果不写别名没有class的情况下会输出错误信息
# 别名可以跳过相关的检测 生成表后 创建模型后可以修改相关配置

# 5.执行命令 生成migrate文件 (如果已经有了表 可以直接进入第8步)
$ php artisan relation:table 

 请选择一个关系 [App\Relations\UserProfile]:
  [0] App\Relations\UserProfile
  [1] App\Relations\UserPosts
  [2] App\Relations\UserCollectPosts
  [3] App\Relations\Likes
 
# 选择后会生成创建表文件 database/migrations/2023_08_24_000001_create_user_profiles_table.php

# 6.修改database/migrations下的文件 根据自己的需求添加字段 (如果已经有了表 可以直接进入第8步)

# 7、生成表 (如果已经有了表 可以直接进入第8步)
$ php artisan migrate

# 8、生成相关模型
$ php artisan make:model UserProfile

# 9.生成模型后 再去修改配置文件 添加别名和 relations中添加关系模型
return [
    /*
    |--------------------------------------------------------------------------
    | Relations Config
    |--------------------------------------------------------------------------
    |
    |   直接把关系文件放到下面的数组中就行
    |
    */

    // 模型的别名 - 多态关系也会使用到模型的别名
    'alias' => [
        // '别名' => 模型::class,
        'badge' => \App\Models\api\Badge::class,
        'user' => \App\Models\User::class,
        'post' => \App\Models\api\Post::class,
        'tag' => \App\Models\api\Tag::class,
        'file' => \App\Models\api\File::class,
        'category' => \App\Models\api\Category::class,
        'user_profile' => \App\Models\api\UserProfile::class,
    ],
    // 模型的主键 没有特殊可以不定义 默认就是id
    'primarys' => [
        // '别名/模型:class' => '主键'
    ],
    'relations' => [
        \App\Relations\UserProfile::class,
    ],
];

# 10. 现在关系生效了 可以去查看效果了
Route::get('t', function(){
    $user = \App\Models\User::find(6);
    dd($user->profile);
    // profile 是  \App\Relations\UserProfile 中配置的
});
# 11. 查看所有模型绑定的关系
$ php artisan relation:list
+----------------------------+---------------+--------------------+------------+---------------+
| 模型                       | 关联方法      | 关系名称           | 类型       | 角色          |
+----------------------------+---------------+--------------------+------------+---------------+
| App\Models\api\UserProfile | user          | user_profile       | 一对一     | belongsTo     |
| App\Models\User            | profile       | user_profile       | 一对一     | hasOne        |
| App\Models\User            | post          | user_posts         | 一对多     | hasMany       |
| App\Models\User            | collect_posts | user_post_collects | 多对多     | belongsToMany |
| App\Models\User            | like_posts    | likes              | 多态多对多 | morphedByMany |
| App\Models\User            | like_comments | likes              | 多态多对多 | morphedByMany |
| App\Models\User            | likes         | likes              | 多态多对多 | morphToMany   |
| App\Models\User            | like_users    | likes              | 多态多对多 | morphedByMany |
| App\Models\api\Post        | user          | user_posts         | 一对多     | belongsTo     |
| App\Models\api\Post        | collect_users | user_post_collects | 多对多     | belongsToMany |
| App\Models\api\Post        | likes         | likes              | 多态多对多 | morphToMany   |
| App\Models\api\Comment     | likes         | likes              | 多态多对多 | morphToMany   |
+----------------------------+---------------+--------------------+------------+---------------+


# 12. 查看所有模型绑定的相关方法
$ php artisan relation:use [-a]  
# -a 是全部  没有-a 会让你选择一个关系模型

您选择的是App\Relations\UserProfile
App\Models\api\UserProfile
  // OneToOne[一对一] user_profile 
  public function user(){ 
      return $this->belongsTo('App\Models\User', 'user_id', 'id')->withDefault();
  }

App\Models\User
  // OneToOne[一对一] user_profile 
  public function profile(){ 
      return $this->hasOne('App\Models\api\UserProfile', 'user_id', 'id')->withDefault(); 
  } 

把这些方法拷贝到相应的模型中 就可以从配置文件 /config/relations.php 中删除了 

备注

  1. 远程一对多关系 和 远程一对一关系 是一样的配置 一般远程一对一好像用不到吧
  2. 如果使用 php artisan relation:use 拷贝到对应的模型中 请务必删除配置文件[/config/relations.php]中的关系模型[relations 里面的] 多次绑定可能除了问题找不到原因
  3. 当 belongsTo,hasOne,hasOneThrough 和 morphOne 这些关联方法返回 null 的时候 你可以定义一个默认的模型返回。该模式通常被称为 空对象模式,它可以帮你省略代码中的一些条件判断。目前只支持 true false null array 还没支持闭包函数 有需要可以拷贝出来自定义