eherrera/eloquent-custom-attributes

Laravel的Eloquent ORM的属性处理

dev-master 2018-12-09 21:44 UTC

This package is not auto-updated.

Last update: 2024-09-24 22:05:35 UTC


README

这个小型库允许你为Eloquent模型定义自定义(虚拟)属性,并使用它们与真实属性交互(或选择不交互)。

安装

  • 简单的Composer安装即可:composer require eherrera/eloquent-custom-attributes:dev-master (设置你喜欢的版本要求)

使用

  • CustomAttributeHelperTrait添加到你的模型中,并将任意数量的各种属性处理特性添加到你的模型中
  • 定义$customAttributes属性,并列出属性名及其处理类
  • 重写Eloquent的getAttributesetAttribute方法,以便它们与自定义属性一起工作
  • 之后,你可以像平时一样使用属性。请参阅下面的示例
/**
 * @property array $json_meta_data This attribute is actually of 'string' 
 *                                 type in database and in model. 
 *                                 But we can work with it just like 
 *                                 it is array delegating all underlying 
 *                                 operations to JsonAttrHandlerTrait
 */
class Invoice extends Eloquent
{
    use CustomAttributeHelperTrait;
    use JsonAttrHandlerTrait;

    protected $customAttributes = [
        'json_meta_data' => JsonAttrHandlerTrait::class,
    ];

    /**
     * We have to override Eloquent's getAttribute() /  
     * setAttribute() on the model directly (not in CustomAttributeHelperTrait) 
     * because you might wish to do something in those methods yourself
     */
    public function getAttribute($key)
    {
        if ($this->isCustomAttribute($key)) {
            return $this->getCustomAttribute($key);
        }

        return parent::getAttribute($key);
    }

    public function setAttribute($key, $value)
    {
        if ($this->isCustomAttribute($key)) {
            $this->setCustomAttribute($key, $value);

            return;
        }

        parent::setAttribute($key, $value);
    }
    
/**
 * Just some simple class to show actual work with model ;)
 */
class Main
{
    public function main() {
        $invoice = Invoice::findOrFail(1);
        $invoice->json_meta_data = ['key' => 'value'];
        $invoice->json_meta_data['key_next'] = 'value_next';
        
        $invoice->save();
    }
}

有趣

  • 自定义属性名可以与Laravel模型的真实属性名相同。在这种情况下,自定义属性将隐藏真实属性,并且与之的交互将通过相应的特性进行(当然,你仍然可以通过$model->attributes[]访问原始属性值)。但当然,如果你需要两者都可见,你可以为自定义属性使用另一个名称来与真实属性交互
  • 你可以有一个自定义属性(例如date属性)与模型的好几个真实属性交互(例如daymonthyear,如果需要的话,可以分别交互)

扩展

如果你想实现自己的自定义属性处理器,你只需实现负责值转换的特性即可

  • 此类特性的命名约定为<typeName>AttrHandlerTrait
  • 属性处理特性必须实现两个方法:handleGetAttribute<typeName>handleSetAttribute<typeName>。例如,检查Json\JsonAttrHandlerTrait
  • 在特性中注意方法命名。不要使它们太常见,因为它们必须与Eloquent模型可能使用的其他特性的方法良好共存
  • 如果你的自定义属性表示复杂类型(不仅仅是字符串或数字),请考虑为其创建包装器。此类包装器的示例可以是ArrayAttributeWrapper。它封装一个数组值,提供对它的访问,并在属性更改时更新相应的模型。包装器被缓存,因此可以从脚本中的任何部分多次访问属性