javascript / laravel-macroable-models
一个动态为Laravel模型添加方法的包
Requires (Dev)
- orchestra/testbench: ^8
- phpunit/phpunit: ^10
This package is auto-updated.
Last update: 2024-09-23 17:52:39 UTC
README
一个动态为Laravel模型添加方法的包 🕊
该包为开发者提供了一种简单的方式,可以以编程方式向Laravel Eloquent 模型 添加方法。幕后,它使用了Laravel自带的可宏特例。更多详情,请查看我在博客上的解释。
安装
只需使用composer
安装此包
composer require javoscript/laravel-macroable-models
(仅适用于Laravel <5.5,或如果您想明确指定) - 将服务提供者添加到config/app.php
文件中的providers
数组
// config/app.php $providers = [ // ... \Javoscript\MacroableModels\MacroableModelsServiceProvider::class, // ... ];
使用示例
该包提供了一个门面,以方便访问其功能。或者,您也可以通过app('macroable-models')
辅助函数访问。
出于明显的原因,宏应该在其他系统部分使用它之前添加到模型中。因此,服务提供者的boot
方法是开始添加宏的好地方。
例如,在AppServiceProvider
中向\App\User
模型添加方法
// app/Providers/AppServiceProvider.php // ... use \Javoscript\MacroableModels\Facades\MacroableModels; use \App\User; // ... public function boot() { MacroableModels::addMacro(User::class, 'sayHi', function() { return 'Hi!'; }); }
在向User
模型添加宏之后,现在每个Eloquent模型的实例都将具有可用的sayHi()
方法。我们可以在artisan tinker
中快速验证这一点。
php artisan tinker
>>> \App\User::first()->sayHi()
=> "Hi!"
在专门的MacrosServiceProvider
文件中
如果您想将多个宏定义放在一起,那么添加一个服务提供者可能是好主意。
您可以使用artisan
生成一个新的服务提供者
php artisan make:provider MacrosServiceProvider
然后,您应该将其添加到config/app.php
文件中的providers
数组。
// config/app.php $providers = [ // ... App\Providers\MacrosServiceProvider::class, // ... ];
然后,在新服务提供者的boot
方法中,您可以集中定义宏
// app/Providers/MacrosServiceProvider.php // ... use \Javoscript\MacroableModels\Facades\MacroableModels; use \App\User; // ... public function boot() { MacroableModels::addMacro(User::class, 'sayHi', function() { return 'Hi!'; }); MacroableModels::addMacro(User::class, 'sayBye', function() { return 'Bye bye'; }); }
可用方法
以下示例将使用\App\User
模型,以便您可以在新的Laravel应用程序中尝试这些示例。任何扩展了Illuminate\Database\Eloquent\Model
类的类都可以使用这些宏进行扩展。
addMacro(Model::class, 'macroName', function() {}) : void
此包最重要的方法,也是您最有可能大量使用的方法。向Model::class
模型添加名为macroName
的宏。
在添加宏之后,您可以像通常那样在模型上调用该方法。
MacroableModels::addMacro(\App\User::class, 'sayHi', function() { return "Hi!"; }); \App\User::first()->sayHi();
带参数
定义的宏函数可以接收任何数量和类型的参数。
MacroableModels::addMacro(\App\User::class, 'say', function(string $something) { return $something; }); $user = \App\User::first(); $user->say("Hello world!");
上下文绑定...正确的$this
在宏函数中,您有权访问$this
对象,该对象引用执行函数的模型实例。
MacroableModels::addMacro(\App\User::class, 'getId', function() { return $this->id; }); \App\User::first()->getId(); // 1
添加关系
您也可以定义关系函数!
MacroableModels::addMacro(\App\User::class, 'posts', function() { return $this->hasMany(App\Post::class); });
注意!您将无法使用Laravel的魔法关系属性。
$user = App\User::first(); $user->posts; // null // This will always return null, as the posts attribute wasn't defined $user->posts()->get() // This will correctly return the posts Eloquent collection
覆盖现有宏
如果您添加了一个与现有宏具有相同名称的宏,则它将替换它。
MacroableModels::addMacro(\App\User::class, 'greet', function() { return "Hi!"; }); \App\User::first()->greet(); // "Hi!" MacroableModels::addMacro(\App\User::class, 'greet', function() { return "Hello human"; }); \App\User::first()->greet(); // "Hello human"
模型的优先级
如果您添加了一个与模型中现有方法同名的大宏,后者将具有优先权。您无法使用此包覆盖它。
class Dog extends Illuminate\Database\Eloquent\Model { public function bark() { return "Woof!"; } } MacroableModels::addMacro(Dog::class, 'bark', function() { return "Miauuu!"; }); $dog = new Dog; $dog->bark(); // "Woof!"
removeMacro(Model::class, 'macroName') : boolean
这是addMacro
的反操作,此方法从指定的模型中删除之前添加的大宏。如果模型上已注册该名称的大宏并且已正确删除,则返回true
- 否则返回false
。
MacroableModels::removeMacro(\App\User::class, 'salute'); // false MacroableModels::addMacro(\App\User::class, 'salute', function() { return "Hello!"; }); MacroableModels::removeMacro(\App\User::class, 'salute'); // true
附加功能
因为为什么不呢?🤷♂
getAllMacros() : Array
返回所有已注册的大宏,按名称分组。
MacroableModels::addMacro(\App\User::class, 'hi', function() { return "Hi!"; }) MacroableModels::addMacro(\App\Dog::class, 'hi', function() { return "Woof!"; }) MacroableModels::addMacro(\App\User::class, 'bye', function() { return "Bye bye"; }) MacroableModels::getAllMacros() /* [ "hi" => [ "App\User" => Closure() {#3362 …2}, "App\Dog" => Closure() {#3376 …2}, ], "bye" => [ "App\User" => Closure() {#3366 …2}, ], ] */
modelHasMacro(Model::class, 'macroName') : boolean
很简单:如果模型具有该宏,则返回true
- 否则返回false
。
MacroableModels::modelHasMacro(\App\User::class, 'salute'); // false MacroableModels::addMacro(\App\User::class, 'salute', function() { return "Hi!"; }); MacroableModels::modelHasMacro(\App\User::class, 'salute'); // true
modelsThatImplement('macroName') : Array
给定一个宏名称,它返回一个数组,包含已向其添加的模型类。
MacroableModels::addMacro(\App\User::class, 'hi', function() { return "Hi!"; }); MacroableModels::addMacro(\App\Dog::class, 'hi', function() { return "Woof!"; }); MacroableModels::modelsThatImplement('hi'); /* [ "App\User", "App\Dog", ] */
macrosForModel(Model::class) : Array
给定模型类,它返回一个数组,包含添加到该模型的所有宏,详细说明每个宏定义的参数。
MacroableModels::addMacro(\App\User::class, 'say', function(String $something) { return $something; }); MacroableModels::addMacro(\App\User::class, 'sum', function(Integer $a, Integer $b) { return $a + $b; }); MacroableModels::macrosForModel(\App\User::class); /* [ "say" => [ "name" => "say", "parameters" => [ ReflectionParameter {#3385 +name: "something", position: 0, typeHint: "string", }, ], ], "sum" => [ "name" => "sum", "parameters" => [ ReflectionParameter {#3357 +name: "a", position: 0, typeHint: "Integer", }, ReflectionParameter {#3360 +name: "b", position: 1, typeHint: "Integer", }, ], ], ] */
相关包
有一些相关的包,从中汲取了一些灵感。