为 Laravel 5 的 Eloquent ORM 提供自验证智能模型

v3.6.1 2024-02-18 17:48 UTC

This package is auto-updated.

Last update: 2024-09-18 19:07:16 UTC


README

Latest Stable Version License Total Downloads Monthly Downloads Daily Downloads

为 Laravel Framework 5 的 Eloquent ORM 提供自验证智能模型。

基于 Colby Rabideau 为 Laravel 3 开发的 Aware 扩展包。

版权 (C) 2013-2015 Max Ehsan & Igor Santos

变更日志

访问我们的 发布列表。变更日志在那里制作 :)

安装

laravelbook/ardent 添加到 composer.json 中的需求(查看我们最新的稳定版本,见徽章!)

{
    "require": {
        "laravelbook/ardent": "3.*"
    }
}

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

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

(自 1.1 版本起)Laravel 之外的使用

如果您想将 Ardent 作为独立的 ORM 包使用,请在您的项目启动文件中使用以下配置(根据您的数据库更改属性)

\LaravelArdent\Ardent\Ardent::configureAsExternal(array(
  'driver'    => 'mysql',
  'host'      => 'localhost',
  'port'      => 3306,
  'database'  => 'my_system',
  'username'  => 'myself',
  'password'  => 'h4ckr',
  'charset'   => 'utf8',
  'collation' => 'utf8_unicode_ci'
), 'en'); //English is the default messages language, may be left empty

文档

简介

您在构建的应用程序中经常需要重复创建相同的样板代码吗?这种典型的表单处理代码看起来很熟悉吗?

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

        $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 - 由魔法粉末驱动的、手腕友好的、一站式解决方案,解决所有您单调的输入清理样板代码!

玩笑话 aside,输入验证功能可能会很快变得枯燥乏味。Ardent 通过提供用于自动化许多重复性任务的辅助工具来解决这些复杂性。

尽管 Ardent 对于输入验证来说很棒,但它还可以显著减少您的 Eloquent 数据模型代码。如果您发现自己反复在多个单独的应用程序中编写非常相似的代码,Ardent 特别有用。

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

让您摆脱重复的脑力劳动!

入门指南

Ardent 的目标是扩展 Eloquent 基类而不改变其核心功能。由于 Ardent 本身是 Illuminate\Database\Eloquent\Model 的后代,因此您的所有 Ardent 模型都与 Eloquent 完全兼容,并可以利用 Laravel 强大的 OR/M 全部功能。

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

use LaravelArdent\Ardent\Ardent;

class User extends Ardent {}

注意:您可以自由地将纯 Eloquent 模型与 Ardent 后代混合。如果一个模型对象不依赖于用户提交的内容,并且不需要验证,您可以保留 Eloquent 模型类不变。

使用 Ardent 轻松验证

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

class User extends \LaravelArdent\Ardent\Ardent {
  public static $rules = array(
    'name'                  => 'required|between:3,80|alpha_dash',
    'email'                 => 'required|between:5,64|email|unique:users',
    'password'              => 'required|min:6|confirmed',
    'password_confirmation' => 'required|min:6',
  );
}

注意:您也可以使用 数组语法 为验证规则指定。虽然 Laravel 文档很好,但不幸的是,5.1 之后的验证规则管道/数组语法的明确参考已经消失了。

Ardent 模型在调用 Ardent->save() 时会自动进行验证。

$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') 获取特定属性的错误。

注意:Arudent 利用 Laravel 的 MessagesBag 对象,该对象有 一种简单优雅的格式化错误的方法

覆盖验证

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

1. 强制保存

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

2. 覆盖规则和消息

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

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

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

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

自定义验证错误消息

就像 Laravel Validator 一样,Ardent 允许您使用 相同的语法 设置自定义错误消息。

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

自定义验证规则

您可以像为 Laravel Validator 创建自定义验证规则一样创建自定义验证规则。

模型钩子(自 2.0

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

所有返回false(特指布尔值,而非简单的“假”值)的before钩子将停止操作。所以,例如,如果你想在beforeSave方法中出现错误时停止保存,只需返回false,则保存将不会发生 - 显然,afterSave也不会被调用。

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

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

例如,您可以使用beforeSave来哈希用户密码(实际上,使用自动哈希会更好!)

class User extends \LaravelArdent\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
  }
}

(自1.0以来)添加了beforeSave和afterSave

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!";
  }
);

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

(自2.0以来)更简洁的关系定义

你有没有编写过一个Eloquent模型,其中包含许多关系,然后注意到你的类是多么杂乱,所有那些几乎与方法名本身相同内容的单行代码?

在Ardent中,你可以用数组干净地定义你的关系及其信息,它们将像你用方法定义它们一样工作。以下是一个示例

class User extends \LaravelArdent\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 \LaravelArdent\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 \LaravelArdent\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 \LaravelArdent\Ardent\Ardent {
  public static $passwordAttributes  = array('password');
  public $autoHashPasswordAttributes = true;
}

Ardent会自动将明文密码属性替换为安全哈希校验和,并将其保存到数据库。它内部使用Laravel的Hash::make()方法生成哈希。 注意:建议使用Eloquent的$hidden属性,即使哈希过,密码也不容易从API或类似系统中泄露出来。

如果您独立使用Ardent,可以使用Ardent::$hasher来验证字段值,例如使用User::$hasher->check($given_password, $user->password)

具有唯一规则的更新

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

来自Laravel文档

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

以前,程序员必须手动管理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)