rexlu/ardent

Laravel 4.2 Eloquent ORM的自动验证智能模型,并添加一些ORM功能。

dev-master 2016-08-26 11:14 UTC

This package is not auto-updated.

Last update: 2024-09-14 19:31:17 UTC


README

Laravel框架4的Eloquent ORM的自动验证智能模型。

安装

rexlu/ardent添加到composer.json的要求中(查看我们的最新稳定版本在徽章上!)

{
    "require": {
        "rexlu/ardent": "dev-master"
    }
}

使用composer update更新您的包或使用composer install安装。

您还可以使用composer require rexlu/ardent添加此包,然后指定您想要的版本(目前,dev-master是您的最佳选择)。

文档

简介

你多久会在自己构建的应用程序中重新创建相同的样板代码?这样的典型表单处理代码对你来说是否过于熟悉?

Route::post('register', function() {
        $rules = array(
            'name'                  => 'required|min:3|max:80|alpha_dash',
            'email'                 => 'required|between:3,64|email|unique:users',
            'password'              => 'required|alpha_num|between:4,8|confirmed',
            'password_confirmation' => 'required|alpha_num|between:4,8'
        );

        $validator = Validator::make(Input::all(), $rules);

        if ($validator->passes()) {
            User::create(array(
                    'name'     => Input::get('name'),
                    'email'    => Input::get('email'),
                    'password' => Hash::make(Input::get('password'))
                ));

            return Redirect::to('/')->with('message', 'Thanks for registering!');
        } else {
            return Redirect::to('/')->withErrors($validator->getMessages());
        }
    }
);

自己实现通常会带来很多重复的样板代码。作为一个额外的奖励,你的控制器(或路由处理程序)会过早地变得臃肿,你的代码会变得混乱、丑陋且难以理解。

如果有人为你做所有的重活会怎样?如果,而不是重复上面的混乱,你只需要输入这些几行代码呢?...

Route::post('register', function() {
        $user = new User;
        if ($user->save()) {
            return Redirect::to('/')->with('message', 'Thanks for registering!');
        } else {
            return Redirect::to('/')->withErrors($user->errors());
        }
    }
);

欢迎来到Ardent!

Ardent - 由魔法尘埃驱动的、手腕友好的、一站式解决方案,解决你所有的枯燥输入清理样板代码!

开玩笑的,输入验证功能很快就会变得枯燥难写和维护。Ardent通过提供自动化许多重复任务的辅助器来处理这些复杂性。

尽管Ardent非常适合输入验证,但它还会帮助你显著减少Eloquent数据模型代码。如果你发现自己疲惫不堪地一次又一次在多个单独的应用程序中编写非常相似的代码,Ardent特别有用。

例如,用户注册或博客文章提交是一个常见的编码要求,你可能希望在应用程序中实现它并再次在其他应用程序中重用它。使用Ardent,您可以一次编写您自己的自感知、智能模型,然后在其他项目中重用它们(无需或仅作很少的修改)。一旦你习惯了这种方式,你真的会想知道在没有Ardent的情况下你是如何应对的。

不再有重复的大脑损伤了!

入门

Ardent旨在扩展Eloquent基类,而不改变其核心功能。由于Ardent本身是Illuminate\Database\Eloquent\Model的派生类,因此所有你的Ardent模型都与Eloquent完全兼容,可以充分利用Laravel出色的OR/M的全部功能。

要创建一个新的Ardent模型,只需让您的模型类继承自Ardent基类。在接下来的示例中,我们将使用完整命名空间类来使示例更简洁,但鼓励您在所有类中使用use

use rexlu\Ardent\Ardent;

class User extends Ardent {}

注意:您可以自由地将您普通的Eloquent模型与Ardent的派生类混合。如果一个模型对象不依赖于用户提交的内容并且因此不需要验证,您可以将Eloquent模型类保持原样。

Ardent的轻松验证

Ardent模型使用Laravel内置的验证器类。定义模型的验证规则很简单,通常在模型类中作为静态变量完成。

class User extends \rexlu\Ardent\Ardent {
  public static $rules = array(
    'name'                  => 'required|between:4,16',
    'email'                 => 'required|email',
    'password'              => 'required|alpha_num|between:4,8|confirmed',
    'password_confirmation' => 'required|alpha_num|between:4,8',
  );
}

注意:您还可以使用数组语法定义验证规则。

当调用Ardent->save()时,Ardent模型会自动验证自身。

$user           = new User;
$user->name     = 'John doe';
$user->email    = 'john@doe.com';
$user->password = 'test';

$success = $user->save(); // returns false if model is invalid

注意:您也可以在任何时候使用Ardent->validate()方法验证模型。

检索验证错误

当Ardent模型验证失败时,将一个包含验证失败消息的Illuminate\Support\MessageBag对象附加到Ardent对象上。

使用Ardent->errors()方法或Ardent->validationErrors属性检索验证错误消息集合实例。

使用Ardent->errors()->all()检索所有验证错误。使用Ardent->validationErrors->get('attribute')检索特定属性的错误。

注意:Ardent利用Laravel的MessagesBag对象,它有一个简单且优雅的错误格式化方法

覆盖验证

有两种方法可以覆盖Ardent的验证

1. 强制保存

forceSave()验证模型,但无论是否有验证错误都会保存。

2. 覆盖规则和消息

两者Ardent->save($rules, $customMessages)Ardent->validate($rules, $customMessages)都接受两个参数

  • $rules是一个与Ardent::$rules相同形式的Validator规则数组。
  • $customMessages参数也是如此(与Ardent::$customMessages相同)

一个非空数组将仅覆盖该实例方法中指定的类为该实例指定的规则或自定义错误消息。

注意$rules$customMessages的默认值是空的数组array();因此,如果您传递一个空数组,则不会进行覆盖。

自定义验证错误消息

与Laravel验证器一样,Ardent允许您使用相同的语法设置自定义错误消息。

class User extends \rexlu\Ardent\Ardent {
  public static $customMessages = array(
    'required' => 'The :attribute field is required.',
    ...
  );
}

自定义验证规则

您可以以与Laravel验证器相同的方式创建自定义验证规则

模型钩子(自2.0以来)

Ardent在Eloquent模型事件上提供了一些语法糖:传统的模型钩子。它们是将附加操作连接到模型生命周期不同时刻的简单方法。它们可以用于在删除条目之前执行额外的清理工作、在验证发生后执行自动修复或更新更新后的相关模型。

所有返回false(特别是布尔值,而不是简单的“假”值)的before钩子将停止操作。因此,例如,如果您想在beforeSave方法中出错时停止保存,只需返回false即可,这样就不会执行保存操作,并且显然也不会调用afterSave

以下是所有可用钩子的完整列表

  • before/afterCreate()
  • before/afterSave()
  • before/afterUpdate()
  • before/afterDelete()
  • before/afterValidate() - 当返回false时将停止验证,因此使save()操作失败,因为验证是失败的。

例如,您可以使用beforeSave来散列用户密码

class User extends \rexlu\Ardent\Ardent {
  public function beforeSave() {
    // if there's a new password, hash it
    if($this->isDirty('password')) {
      $this->password = Hash::make($this->password);
    }

    return true;
    //or don't return nothing, since only a boolean false will halt the operation
  }
}

Additional beforeSave and afterSave (since 1.0)

beforeSaveafterSave可以在运行时包含。只需将闭包(以模型作为参数)传递给save()(或forceSave())方法即可。

$user->save(array(), array(), array(),
  function ($model) { // closure for beforeSave
    echo "saving the model object...";
    return true;
  },
  function ($model) { // closure for afterSave
    echo "done!";
  }
);

注意:闭包应该有一个参数,因为它将传递一个引用到正在保存的模型。

您是否曾经编写过一个拥有大量关系的Eloquent模型,却发现您的类非常杂乱,所有这些几乎与方法名称内容相同的单行代码?

在Ardent中,您可以使用数组清晰地定义您的关系及其信息,并且它们将像您在方法中定义它们一样工作。以下是一个示例

class User extends \rexlu\Ardent\Ardent {
  public static $relationsData = array(
    'address' => array(self::HAS_ONE, 'Address'),
    'orders'  => array(self::HAS_MANY, 'Order'),
    'groups'  => array(self::BELONGS_TO_MANY, 'Group', 'table' => 'groups_have_users')
  );
}

$user = User::find($id);
echo "{$user->address->street}, {$user->address->city} - {$user->address->state}";

数组语法如下

  • 第一个索引值:关系名称,可以是以下之一:hasOnehasManybelongsTobelongsToManymorphTomorphOnemorphMany,或者相关的常量(例如Ardent::HAS_MANYArdent::MORPH_ONE)。
  • 第二个索引:类名称,包含完整的命名空间。例外是morphTo关系,它不需要额外的参数。
  • 命名参数,遵循原始Eloquent方法定义的参数
    • foreignKey [可选],适用于hasOnehasManybelongsTobelongsToMany
    • tableotherKey [可选]、timestamps [布尔值,可选]和pivotKeys [数组,可选],适用于belongsToMany
    • nametypeid,由morphTomorphOnemorphMany(后两个需要定义name)使用

注意:此功能基于简单的Yii 1.1 ActiveRecord上的关系

自动填充Ardent实体

Ardent能够自动从表单输入提交中填充您的实体模型类!

让我们看看它是如何工作的。考虑以下代码片段

$user           = new User;
$user->name     = Input::get('name');
$user->email    = Input::get('email');
$user->password = Hash::make(Input::get('password'));
$user->save();

让我们调用Ardent的魔法并重写前面的代码片段

$user = new User;
$user->save();

就是这样!我们所做的只是去掉了无聊的部分。

信不信由你,上面的代码与它的较旧、但相当冗长的兄弟执行的任务本质上相同。Ardent使用用户提交的表单数据填充模型对象的属性。不再需要痛苦地尝试找出您忘记填充哪个Eloquent属性。让Ardent处理无聊的事情,而您则去做有趣的事情!它内部遵循相同的批量赋值规则,取决于$fillable/$guarded属性。

要启用自动填充功能,只需在您的模型类中将实例变量$autoHydrateEntityFromInput设置为true。但是,为了防止填充现有属性,如果您希望在更新场景中也进行自动填充,应使用$forceEntityHydrationFromInput

class User extends \rexlu\Ardent\Ardent {
  public $autoHydrateEntityFromInput = true;    // hydrates on new entries' validation
  public $forceEntityHydrationFromInput = true; // hydrates whenever validation is called
}

自动清除冗余表单数据

Ardent模型可以自动地清除冗余输入数据(例如密码确认、隐藏的CSRF _token或自定义HTTP _method字段)- 这样额外的数据就永远不会保存到数据库中。Ardent将使用确认字段来验证表单输入,然后在将模型实例保存到数据库之前谨慎地丢弃这些属性!

要启用此功能,只需在您的模型类中将实例变量$autoPurgeRedundantAttributes设置为true

class User extends \rexlu\Ardent\Ardent {
  public $autoPurgeRedundantAttributes = true;
}

您还可以清除其他字段。属性Ardent::$purgeFilters是一个数组,您可以向其中添加自定义规则。这些闭包接收属性键作为参数,并应返回false以删除应清除的属性。例如:

function __construct($attributes = array()) {
  parent::__construct($attributes);

  $this->purgeFilters[] = function($key) {
    $purge = array('tempData', 'myAttribute');
    return ! in_array($key, $purge);
  };
}

自动转换安全文本属性

假设您的模型类中有一个名为 password 的属性,但不想将明文版本存储在数据库中。最实际的做法是存储原始内容的哈希值。不用担心,Ardent 可以完全自动地为您转换任意数量的安全字段!

要实现这一点,请将属性名称添加到您的模型类中的静态数组变量 Ardent::$passwordAttributes 中,并将实例变量 $autoHashPasswordAttributes 设置为 true

class User extends \rexlu\Ardent\Ardent {
  public static $passwordAttributes  = array('password');
  public $autoHashPasswordAttributes = true;
}

Ardent 会自动将明文密码属性替换为安全的哈希校验和并保存到数据库中。它内部使用 Laravel 的 Hash::make() 方法生成哈希。

具有唯一规则的更新

Ardent 可以帮助您进行唯一更新。根据 Laravel 文档,当您更新(因此验证)具有唯一规则的字段时,您必须传入您正在更新的记录的唯一 ID。如果不传入此 ID,验证将失败,因为 Laravel 的验证器会认为这是一条重复记录。

来自 Laravel 文档

    'email' => 'unique:users,email,10'

在过去,程序员必须手动管理在运行时传递 ID 以及更改规则集以包含 ID。Ardent 不同。只需设置您的规则为 unique,调用函数 updateUniques,Ardent 就会处理其余部分。

示例

在您的扩展模型中定义您的规则

  public static $rules = array(
     'email' => 'required|email|unique',
     'password' => 'required|between:4,20|confirmed',
     'password_confirmation' => 'between:4,20',
  );

在您的控制器中,当您需要更新时,只需调用

$model->updateUniques();

如有需要,您可以在运行时将规则传递给 updateUniques,否则它将使用模型提供的静态规则。

请注意,在上面的规则示例中,我们没有告诉验证器使用哪个表或哪个字段,如 Laravel 文档中所述(例如 unique:users,email,10)。Ardent 足够聪明,能够自己找出这些信息。(感谢 GitHub 用户 @Sylph)