calebporzio/parental

此包已被放弃,不再维护。作者建议使用tightenco/parental包。

一个简单的优雅特质,允许通过子模型访问关系。

资助包维护!
calebporzio

安装: 2,096,837

依赖项: 3

建议者: 0

安全性: 0

星星: 1,262

关注者: 33

分支: 96

开放问题: 7

v1.4.0 2024-03-12 13:04 UTC

README

Parental - Use single table inheritance in your Laravel App

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()将返回子模型实例(在这种情况下是AdminGuest)。

类型别名

如果您不想在类型列中存储原始类名,您可以使用$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为糟糕的标志设计,以及@DanielCoulbourneTwenty Percent Time上帮助构思想法。