envor/parental

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

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

维护者

详细信息

github.com/envor/parental

来源

资助包维护!
calebporzio

0.0.1 2024-02-11 05:31 UTC

This package is auto-updated.

Last update: 2024-02-11 05:35:27 UTC


README

Parental - Use single table inheritance in your Laravel App

Parental

Parental是一个Laravel包,它将STI(单表继承)功能带到了Eloquent。

什么是单表继承(STI)?

这是一个复杂名称,指的是一个简单概念:扩展一个模型(通常是为了添加特定行为),但引用的是同一个表。

安装

composer require envor/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特质和一个type列到users表中,运行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 上的想法启发。