imanghafoori / laravel-decorator
一个易于装饰函数调用的包。
Requires
- php: 7.4.*|8.0.*|8.1.*|8.2.*|8.3.*|8.4.*
- illuminate/container: ~5.5|6.*|7.*|8.*|9.*|10.*|^11.0|^12.0
- illuminate/support: ~5.5|6.*|7.*|8.*|9.*|10.*|^11.0|^12.0
Requires (Dev)
- orchestra/testbench: ~6.0|^9.0
- squizlabs/php_codesniffer: 3.*
Suggests
- imanghafoori/laravel-anypass: Allows you login with any password in local environment.
- imanghafoori/laravel-heyman: It allows to write expressive code to authorize, validate and authenticate.
- imanghafoori/laravel-masterpass: You can set a master password for your accounts.
- imanghafoori/laravel-widgetize: Gives you a better structure and caching opportunity for your laravel apps.
README
Laravel应用中的装饰器模式
为聪明的整洁程序员而设计,爱心满满
尝试将Python语言中的"装饰器"功能移植到Laravel框架中。
🚚 安装
composer require imanghafoori/laravel-decorator
什么是 "装饰器"
❓
装饰器是一个可调用的函数,它围绕原始装饰的可调用函数包装,以形成一个新的可调用函数,该函数由前两个组成。
就像一条蛇把一只鹿整个吞下去,然后围绕它的身体盘旋!
之后,这条蛇就具有了吃草和消化草的能力了,因为它的体内有只鹿。
技术上,一个 "装饰器"
1- 是一个 "可调用对象"
2- 它接受另一个 "可调用对象"(就像蛇吞食另一条蛇一样,作为它的唯一参数)
3- 并返回一个新的 "可调用对象"
(它在内部调用原始的可调用对象,在它之前和之后放置一些代码)
什么?!?!?! (0_o)
在Laravel中,什么可以被认为是 "可调用对象"
?!?
简单来说,任何可以被调用(调用)的东西,例如:使用 App::call();
或 call_user_func()
调用,如:'MyClass@myMethod'
或闭包,[UserRepo::class, 'find']
像专业人士一样缓存
缓存数据库查询总是需要的,但总是很麻烦要在现有代码中添加更多代码。它会使代码更加混乱,我们可能会破坏当前的代码,毕竟它增加了一层雾。
想象一下,你有一个 UserController
,它调用 UserRepo@find
来获取 $user
。
然后过了一段时间,你决定出于明显的原因在这两个类之间添加一个缓存层。
根据SOLID原则,你不应该在控制器或UserRepo中放置缓存代码逻辑,而应该在两者之间。
换句话说,你希望在不修改现有代码的情况下添加新功能(在这个例子中是缓存)。
这听起来像是 开闭原则
对吧?!👃
你希望保持职责分离。在这种情况下,缓存不应该在存储库或控制器中,而应该在其自己的类中。
这听起来像是 单一职责原则
对吧?!👃
class UserRepository { function find($uid) { return User::find($uid); } } class MadUsersController extends Controller { function show ($madUserId) { $madUser = app()->call('UserRepository@find', ['id' => $madUserId]); } }
现在没有缓存,直接调用。
借助laravel-decorator内置的缓存装饰器,你可以去 AppServiceProvider.php
(或任何其他服务提供者)
<?php use Imanghafoori\Decorator\Decorators\DecoratorFactory; class AppServiceProvider extends ServiceProvider { public function boot() { $keyMaker = function ($madId) { return 'mad_user_key_' . $madId; }; $time = 10; $decorator = DecoratorFactory::cache($keyMaker, $time); \Decorator::decorate('UserRepository@find', $decorator); } }
你将在你的 UserController
中从调用中获取缓存的输出,而不需要触摸它!但请记住更改
app()->call('UserRepository@find', ... // to : app('decorator')->call('UserRepository@find', ...
定义你自己的装饰器
public function boot () { \Decorator::define('myDecoratorName1', 'SomeClass@someMethod'); // or \Decorator::define('myDecoratorName2', function ($callable) { return function (...) use ($callable){ ... } }); }
然后你可以使用这个名称(myDecoratorName
)来装饰方法。
如何装饰一个方法?
// You may set multiple decorators on a single method... \Decorator::decorate('class@method, 'someClass@someOtherDecorator'); // (first) // or reference the decorator by its name : \Decorator::decorate('class@method, 'myDecoratorName'); // (second)
如何调用带其装饰器的方法?
装饰门面
装饰门面方法
首先,你应该扩展 Imanghafoori\Decorator\DecoratableFacade
类(而不是laravel基门面)。
现在你可以在你的服务提供者的boot方法中应用装饰器
然后,当你像平常一样调用你的门面时,你会得到装饰的结果。
⚠️ 注意
能力越大,责任越大。
记住,当你装饰某物时,不要违反 Liskoves替代原则
。
例如,一个返回 int|null
的方法调用在装饰后不应该意外地返回 string
。
$result = app('decorate')->call(...
因为方法的用户应该准备好接受他们得到的值的类型。
但是如果你只返回 int
类型,并且你的装饰器导致 null
值被过滤掉,那就没问题。
⭐ 你的点赞让我们做得更多 ⭐
一如既往,如果你觉得这个包很有用,并希望鼓励我们维护和改进它,请 点击星号按钮
表达你的意愿。
作者的其他包
💎 一个简洁而强大的包,为你提供重构控制器的机会。
💎 一个简洁而强大的包,为你的Laravel应用提供更好的结构和缓存机会。
💎 它仅允许你在本地环境中使用任何密码登录。
💎 与 hey-man 包一起,授权和ACL现在变得非常简单!