waavi/laravel-value-objects

Laravel 5.1 的值对象

1.0.0 2016-01-14 15:42 UTC

This package is auto-updated.

Last update: 2024-09-13 23:28:08 UTC


README

Latest Version on Packagist Software License Build Status Total Downloads

允许你在 Eloquent 模型中创建值对象,然后将其作为普通字符串或 json 编码保存到数据库中。

WAAVI 是一家位于西班牙马德里的网络开发工作室。您可以在 waavi.com 上了解更多关于我们的信息。

安装

您可以通过 composer 安装此包

composer require waavi/laravel-value-objects 1.0.x

用法

使用单字段值对象

假设您想向 Device Eloquent 模型添加一个 Temperature 字段。您可能希望对此字段应用转换,或以摄氏度、华氏度或开尔文为单位获取值。如果您在多个模型中使用此类字段,则可能需要在所有模型之间复制粘贴这些函数,这可能变得很麻烦。

这就是值对象变得非常有用的地方。让我们看看它是如何工作的。首先,我们创建了 Device 模型,该模型将具有一个转换为 Temperature 值对象的温度字段,并使用 'CastsValueObjects' 特性。

    use Illuminate\Database\Eloquent\Model;

    class Device extends Model
    {
        use \Waavi\ValueObjects\Traits\CastsValueObjects;

        /**
         * The attributes that should be casted to native types.
         *
         * @var array
         */
        protected $casts = [
            'temperature'   => Temperature::class,
        ];
    }

Temperature 值对象将扩展自 'Waavi\ValueObjects\Single',可以定义如下

    use Waavi\ValueObjects\Single;

    class Temperature extends Single
    {
        /**
         * @return float
         */
        public function inCelsius()
        {
            // In single field value objects, the name of the field is always $value
            return (float) $this->value;
        }

        /**
         * @return float
         */
        public function inKelvin()
        {
            return (float) $this->value + 273.15;
        }

        /**
         * @return float
         */
        public function inFahrenheit()
        {
            return (float) $this->value * 1.8 + 32;
        }
    }

单字段值对象以普通字符串形式保存到数据库中,可以使用以下方式使用

    $device = new Device;
    $device->temperature = new Temperature(30);
    $device->temperature = 30;          // This also works
    echo $device->temperature;          // Prints '30'
    echo $device->temperature->value;         // Prints '30'
    echo $device->temperature->inKelvin();    // Prints 303.15

您也可以使用访问器和修改器,就像在 Eloquent 模型中一样。例如,您可以重新编写 Temperature 类如下

    use Waavi\ValueObjects\Single;

    class Temperature extends Single
    {
        /**
         *  Make all subzero temperatures equal to zero.
         *  @return void
         */
        public function setValueAttribute($value)
        {
            $this->attributes['value'] = $value > 0 ? $value : 0;
        }

        /**
         * @return float
         */
        public function getCelsiusAttribute()
        {
            return (float) $this->value;
        }

        /**
         * @return float
         */
        public function getKelvinAttribute()
        {
            return (float) $this->value + 273.15;
        }

        /**
         * @return float
         */
        public function getFahrenheitAttribute()
        {
            return (float) $this->value * 1.8 + 32;
        }
    }

然后,您可以按如下方式访问温度属性

    $device = new Device;
    $device->temperature = 30;
    echo $device->temperature;            // Prints '30'
    echo $device->temperature->value;     // Prints '30'
    echo $device->temperature->kelvin;    // Prints 303.15

使用多字段值对象

有时值对象可能不是那么简单,可能需要多个字段而不是一个字段。假设我们有一个包含起点和终点字段的 Trip 模型,这些字段由坐标组成。然后,我们可以像以前一样定义 Trip 模型

    use Illuminate\Database\Eloquent\Model;

    class Trip extends Model
    {
        use \Waavi\ValueObjects\Traits\CastsValueObjects;

        /**
         * The attributes that should be casted to native types.
         *
         * @var array
         */
        protected $casts = [
            'origin'        => Coordinate::class,
            'destination'   => Coordinate::class,
        ];
    }

然后,我们可以定义 Coordinate 值对象如下

    use Waavi\ValueObjects\Json;

    class Coordinate extends Json
    {
        protected $fillable = ['lat', 'lng'];

        /**
         *  Return the distance between this coordinate and another
         *
         *  @return float
         */
        public function distanceTo(Coordinate $coord) {
            /** Calculate distance **/
            return $distance;
        }
    }

现在我们需要扩展自 'Waavi\ValueObjects\Json' 值对象,因为我们需要多个字段来表示我们的值对象,并且我们需要定义一个包含允许在值对象中使用的字段名称的 fillable 数组。这次,字段在保存之前将被 json 编码。

与之前一样,提供了修改器和访问器。

我们可以这样处理这个模型对象

    $trip = new Trip;
    $trip->origin = new Coordinate(['lat' => 20.1221, 'lng' => 12.1231]);
    $trip->destination = new Coordinate(['lat' => 10.13, 'lng' => 12.14]);
    echo $trip->origin;                     // Prints json representation {'lat':'20.1221','lng':'12.1231'}
    echo $trip->origin->lat;              // Prints '20.1221'
    echo $trip->origin->distanceTo($trip->destination);      // Prints distance between them.