ralphjsmit/laravel-helpers

一个包含方便的助手函数的Laravel应用包。

1.9.0 2024-03-14 08:30 UTC

README

此包包含了一组方便的助手函数,用于您的Laravel应用。

安装

您可以通过composer安装此包

composer require ralphjsmit/laravel-helpers

Laravel

工厂

您可以让您的工厂扩展Laravel默认的工厂,也可以让它们扩展RalphJSmit\Helpers\Laravel\Factories\Factory类。

使用resolveRelationship()进行复杂的工厂关系

当您有一个复杂的关系时,您可以使用resolveRelationship()方法来解决这个关系。如果您想使用闭包或类似的方式来修改工厂,这非常有用。

use RalphJSmit\Helpers\Laravel\Factories\Factory;

class PostFactory extends Factory
{
    public function definition(): array
    {
        return [
            'user_id' => null,
        ];
    }
    
    public function withUser(User|UserFactory|Closure|int|null $user = null): static
    {
        return $this->set('user_id', $this->resolveRelationship(User::class, $user));    
    }
}

一个简单的例子可能如下所示

$post = Post::factory()
    ->withUser(fn(UserFactory $factory): UserFactory => $factory->set('name', 'John Doe'))
    ->create();

管道,流水线 & 可管道

管道与流水线

Laravel有一个未记录的功能叫做流水线。流水线非常适合将数据通过一系列的函数/类发送。

然而,Laravel中的流水线有一个很大的缺点:在每一个函数或类中,您需要调用一个闭包来移动到流水线中的下一个管道。如果您不调用这个闭包,流水线就会停止。Laravel中间件就是一个很好的例子。

但是,有时您可能不想使用闭包,只想将第一个管道的结果传递给第二个管道,这意味着整个流水线总是会被执行。此包为此提供了一个自定义实现,称为“管道”。您没有停止执行的方法(请使用常规流水线),但您也不需要在每个管道中调用闭包。

从现在起,我将把这个包的自定义实现称为“管道”,而将更高级的、常规的Laravel实现称为“流水线”。

流水线

您可以使用pipeline()函数创建一个新的流水线

$result = pipeline()
  ->send($class)
  ->through($pipes)
  ->thenReturn();

要了解更多关于流水线的信息,请查看这篇文章

管道

您可以使用pipe()函数创建一个新的管道

$result = pipe($thing)
  ->through([
    PerformAction::class,
    PerformAnotherAction::class,
  ])
  ->then(function($result) {
    // Do something with $result and return it.
    return $result;
  });

->through()数组中的每个项目可以是以下之一

  1. 一个闭包或可调用对象
  2. 一个可调用的类(它也是一个可调用对象)
  3. 一个类实例
  4. 一个类字符串

默认情况下,管道将尝试通过方法'handle'来执行每个项目。您可以使用->via()方法来更改该方法。

在每个管道的末尾,您可以将一个闭包传递给->then()方法来对结果进行处理。您也可以使用->thenReturn()方法立即返回结果。

$result = pipe($thing)
  ->through(/** */)
  ->via('execute')
  ->thenReturn();

可管道

此包还提供了一个方便的特性,您可以使用它来使您的类可管道。如果您包含此特性,您的类将具有以下新方法

  1. ->pipe($callback)。此方法将对象传递给给定的闭包或可调用对象,并返回执行的可调用对象的结果。
  2. ->pipeInto($class)。此pipeInto()方法创建给定类的新实例,并将对象传递给构造函数。
  3. ->pipeThrough($callbacks)。此pipeThrough()方法将对象传递给给定的闭包/可调用对象数组,并返回执行的可调用对象的结果。

所有三种方法都与 \Illuminate\Support\Collection 类中同名的方法相同。例如,请参阅 Laravel 网站上关于 pipe()pipeInto()pipeThrough() 的文档。

Carbon

此包提供了一些方便的辅助函数,使使用 Carbon 对象更加愉快。

carbon($input = null, $timezone = null)

您可以使用 carbon($input, $timezone) 辅助函数来创建一个 Carbon 对象。在底层,这使用 Carbon::parse()。两个参数都是可选的。

$firstDayOfNextMonth = carbon('first day of next month', 'Europe/Amsterdam');

carbonDate($input = null, $timezone = null)

您可以使用 carbonDate($input, $timezone) 辅助函数来创建一个 Carbon 对象,并将天.floor() 到 00:00:00。底层使用 Carbon::parse()->floorDay()。两个参数都是可选的。

$firstDayOfNextMonth = carbonDate('first day of next month', 'Europe/Amsterdam');

$firstDayOfNextMonth->toTimeString();
// '00:00:00'

yesterday()tomorrow()

您可以使用 tomorrow() 函数创建明天的 Carbon 实例。底层使用 now()->addDay()

您可以使用 yesterday() 函数创建昨天的 Carbon 实例。底层使用 now()->subDay()

$tomorrow = tomorrow();
$yesterday = yesterday();

daysOfMonth(Carbon|string $month)

您可以使用 daysOfMonth() 函数创建一个 Collection 实例,其中月份的日期作为数字键,值为 0。这对于创建图表等非常有用。

$days = daysOfMonth(carbon('march 2021'));

$days->all();
//          [
//            1 => 0,
//            2 => 0,
//            3 => 0,
//            4 => 0,
//            5 => 0,
//            ...
//            30 => 0,
//            31 => 0,
//         ]

Eloquent

TimeCast

Eloquent 提供了许多有用的类型转换,如 arraydatedatetime。然而,Laravel 并没有提供 time 类型转换,用于存储和转换如 "08:30:00" 这样的时间戳到 Carbon 实例。

原因可能是因为仅传递 "08:30:00" 这样的时间戳到 Carbon 假设了一个带有当前日期的 Carbon 实例。这可能会或可能不会成为您的问题。

为了将时间字符串转换为 Carbon 实例,您可以将 TimeCast 类设置为类型转换。但请注意,这将创建一个假设当前日期的 Carbon 实例。

use RalphJSmit\Helpers\Laravel\Models\Casts\TimeCast;

class Something extends Model
{
    protected $casts = [
        'time' => TimeCast::class,
    ];
};

BooleanAsTimestampCast

BooleanAsTimestampCast 类型转换是一个方便的类型转换,您可以使用它将布尔值存储为时间戳。实际上,这仍然与数据库中的普通布尔值一样工作。但是,以这种方式存储布尔值可以为您提供额外的优势,即知道布尔值何时启用。

如果值设置为 true,它将在数据库中存储当前的时间戳。如果值设置为 false,它将在数据库中存储 null

use RalphJSmit\Helpers\Laravel\Models\Casts\TimeCast;

class Something extends Model
{
    protected $casts = [
        'time' => BooleanAsTimestampCast::class,
    ];
};
#### Smart factory name guessing with `HasFactory`

You can use the new `HasFactory` trait to automatically guess the name of your factories. This optimized factory trait can also guess the name of factories in different namespaces than `App\Models`, like `Support\.

```php
use Illuminate\Database\Eloquent\Model;
use RalphJSmit\Helpers\Laravel\Concerns\HasFactory;

class MyModel extends Model 
{
    use HasFactory;
}

如果您需要或希望自行定义工厂类,您还可以使用 protected $factory 属性来定义您的工厂。

class MyModel extends Model 
{
    use HasFactory;
    
    protected $factory = MyModelFactory::class;
}

Livewire

CanBeRefreshed 特性

您可以使用 CanBeRefreshed 特性来自动注册以下事件

use RalphJSmit\Helpers\Livewire\CanBeRefreshed;

class MyComponent extends Component
{
    use CanBeRefreshed;
    
    // Will register the following event and listener:
    // [ '$refresh' => '$refresh', ]
    
    // Registering additional listeners is no problem:
    protected $listeners = [
        /* Your other listeners */
    ];
}

RegisterListeners 特性

您可以使用 RegisterListeners 特性动态注册事件监听器,例如从 mount()initialized() 方法中。

use RalphJSmit\Helpers\Livewire\RegisterListeners;

// Somewhere...
$this->registerListeners([
    'my-event' => 'myListener'
]);

RegisterMessages 特性

您可以使用 RegisterMessages 特性动态注册事件监听器,例如从 mount()initialized() 方法中。

use RalphJSmit\Helpers\Livewire\RegisterMessages;

// Somewhere...
$this->registerMessages([
    'user.email.required' => 'Adding an e-mail address is required.'
]);

通用

🐞 如果您发现一个错误,请提交详细的问题,我会尽快修复。

🔐 如果您发现一个漏洞,请查看 我们的安全策略

🙌 如果您想贡献,请提交拉取请求。所有 PR 都会得到完全的认可。如果您不确定我是否会接受您的想法,请随时联系我!

🙋‍♂️ Ralph J. Smit