calebporzio / parental
v1.4.0
2024-03-12 13:04 UTC
Requires
- php: ^8.0
- illuminate/database: ^9.0||^10.0||^11.0
- illuminate/events: ^9.0||^10.0||^11.0
Requires (Dev)
- orchestra/testbench: ^7.0||^8.0||^9.0
- phpunit/phpunit: ^9.5.10||^10.5
- tightenco/duster: ^2.7
This package is auto-updated.
Last update: 2024-03-14 15:51:15 UTC
README
Parental
Parental是一个Laravel包,它将STI(单表继承)功能引入Eloquent。
什么是单表继承(STI)?
这是一个简单概念的复杂名称:扩展模型(通常用于添加特定行为),但引用相同的表。
安装
composer require tightenco/parental
简单使用
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Parental\HasChildren; // The "parent" class User extends Model { use HasChildren; // }
namespace App\Models; use Parental\HasParent; // The "child" class Admin extends User { use HasParent; public function impersonate($user) { //... } }
use App\Models\Admin; // Returns "Admin" model, but reference "users" table: $admin = Admin::first(); // Can now access behavior exclusive to "Admin"s $admin->impersonate($user);
我们刚刚解决了什么问题?
没有Parental,调用Admin::first()
会抛出错误,因为Laravel会在admins
表中查找。Laravel使用模型的类名生成预期的表名、外键和枢纽表名。通过将HasParent
特质添加到Admin模型中,Laravel现在将引用父模型的类名users
。
从父模型访问子模型
// First, we need to create a `type` column on the `users` table Schema::table('users', function ($table) { $table->string('type')->nullable(); });
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Parental\HasChildren; // The "parent" class User extends Model { use HasChildren; protected $fillable = ['type']; }
namespace App\Models; use Parental\HasParent; // A "child" class Admin extends User { use HasParent; }
namespace App\Models; use Parental\HasParent; // Another "child" class Guest extends User { use HasParent; }
use App\Models\Admin; use App\Models\Guest; use App\Models\User; // Adds row to "users" table with "type" column set to: "App/Admin" Admin::create(...); // Adds row to "users" table with "type" column set to: "App/Guest" Guest::create(...); // Returns 2 model instances: Admin, and Guest User::all();
我们刚刚解决了什么问题?
在此之前,如果我们运行:User::first()
,我们只会得到User
模型。通过添加HasChildren
特质和在users
表中添加一个type
列,运行User::first()
将返回子模型实例(在这种情况下是Admin
或Guest
)。
类型别名
如果您不想在类型列中存储原始类名,您可以使用$childTypes
属性来覆盖它们。
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Parental\HasChildren; class User extends Model { use HasChildren; protected $fillable = ['type']; protected $childTypes = [ 'admin' => Admin::class, 'guest' => Guest::class, ]; }
现在,运行Admin::create()
将把users
表中的type
列设置为admin
而不是App\Models\Admin
。
如果您正在处理现有的类型列,或者您想将应用程序的详细信息与应用程序数据库解耦,这个特性很有用。
自定义类型列名称
您可以通过在父模型上设置$childColumn
属性来覆盖默认的类型列。
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Parental\HasChildren; class User extends Model { use HasChildren; protected $fillable = ['parental_type']; protected $childColumn = 'parental_type'; }
Laravel Nova支持
如果您想使用与子模型共享的父Nova资源,您可以在NovaServiceProvider的boot方法的末尾注册以下提供程序
class NovaServiceProvider extends NovaApplicationServiceProvider { public function boot() { parent::boot(); // ... $this->app->register(\Parental\Providers\NovaResourceProvider::class); } }
感谢@sschoger为糟糕的标志设计,以及@DanielCoulbourne在Twenty Percent Time上帮助构思想法。