laragear / meta-model
允许其他开发者定制您的包模型和迁移
Requires
- php: ^8.1
- illuminate/database: 10.*|11.*
Requires (Dev)
- mockery/mockery: ^1.6
- phpunit/phpunit: ^10.5|11.*
This package is auto-updated.
Last update: 2024-08-31 00:02:31 UTC
README
允许其他开发者定制您的包模型和迁移。
use Illuminate\Database\Eloquent\Model; use Laragear\MetaModel\CustomizableModel; use MyVendor\MyPackage\Migrations\MyMigration; class MyPackageModel extends Model { use CustomizableModel; protected static function migrationClass(): string { return MyMigration::class } }
提示
您是从包中过来的吗?您可能想阅读 MIGRATIONS.md 文件。
保持此包免费
您的支持使我能够保持此包免费、最新和维护。或者,您也可以 传播信息!
要求
- Laravel 10 或更高版本
安装
启动 Composer 并将其要求添加到您的包中
composer require laragear/meta-model
定制模型
大多数时候,您的用户会希望定制包中的模型和迁移。例如,他们可能希望添加列并将它们转换为特定的数据类型,或者修改哪些属性被隐藏。这可以通过包含 CustomizableModel
特质的模型来实现。
namespace Vendor\Package\Models; use Illuminate\Database\Eloquent\Model; use Laragear\MetaModel\CustomizableModel; use Vendor\Package\Migrations\CarMigration; class Car extends Model { use CustomizableModel; protected static function migrationClass(): string { return CarMigration::class; } }
从那里,最终开发者可以使用可用的静态属性来定制模型
$useConnection
: 要使用的自定义连接名称。$useTable
: 要使用的自定义表名称。$useCasts
: 要合并的铸造属性。$useFillable
: 要合并的填充属性。$useGuarded
: 要合并的受保护属性。$useHidden
: 要合并的隐藏属性。$useVisible
: 要合并的可见属性。$useAppends
: 要合并的追加属性。
除了 $useTable
之外的所有静态属性都接受一个闭包,该闭包接收模型并返回一个属性数组。最终开发者应在 AppServiceProvider
的 boot()
方法中修改这些属性。
namespace App\Providers; use MyVendor\MyPackage\Models\Car; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { /** * Bootstrap any application services. */ public function boot(): void { Car::$useCasts = ['is_new' => 'boolean']; } }
追加
正如你所猜测的,useAppend
只在您的模型有属性访问器时才工作。如果您期望用户在模型序列化时追加属性,确保您有适当的访问器。
例如,我们可以在我们的 Car 模型中添加 color
和 chassis
属性访问器。
namespace Vendor\Package\Models; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Model; use Laragear\MetaModel\CustomizableModel; use Vendor\Package\Migrations\ModelMigration; class Car extends Model { use CustomizableModel; // ... protected function getColorAttribute() { return $this->metadata->color; } protected function chassis(): Attribute { return Attribute::get(fn() => (string) $this->metadata->chassis) } }
之后,最终开发者可以在运行时追加这些属性。
namespace App\Providers; use MyVendor\MyPackage\Models\Car; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { /** * Bootstrap any application services. */ public function boot(): void { Car::$useAppends = ['color', 'chassis']; } }
可定制迁移
要允许可定制迁移,创建一个标准的迁移文件,但不是返回一个扩展默认 Migration
类的类,而是返回一个调用您的模型类的 migration()
调用。
让我们解释一下这是多么神奇。
例如,假设我们想要为 Car 模型创建一个迁移。我们将创建一个扩展 CustomizableMigration
类的类。从那里,表模式将在 create()
方法中处理。
namespace MyVendor\MyPackage\Migrations; use Illuminate\Database\Schema\Blueprint; use Laragear\MetaModel\CustomizableMigration; use MyVendor\MyPackage\Models\Car; class CarsMigration extends CustomizableMigration { protected function create(Blueprint $table) { $table->id(); $table->string('manufacturer'); $table->string('model'); $table->tinyInteger('year'); $table->timestamps(); } }
定义我们的默认迁移类后,我们需要在模型的 $migration
静态属性中指定它所在的位置
namespace MyVendor\MyPackage\Models; use Illuminate\Database\Eloquent\Model; use Laragear\MetaModel\CustomizableModel; use MyVendor\MyPackage\Migrations\CarsMigration; class Car extends Model { use CustomizableModel; protected static function migrationClass(): string { reutnr CarsMigration::class }; }
一旦这样,我们就可以创建迁移文件 0000_00_00_000000_create_cars_table.php
。我们不返回一个扩展默认 Laravel 迁移的类,而是使用我们的模型和 migration()
方法。
// database/migrations/0000_00_00_000000_create_cars_table.php use MyVendor\MyPackage\Models\Car; use Illuminate\Database\Schema\Blueprint; return Car::migration();
启动
您可以使用 boot()
方法在迁移实例化时运行自定义逻辑。
namespace MyVendor\MyPackage\Migrations; use Illuminate\Database\Schema\Blueprint; use Laragear\MetaModel\CustomizableMigration; use MyVendor\MyPackage\Models\Car; class CarsMigration extends CustomizableMigration { protected function boot() : void { if (app()->isUnitTesting()) { Car::$useConnection = env('DB_CONNECTION'); } } protected function create(Blueprint $table) { $table->id(); $table->string('manufacturer'); $table->string('model'); $table->tinyInteger('year'); $table->timestamps(); } }
注意
每次实例化迁移时都会运行 boot()
方法。确保当需要时,该方法的效果是幂等的。
添加自定义列
您可能希望让最终开发者在迁移中添加额外的列。为了实现这一点,只需在 create()
方法内部任何位置调用 addColumns()
,确保传递 Blueprint
实例。在调用此方法的一个好位置是在 timestamps()
之前或主键之后。
namespace MyVendor\MyPackage\Migrations; use Illuminate\Database\Schema\Blueprint; use Laragear\MetaModel\CustomizableMigration; abstract class CarsMigration extends CustomizableMigration { protected function create(Blueprint $table) { $table->id(); $table->string('manufacturer'); $table->string('model'); $table->tinyInteger('year'); $this->addColumns($table); $table->timestamps(); } }
之后,在您的迁移文件中,向 migration()
方法添加一个空的回调,或使用 with()
方法,让最终开发者知道他可以扩展表模式。
use MyVendor\MyPackage\Models\Car; use Illuminate\Database\Schema\Blueprint; return Car::migration(function (Blueprint $table) { // Add your custom columns here. // Don't forget to add casts to the model if necessary! })
最终开发者也可以根据需要以编程方式添加多个回调,这对于分离关注点非常有用。
use MyVendor\MyPackage\Models\Car; use Illuminate\Database\Schema\Blueprint; return Car::migration( fn ($table) => /* ... */, fn ($table) => /* ... */, fn ($table) => /* ... */, );
提示
如果您不想支持额外的列,则可以省略 addColumns()
调用,因为任何添加的回调都不会执行。
多态
注意
多态仅支持单一关系。在一个表上存在多个多态关系被强烈不建议。
如果您的迁移需要多态关系,您会发现最终开发者在其应用程序中不一定有相同的键类型。这个问题可以通过使用 createMorph()
或 createNullableMorph()
方法并传递 Blueprint
实例和多态类型的名称来解决。
protected function create(Blueprint $table) { $table->id(); $this->createMorphRelation($table, 'ownable'); $table->string('manufacturer'); $table->string('model'); $table->tinyInteger('year'); $table->timestamps(); }
这将允许最终开发者在需要时通过 morph()
方法更改多态类型。例如,如果他在目标模型中使用 ULID 多态,他可能只需一行代码即可设置它
use MyVendor\MyPackage\Models\Car; return Car::migration()->morph('ulid', 'custom_index_name');
默认索引名称
您也可以为多态设置自定义的索引名称。除非用户手动覆盖,否则它将作为默认值使用。
protected function create(Blueprint $table) { $this->createMorphRelation($table, 'ownable', 'ownable_table_index'); // ... }
use MyVendor\MyPackage\Models\Car; // Uses "custom_index_name" as index name return Car::migration()->morph('ulid', 'custom_index_name'); // Uses "ownable_table_index" as index name return Car::migration()->morph('ulid');
在升级后和降级前
最终开发者可以使用 afterUp()
和 beforeDown()
方法分别执行逻辑,在表创建后,在表删除前。这允许开发者增强表或避免失败的迁移。
例如,最终开发者可以使用这些方法创建外键列引用,并在删除表之前删除它们。
use MyVendor\MyPackage\Models\Car; use Illuminate\Database\Schema\Blueprint; return Car::migration() ->afterUp(function (Blueprint $table) { $table->foreign('manufacturer')->references('name')->on('manufacturers'); }) ->beforeDown(function (Blueprint $table) { $table->dropForeign('manufacturer'); });
重要
afterUp()
和 beforeDown()
为迁移添加回调,它不会替换它们。
包文档
如果您计划将其添加到您的包中,您可能还想将 MIGRATIONS.md 文件复制并粘贴到您的包中。这样开发者就会知道如何使用您的模型和迁移。或者,您也可以仅复制其内容,或链接回此存储库。
Laravel Octane 兼容性
- 没有使用过时的应用程序实例的单例。
- 没有使用过时的配置实例的单例。
- 没有使用过时的请求实例的单例。
- 特质静态属性只被最终开发者写入一次。
使用此包与 Laravel Octane 一起使用应该没有问题。
安全
如果您发现任何与安全相关的问题,请通过电子邮件 darkghosthunter@gmail.com 反馈,而不是使用问题跟踪器。
许可证
在发布时,此特定包版本是根据 MIT 许可证 的条款许可的。
Laravel 是 Taylor Otwell 的商标。版权所有 © 2011-2024 Laravel LLC。