gawsoft / laravel-macroable-models
从用于动态为Laravel模型添加方法的包派生而来
Requires (Dev)
- orchestra/testbench: ^8
- phpunit/phpunit: ^10
This package is auto-updated.
Last update: 2024-09-25 16:04:07 UTC
README
这是从原始仓库 javoscript/laravel-macroable-models 分支出来的。原始仓库未更新,且所有者不接受pull请求。
Laravel 动态宏模型
一个用于动态为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", }, ], ], ] */
相关包
有一些相关的包,从中获取了一些灵感。