Code Monkey home page Code Monkey logo

ardent's Introduction

Ardent

Latest Stable Version License Total Downloads Monthly Downloads Daily Downloads

Self-validating smart models for Laravel Framework 5's Eloquent ORM.

Based on the Aware bundle for Laravel 3 by Colby Rabideau.

Copyright (C) 2013-2015 Max Ehsan & Igor Santos

Changelog

Visit our Releases list. The changelog is made there :)

Installation

Add laravelbook/ardent as a requirement to composer.json (see our latest stable version on the badges!):

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

Update your packages with composer update or install with composer install.

You can also add the package using composer require laravelbook/ardent and later specifying the version you want (for now, dev-master is your best bet).

Usage outside of Laravel (since 1.1)

If you're want to use Ardent as a standalone ORM package you're invited to do so by using the following configuration in your project's boot/startup file (changing the properties according to your database, obviously):

\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

Documentation

Introduction

How often do you find yourself re-creating the same boilerplate code in the applications you build? Does this typical form processing code look all too familiar to you?

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());
        }
    }
);

Implementing this yourself often results in a lot of repeated boilerplate code. As an added bonus, you controllers (or route handlers) get prematurely fat, and your code becomes messy, ugly and difficult to understand.

What if someone else did all the heavy-lifting for you? What if, instead of regurgitating the above mess, all you needed to type was these few lines?...

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());
        }
    }
);

Enter Ardent!

Ardent - the magic-dust-powered, wrist-friendly, one-stop solution to all your dreary input sanitization boilerplates!

Puns aside, input validation functionality can quickly become tedious to write and maintain. Ardent deals away with these complexities by providing helpers for automating many repetitive tasks.

Ardent is not just great for input validation, though - it will help you significantly reduce your Eloquent data model code. Ardent is particularly useful if you find yourself wearily writing very similar code time and again in multiple individual applications.

For example, user registration or blog post submission is a common coding requirement that you might want to implement in one application and reuse again in other applications. With Ardent, you can write your self-aware, smart models just once, then re-use them (with no or very little modification) in other projects. Once you get used to this way of doing things, you'll honestly wonder how you ever coped without Ardent.

No more repetitive brain strain injury for you!

Getting Started

Ardent aims to extend the Eloquent base class without changing its core functionality. Since Ardent itself is a descendant of Illuminate\Database\Eloquent\Model, all your Ardent models are fully compatible with Eloquent and can harness the full power of Laravels awesome OR/M.

To create a new Ardent model, simply make your model class derive from the Ardent base class. In the next examples we will use the complete namespaced class to make examples cleaner, but you're encouraged to make use of use in all your classes:

use LaravelArdent\Ardent\Ardent;

class User extends Ardent {}

Note: You can freely co-mingle your plain-vanilla Eloquent models with Ardent descendants. If a model object doesn't rely upon user submitted content and therefore doesn't require validation - you may leave the Eloquent model class as it is.

Effortless Validation with Ardent

Ardent models use Laravel's built-in Validator class. Defining validation rules for a model is simple and is typically done in your model class as a static variable:

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',
  );
}

Note: you're free to use the array syntax for validation rules as well. I hope you don't mind the old Laravel docs link, but as good as Laravel documentation is, clear reference on pipe/array syntaxes for Validation rules is unfortunately gone since 5.1.

Ardent models validate themselves automatically when Ardent->save() is called.

$user           = new User;
$user->name     = 'John doe';
$user->email    = '[email protected]';
$user->password = 'test';

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

Note: You can also validate a model at any time using the Ardent->validate() method.

Retrieving Validation Errors

When an Ardent model fails to validate, a Illuminate\Support\MessageBag object is attached to the Ardent object which contains validation failure messages.

Retrieve the validation errors message collection instance with Ardent->errors() method or Ardent->validationErrors property.

Retrieve all validation errors with Ardent->errors()->all(). Retrieve errors for a specific attribute using Ardent->validationErrors->get('attribute').

Note: Ardent leverages Laravel's MessagesBag object which has a simple and elegant method of formatting errors.

Overriding Validation

There are two ways to override Ardent's validation:

1. Forced Save

forceSave() validates the model but saves regardless of whether or not there are validation errors.

2. Override Rules and Messages

both Ardent->save($rules, $customMessages) and Ardent->validate($rules, $customMessages) take two parameters:

  • $rules is an array of Validator rules of the same form as Ardent::$rules.
  • The same is true of the $customMessages parameter (same as Ardent::$customMessages)

An array that is not empty will override the rules or custom error messages specified by the class for that instance of the method only.

Note: the default value for $rules and $customMessages is empty array(); thus, if you pass an array() nothing will be overriden.

Custom Validation Error Messages

Just like the Laravel Validator, Ardent lets you set custom error messages using the same syntax.

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

Custom Validation Rules

You can create custom validation rules the same way you would for the Laravel Validator.

Model Hooks (since 2.0)

Ardent provides some syntatic sugar over Eloquent's model events: traditional model hooks. They are an easy way to hook up additional operations to different moments in your model life. They can be used to do additional clean-up work before deleting an entry, doing automatic fixes after validation occurs or updating related models after an update happens.

All before hooks, when returning false (specifically boolean, not simply "falsy" values) will halt the operation. So, for example, if you want to stop saving if something goes wrong in a beforeSave method, just return false and the save will not happen - and obviously afterSave won't be called as well.

Here's the complete list of available hooks:

  • before/afterCreate()
  • before/afterSave()
  • before/afterUpdate()
  • before/afterDelete()
  • before/afterValidate() - when returning false will halt validation, thus making save() operations fail as well since the validation was a failure.

For example, you may use beforeSave to hash a users password (actually, it would be a better idea to use auto-hashing!):

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
  }
}

Additionals beforeSave and afterSave (since 1.0)

beforeSave and afterSave can be included at run-time. Simply pass in closures with the model as argument to the save() (or forceSave()) method.

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

Note: the closures should have one parameter as it will be passed a reference to the model being saved.

Cleaner definition of relationships (since 2.0)

Have you ever written an Eloquent model with a bunch of relations, just to notice how cluttered your class is, with all those one-liners that have almost the same content as the method name itself?

In Ardent you can cleanly define your relationships in an array with their information, and they will work just like if you had defined them in methods. Here's an example:

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

The array syntax is as follows:

  • First indexed value: relation name, being one of hasOne, hasMany, belongsTo, belongsToMany, morphTo, morphOne, morphMany, or one of the related constants (Ardent::HAS_MANY or Ardent::MORPH_ONE for example).
  • Second indexed: class name, with complete namespace. The exception is morphTo relations, that take no additional argument.
  • named arguments, following the ones defined for the original Eloquent methods:
    • foreignKey [optional], valid for hasOne, hasMany, belongsTo and belongsToMany
    • table,otherKey [optional],timestamps [boolean, optional], and pivotKeys [array, optional], valid for belongsToMany
    • name, type and id, used by morphTo, morphOne and morphMany (the last two requires name to be defined)

Note: This feature was based on the easy relations on Yii 1.1 ActiveRecord.

Automatically Hydrate Ardent Entities

Ardent is capable of hydrating your entity model class from the form input submission automatically!

Let's see it action. Consider this snippet of code:

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

Let's invoke the magick of Ardent and rewrite the previous snippet:

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

That's it! All we've done is remove the boring stuff.

Believe it or not, the code above performs essentially the same task as its older, albeit rather verbose sibling. Ardent populates the model object with attributes from user submitted form data. No more hair-pulling trying to find out which Eloquent property you've forgotten to populate. Let Ardent take care of the boring stuff, while you get on with the fun stuffs!
It follows the same mass assignment rules internally, depending on the $fillable/$guarded properties.

To enable the auto-hydration feature, simply set the $autoHydrateEntityFromInput instance variable to true in your model class. However, to prevent filling pre-existent properties, if you want auto-hydration also for update scenarios, you should use instead $forceEntityHydrationFromInput:

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

Automatically Purge Redundant Form Data

Ardent models can auto-magically purge redundant input data (such as password confirmation, hidden CSRF _token or custom HTTP _method fields) - so that the extra data is never saved to database. Ardent will use the confirmation fields to validate form input, then prudently discard these attributes before saving the model instance to database!

To enable this feature, simply set the $autoPurgeRedundantAttributes instance variable to true in your model class:

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

You can also purge additional fields. The attribute Ardent::$purgeFilters is an array of closures to which you can add your custom rules. Those closures receive the attribute key as argument and should return false for attributes that should be purged. Like this:

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

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

Automatically Transform Secure-Text Attributes

Suppose you have an attribute named password in your model class, but don't want to store the plain-text version in the database. The pragmatic thing to do would be to store the hash of the original content. Worry not, Ardent is fully capable of transmogrifying any number of secure fields automatically for you!

To do that, add the attribute name to the Ardent::$passwordAttributes static array variable in your model class, and set the $autoHashPasswordAttributes instance variable to true:

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

Ardent will automatically replace the plain-text password attribute with secure hash checksum and save it to database. It uses the Laravel Hash::make() method internally to generate hash. Note: It's advised to use Eloquent's $hidden attribute so the password, even hashed, won't come out that easily if you're building an API or similar :)

In case you're using Ardent standalone, you can use Ardent::$hasher to verify the field value, using something like User::$hasher->check($given_password, $user->password).

Updates with Unique Rules

Ardent can assist you with unique updates. According to the Laravel Documentation, when you update (and therefore validate) a field with a unique rule, you have to pass in the unique ID of the record you are updating. Without passing this ID, validation will fail because Laravel's Validator will think this record is a duplicate.

From the Laravel Documentation:

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

In the past, programmers had to manually manage the passing of the ID and changing of the ruleset to include the ID at runtime. Not so with Ardent. Simply set up your rules with unique, call function updateUniques and Ardent will take care of the rest.

Example:

In your extended model define your rules

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

In your controller, when you need to update, simply call

$model->updateUniques();

If required, you can runtime pass rules to updateUniques, otherwise it will use the static rules provided by your model.

Note that in the above example of the rules, we did not tell the Validator which table or even which field to use as it is described in the Laravel Documentation (ie unique:users,email,10). Ardent is clever enough to figure it out. (Thank you to github user @Sylph)

ardent's People

Contributors

allmyitjason avatar asoorm avatar baileylo avatar bryantebeek avatar duellsy avatar dwightwatson avatar edilton avatar gg4you avatar hpetru avatar igorsantos07 avatar jaggy avatar kadivadavidak avatar laravelbook avatar lfbittencourt avatar masroore avatar modess avatar mrnomnom avatar nightowl77 avatar peterschumacher avatar pweston avatar ricardoriogo avatar samuel-cloete avatar sarunast avatar shkm avatar shrikantmeena avatar sjdaws avatar tortuetorche avatar vanadium23 avatar vasayxtx avatar wemersonrv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ardent's Issues

Labels for attributes

Mr. Ehsan, I believe it's missing the option of labels for attributes. For the moment the error messages are returning with the attribute name.

In my quick Ardent lab, I have "Your comment is required" withou Ardent validation but I'm getting "The body field is required" with Ardent.

Declaration of Zizaco\Confide\ConfideUser::save() should be compatible with Illuminate\Database\Eloquent\Model::save

Not sure what happened. Did a 'composer update':

"require": {
        "laravel/framework": "4.0.*",
        "twitter/bootstrap": "dev-master",
        "zizaco/confide": "dev-master",
        "zizaco/entrust": "dev-master",
        "jasonlewis/basset": "dev-master",
        "robclancy/presenter": "1.1.*",
        "j20/php-uuid": "dev-master",
        "bllim/datatables": "*",
        "fortawesome/font-awesome": "v3.2.1",
        "teepluss/api": "dev-master",
        "anahkiasen/former": "dev-master",
        "taylorotwell/laravel-oauth2": "dev-master"
    },

Brought my project down. Giving an error:

Declaration of Zizaco\Confide\ConfideUser::save() should be compatible with Illuminate\Database\Eloquent\Model::save(array $options = Array)

/vendor/zizaco/confide/src/Zizaco/Confide/ConfideUser.php:7

Anyone know what is going on?

Here is the log on the composer update:

Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Installing taylorotwell/laravel-oauth2 (0.2.6)
    Downloading: 100%

  - Removing symfony/translation (2.3.x-dev v2.3.1)
  - Installing symfony/translation (2.3.x-dev v2.3.2)
    Downloading: 100%

  - Removing symfony/routing (2.3.x-dev 3deda53)
  - Installing symfony/routing (2.3.x-dev v2.3.2)
    Downloading: 100%

  - Removing symfony/event-dispatcher (2.3.x-dev v2.3.1)
  - Installing symfony/event-dispatcher (2.3.x-dev v2.3.2)
    Downloading: 100%

  - Removing symfony/process (2.3.x-dev 4aafcf7)
  - Installing symfony/process (2.3.x-dev v2.3.2)
    Downloading: 100%

  - Removing symfony/debug (2.3.x-dev 947e8d4)
  - Installing symfony/debug (2.3.x-dev v2.3.2)
    Downloading: 100%

  - Removing symfony/http-foundation (2.3.x-dev 1c8466e)
  - Installing symfony/http-foundation (2.3.x-dev v2.3.2)
    Downloading: 100%

  - Removing symfony/http-kernel (2.3.x-dev 8055d68)
  - Installing symfony/http-kernel (2.3.x-dev 515d24c)
    Downloading: 100%

  - Removing symfony/finder (2.3.x-dev 71ced0f)
  - Installing symfony/finder (2.3.x-dev v2.3.2)
    Downloading: 100%

  - Removing symfony/dom-crawler (2.3.x-dev c8f8f06)
  - Installing symfony/dom-crawler (2.3.x-dev v2.3.2)
    Downloading: 100%

  - Removing symfony/css-selector (2.3.x-dev e3aa249)
  - Installing symfony/css-selector (2.3.x-dev v2.3.2)
    Downloading: 100%

  - Removing symfony/console (2.3.x-dev 251dd20)
  - Installing symfony/console (2.3.x-dev v2.3.2)
    Downloading: 100%

  - Removing symfony/browser-kit (2.3.x-dev 1d2e681)
  - Installing symfony/browser-kit (2.3.x-dev v2.3.2)
    Downloading: 100%

  - Removing laravelbook/ardent (dev-master 2d1d70e)
  - Installing laravelbook/ardent (dev-master 5a24787)
    Downloading: 100%

Any and all help GREATLY appreciated!

Information on how to use Ardent without the complete Laravel framework

I was looking for a decent AR implementation to use with my standalone REST server, and was thinking about using Eloquent when discovered Ardent and that in fact all the Laravel components are under Illuminate's repositories. So far, so good.

However, I couldn't find anywhere how to configure the database connections to be used by Ardent/Eloquent. The only information I got was to create a config/database.php file, but how should I use it to configure the library?

Error when testing or migrating

Guys, after I've changed my model User to extend Ardent, I'm getting the following error when trying to run tests or migrate something:

PHP Fatal error:  Call to a member function flashInput() on a non-object in /Applications/MAMP/htdocs/project/vendor/laravel/framework/src/Illuminate/Http/Request.php on line 286

And here is my model: http://paste.laravel.com/gkB

Any help?

Thanks

RFC: implementation of more traditional AR patterns

I started using Ardent now and noticed some changes in the common AR pattern followed by some Ruby implementations and the Yii's AR itself.
I'm willing to implement those in Ardent, but before I would like some opinion on this. Here I list my ideas:

  • Having all before/after methods, like before/afterSave (as we have already) but also before/afterDelete, before/afterInsert and before/afterUpdate
  • Having an easier way to define relations. If my model have five relations, having five new methods are just a waste of lines with something that could be much more simplified. An idea would be having a property (like static $rules) with the relation details, including the classname and relation type (as Eloquent uses already). Something like: static $relations = [ 'definitions' => ['hasMany'], 'user' => ['hasOne'] ]
  • Would also be nice to have a way to throw an exception on invalid models, just like we get exceptions with findOrFail. I would guess that properties would be a nice way to configure this as well (both for validation and find exceptions). They are very useful for hierarchical systems built on top of try..catch laces.

How to not automatically update a field on save?

For example, when an user update his profile the password is not mandatory.
Right now I'm doing like this:

/* In User Model:
public $autoPurgeRedundantAttributes = true;
public static $passwordAttributes    = array('password');
public $autoHashPasswordAttributes   = true;
*/

$user = User::find($id)

$password = Input::get('password', false);

if ( ! $password) {
    $user->autoHashPasswordAttributes = false;
    $user->password_confirmation = $user->password;
} else {
    $user->password = $password;
    $user->password_confirmation = Input::get('password_confirmation');
}

Is there a better way to handle this scenario?

ErrorException for Ardent::beforeSave / afterSave listeners

I am using Ardent models with the latest build of Laravel 4.0.*. After my composer update today, the Ardent model listeners do not seem to work any more:

call_user_func_array() expects parameter 1 to be a valid callback, non-static method Club::beforeSave() should not be called statically

Has anyone else encountered this issues?

Can't access errors()

My model class extends Ardent.

var_dump($this->validationErrors);

results in:

object(Illuminate\Support\MessageBag)[220]
  protected 'messages' => 
    array (size=1)
      'title' => 
        array (size=1)
          0 => string 'The title field is required.' (length=28)
  protected 'format' => string '<span class="help-inline">:message</span>' (length=41)

I'm on the L4 build as of 3-4 days ago. Can't call $this->errors() either in my model class that extends Ardent.

Mass Assignment

Hi,

How does Ardent handle mass assignment?

Specifically - if I "Automatically Hydrate Ardent Entities" - does that have some ability to whitelist/blacklist certain fields?

Error with Eloquent Methods

When trying to call an Eloquent method I get a call to undefined method error for example:

class Blog extends Ardent {

}

then

Blog::orderBy('date', 'DESC')->paginate(15);
or
Blog::get();

orderBy is not defined, this is the same for all query methods I've tried.

Is it because Ardent is extending Model, however when we create models and want to make use of the Eloquent magic we extend Eloquent instead?

Laravel 4.1 compatibility

Is it save to assume that ardent is working with the new L 4.1 release? If yes, can we just update the composer file?

[Bug] Ardent object not serializable

I noticed that when trying to serialize an Ardent model I get an error:
Serialization of 'Closure' is not allowed

Basically the cause is the purgeFilters property is being set to a Closure in the constructor.

Would be great if it can be fixed ;)

Cheers,

Bryan te Beek

Autohydrate with no rules

I might be doing something wrong but if I am trying to use autohydrate rather than assign attributes from the input array. This is fine provided the attributes have validation rules but in the instance where a field isn't required, the value from the input array is not assigned and saved. I've tried setting an empty validation rule for these fields but still the same - the only way I can get the data to save is by disabling autohydrate and assigning attributes manually.

Ardent redeclaring Model

When installing Ardent via composer with Laravel 4.

PHP Fatal error: Cannot redeclare class Illuminate\Database\Eloquent\Model in PHP Fatal error: Cannot redeclare class Illuminate\Database\Eloquent\Model in /home/sam/laravel4/bootstrap/compiled.php on line 8059

Related to laravel/framework#608

OnDelete hooks for related tables

Would be useful to have a property like:

public static detatchOnDelete = ['relation1', 'relation2'];

This could help developers avoid to have to write beforeDelete methods to erase pivot records. It could maybe be expanded to work on direct relations as well, but the need of this should be verified before.

When Setting autoHydratedEntityFormInput to true non required fields are not saved

When setting $autoHydrateEntityFromInput = true; non required fields in the $rules array are not saved.

Table Structure:

Category Table
-- title
-- description

Model $rules array:

/**
 * Ardent validation rules
 *
 * @var array
 */
public static $rules = array(
  'title'       => 'required'
);

Controller Store Action

/**
 * Store a newly created resource in storage.
 *
 * @return Response
 */
public function store()
{
    $category = new Category;

    if( $category->save() ){
        return Api::response(201, 'Category Created Sucessfully', $category);
    }

    // Get validation errors (see Ardent package)
    $error = $category->errors()->all();

    return Api::response(500, $error);
}

The above saves only the title input because it's the only required field.

After setting $autoHydrateEntityFromInput = false; and changing my controller to the following it works as expected:

/**
 * Store a newly created resource in storage.
 *
 * @return Response
 */
public function store()
{
    $category = new Category(Input::all());

    if( $category->save() ){
        return Api::response(201, 'Category Created Sucessfully', $category);
    }

    // Get validation errors (see Ardent package)
    $error = $category->errors()->all();

    return Api::response(500, $error);
}

undefined method Illuminate\Support\MessageBag::getResults()

Model:

<?php namespace Simple\Blog\Models;

use LaravelBook\Ardent\Ardent;

class Post extends Ardent
{
    //Table name
    protected $table = 'posts';

    public $autoHydrateEntityFromInput = true;

    public static $rules = array(
        'reference' => 'required|numeric',
    );

    public function author()
    {
        return $this->belongsTo('Simple\User\Models\User', 'author_id');
    }

    public function category()
    {
        return $this->belongsTo('Simple\Blog\Models\Category', 'category_id');
    }
}
?>

Controller:

  public function update($id)
  {
    //Grab the Blog post
    $post = Post::where('id', '=', $id)->first();

    //Blog Post validates and updates ok
    if ($post->save())
    {
      return Redirect::action('Simple\Blog\Controllers\AdminController@index')
        ->with('message-type', 'success')
        ->with('message-content', 'Successfully updated '. Input::get('reference') .'!')
      ;
    }
    //Blog Post failed to validate..
    else
    {
      return Redirect::action(
        'Simple\Blog\Controllers\AdminController@edit', array($id))
        ->withInput()
        ->withErrors($post->errors)
      ;
    }
  }

I get this when my input fails validation:

FatalErrorException: Error: Call to undefined method Illuminate\Support\MessageBag::getResults() in /path/to/laravel/bootstrap/compiled.php line 9186

Line 9186:

public function getAttribute($key)
{
...
$relations = $this->{$key}()->getResults();
...
}

If everything validates it carries on to the list page, although it doesn't actually update the row...

Thoughts? Something to do the fact that I am using it from within a package?

BadMethodCallException: Method [validateMatch] does not exist.

I am getting this issue when calling Ardent->save() or ->validate().

Model:

<?php namespace Vendor\Package\Models;

use LaravelBook\Ardent\Ardent;

class Post extends Ardent
{
    protected $table = 'posts';

    //Ardent Values
    public $autoHydrateEntityFromInput = true;

    public static $rules = array(
        'id' => 'numeric',
        'reference'  => 'required|match:/^[a-zA-Z0-9 \/&-\(\)]+$/|between:5,70',
        'title'  => 'required|match:/^[a-zA-Z0-9 \/&-\(\)]+$/|between:5,70',
        'description' => 'required|between:5,170',
        'content' => 'required|min:20',
        'status' => 'in:1,0',
    );

    public function author()
    {
        return $this->belongsTo('Vendor\Package\Models\User', 'author_id');
    }

    public function category()
    {
        return $this->belongsTo('Vendor\Package\Models\Category', 'category_id');
    }
}

?>

Controller:

  public function update($id)
  {
    //Grab the Blog post
    $post = Post::where('id', '=', $id)->first();

    //Set the various values for the updated Blog Post
    $post->category_id = Input::get('category_id');
    $post->reference = Input::get('reference');
    $post->title = Input::get('title');
    $post->description = Input::get('description');
    $post->slug = Input::get('slug');
    $post->content = Input::get('content');
    $post->status = Input::get('status');

    //Blog Post validates and updates ok
    if ($post->save())
    {
      return Redirect::action('Vendor\Package\Controllers\AdminController@index')
        ->with('message-type', 'success')
        ->with('message-content', 'Successfully updated '. Input::get('reference') .'!')
      ;
    }
    //Blog Post failed to validate..
    else
    {
      return Redirect::action(
        'Vendor\Package\Controllers\AdminController@edit', array($id))
        ->withInput()
        ->withErrors($post->errors)
      ;
    }
  }

Any ideas?

Migration issue

Hi guys, I've created a User model that extends Ardent, it's working perfectly.

However in my user migration, I do an insert after creating the table, and after I've changed the model to extend Ardent, I'm getting an error:

Symfony\Component\HttpKernel\Exception\FatalErrorException">FatalErrorException: Error: Class 'Ardent' not found in /Applications/MAMP/htdocs/project/app/models/User.php line 5

When I change back to extend Eloquent, it works.

Oh, and no, I won't using the Seed feature for this, because it doesn't support relationships. So I'll really appreciate if you guys take a look at this.

Thanks !

How to use Ardent to hydrate form entry and perform update?

This isn't an issue as such but wasn't sure where to post for help. I've been playing with Ardent, it's great. I like that you can create a new model and autohydrate from a form.

However, what I'd like to do is use the same form for a creation or update of a model. Can I use Ardent and autohydration for the model update?

I can't figure out how to do it. If I use the $var = new Model; syntax then save it creates a new record in the database.

If I try assigning the id I'd like to update first by adding $var->id = 18; (for example) it complains about the other fields for the model being missing.

If doing an database update from form submission do I have to manually assign all fields using Input->get() then do save() ?

[Feature request] remove Input::get('input_method')

This might be a silly enhancement, but as I use a hidden text input "_method" to ensure the correct routing to the new Resource Controllers available in L4 [public function update($id)], it would be nice to have removed those inputs automatically from the save method.
At the moment I do it manually with the beforeSave closure, which works fine, but isn’t very nice.

Updated unique fields

I must say that I'm a huge fan of Ardent. Just started playing around with it today and it's been a breeze!

The only issue I've run into is updating models when there is a unique field (for example, email address). When I attempt to save the model without updating the unique field, I get an error stating that there is a duplicate in the database. I'm likely doing something wrong, but is there a way to update models that have unique fields w/out doing a force save?

Ardent Save method differs to Eloquent Model?

I'm wondering if as per E_STRICT, the Ardent.php save method should match it's parent save method in Eloquent model?

Or is it different because it's an abstract class or some other reason?

I've been told that Laravel enforces the full error reporting level, which in PHP 5.4 includes E_STRICT.

Apologies if i've misunderstood something.

Purge Redundant Data not working?

Hi

I'm hoping this isn't just me, I've tried to follow instructions (new to Ardent). I have a simple form:

        <label for="name">Course Name</label>               <input name="name" type="text" id="name">               <label for="town">Course Town</label>               <input name="town" type="text" id="town">               
            <label for="par">Par</label>                <input name="par" type="text" id="par">         
            <label for="manager">Manager</label>                <input name="manager" type="text" id="manager"> 
            <label for="pro">Pro</label>                <input name="pro" type="text" id="pro"> 
            <input type="submit" id="login-button" class="radius small button" value="Submit" />    

I want to validate the 'pro' field but not submit it. I have the following code in my model:

class GolfCourse extends Ardent {

public static $rules = array(
'name' => 'required|between:4,16',
'town' => 'required|between:4,7',
'par' => 'required|numeric',
'pro' => 'required|between:3,10'
);

//Automatically get variables from form input
public $public $autoHydrateEntityFromInput = true;= true;

//Allow variables to be validated but don't save unnecesary variables to database
public $autoPurgeRedundantAttributes = true;    

//Don't allow mass assignment of these variables
protected $guarded = array('id');  

}

But upon calling save() I get a message saying the it's trying to insert the 'pro' field which doesn't exist on the database. I have $public $autoHydrateEntityFromInput = true; set to true so I thought this would stop the 'pro' field being inserted?

Uniqueness

Since validation rules are declared as static, it is not possible to use instance variables to validate models for uniqueness?

When updating a user for example, you want to ignore uniqueness for the user being updated. You can do this by specifying the ID of the model to ignore. Otherwise the validation rules will fail as the user you are updating has the same email address as the user you are updating.

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

By using a Validator service you can pass an instance of the model into a method and return a validator object for that model which you can check on save.

namespace Models\Services\Validators;

use Models\User;
use Validator;

class UserValidator {

    public static function getValidator(User $user) {
        $rules = [
            'first_name'  => 'required|max:50',
            'last_name'   => 'required|max:50',
            'email'       => "required|max:100|email|unique:users,email{$user->id}"
        ];

        return Validator::make($user->toArray(), $rules);
    }

}

You can't do this with a static variable on a model.

// This will fail if you are updating an existing user.
public static $rules = array(
    'email' => 'required|email|unique,users,email',
);

What's the usage of before and afterSave as arguments in save method?

I was wondering if there's any difference between:

  1. running code, calling save inside an if-clause and running more code after
  2. running save with before and afterSave closures as arguments

The number 2 looks more like a non-standard way to add hooks that are hardly (IMHO) different between situations where save() would be called. Thus, we could drop those arguments in favor of a cleaner codebase and less confusion (since now with actual, instance before/afterSave methods, both signatures are different and one does not override the other anymore).

Save method fails if not all input fields are in validation rules

Perhabs I'm missing something or I'm just to stupid ;-)
If I do not have all fields in the rules set, then I'm not able to store the data. Also my password_confirmation validation did fail.

My solution was quite simple, but I'm not sure if it is correct.
I just added $this->attributes = Input::all(); on line 139. Afterwards everything seems to work as expected. I have used the latest commit (49395b2)

Using password_confirmation when manually assigning value

I have something like this:

if (!empty($data['password'])){
$this->password = Hash::make($data['password']);
$this->password_confirmation = Hash::make($data['password_confirmation']);
}
$this->save();

When saving, I am always getting an error "The password confirmation does not match."
I am using "confirmed" rule for the password field.
Any ideas?

Thanks

Test Coverage

I'd like to see some test coverage for Ardent. Has anyone written any tests for it already?

Dynamic rules?

Hi,

Is there a way to define model rules dynamically?

For example, a product has a regular and retail price. When both entered, retail price cannot be less than regular price:
'retail_val' => 'required|numeric|min:'.$input['deal_val'],
'deal_val' => 'required|numeric|min:1',

How do I do something like this?

Also, user can manipulate products, but different rules apply for a regular user and admin.

Any help?
Thanks!

[Proposal] Auto hydration when updating a row doesn't work

Because of this part of the class Ardent.php :

if ( empty( $this->attributes ) && $this->autoHydrateEntityFromInput ) {
// pluck only the fields which are defined in the validation rule-set
$this->attributes = array_intersect_key( Input::all(), $rules );
}

We aren't able to auto hydrate a existing row because $this->attributes is not empty. I wondered if it would be possible to add a property to force a merge between the existing values ​​and those from Input :: all ();

Automatically Hydrate Ardent Entities not working

To use the auto hydrate i have to manually pass the validation rules to the save method.
Auto hydrate ignore static rules set in the model.
The rules overrides should append before the auto hydrate logic.

conflict with illuminate

error: Strict Standards: Declaration of LaravelBook\Ardent\Ardent::save() should be compatible with Illuminate\Database\Eloquent\Model::save(array $options = Array) in C:\xampp\htdocs\enarocanje\vendor\laravelbook\ardent\src\LaravelBook\Ardent\Ardent.php on line 25

can you help me with this? i get this error when i run server or go to any page

Fatal error thrown on artisan db:seed following latest commit

Just updated and I now get an error which seems to be down the commit that's just been sent up (5a24787):

PHP Parse error: syntax error, unexpected '[' in /Sites/foo.com/source/vendor/laravelbook/ardent/src/LaravelBook/Ardent/Ardent.php on line 704
{"error":{"type":"Symfony\Component\Debug\Exception\FatalErrorException","message":"syntax error, unexpected '['","file":"/Sites/foo.com/source/vendor/laravelbook/ardent/src/LaravelBook/Ardent/Ardent.php","line":704}}

I'm running php 5.3, which was fine before this commit and the following seed class:

delete(); User::create(array( 'email' => '[email protected]', 'password' => Hash::make('password') )); User::create(array( 'email' => '[email protected]', 'password' => Hash::make('password'), 'first_name' => 'Foo', 'last_name' => 'Bar' )); User::create(array( 'twitter_uid' => 1 )); User::create(array( 'facebook_uid' => 1 )); } ``` }

Using $this when not in object context

I have the following save action:

    public function postRegister()
    {
            $user = new User();

        if ($user->save()) {

            return 'User created!';

        }
        else
        {

            return 'Validation Failed!';
        }
    }

And the following model

<?php

use LaravelBook\Ardent\Ardent;

class User extends Ardent {

    public static $passwordAttributes = array('password');

    public $autoHydrateEntityFromInput = true;
    public $autoPurgeRedundantAttributes = true;
    public $autoHashPasswordAttributes = true;

    public static $rules = array(

        'email' => 'required|email',
        'password' => 'required|alpha_num|confirmed',
        'password_confirmation' => 'required|alpha_num',
    );

}

I'm getting the following error

FatalErrorException: Error: Using $this when not in object context in /Users/shealan/Sites/Blah/vendor/laravelbook/ardent/src/LaravelBook/Ardent/Ardent.php line 263

Eloquent::create() and update() methods not working

Eloquent::create() and Eloquent::update() methods not working when using Ardent as a base model.

Here's an example

/**
     * Store a newly created resource in storage.
     *
     * @return Response
     */
    public function store()
    {
        $category = Category::create(Input::all()); 

        if( $category ){
            return Api::response(201, 'Category Created Sucessfully', $category);
        }

        // Get validation errors (see Ardent package)
        $error = $category->errors()->all();

        return Api::response(500, $error);
    }

The above returns success while when checking the database the tuple wasn't created.

See Zizaco/confide#58

"Select" doesn't work

Using Ardent, method select eloquent or query builder doesnt work

example:
User::select('id', 'nome') or
DB::table('users')->select('id', 'nome')

result: id, nome, email, active, etc all fields

echo $users->toSql() = "Select * from users"

Issues with beforeSave()

I'm experiencing issues with beforeSave based upon the documentation in the README. When using this, based upon the example code, I receive the below error:

public function beforeSave($forced)
{
    if ($this->changed('slug'))
    {
        $this->slug = Str::slug($this->name);
    }

    return true;
}

Results in this error:

Declaration of Country::beforeSave() should be compatible with LaravelBook\Ardent\Ardent::beforeSave($forced = false)

I then updated the code to match that footprint, as so:

public function beforeSave($forced = false)
{
    if ($this->changed('slug'))
    {
        $this->slug = Str::slug($this->name);
    }

    return true;
}

Now, I get this error:

Call to undefined method Illuminate\Database\Query\Builder::changed()

I've run composer update just to check I'm up-to-date but still having the same issue.

Not Working

I'm sure I'm just missing something here, but I can't seem to figure out why I can't seem to make Ardent work properly.

Regardless of what rules I set, the validation always passes. Have you made any changes in recent commits that might have changed the way we should interact with Ardent?

For example:

<?php

use LaravelBook\ardent\Ardent;

class Post extends Ardent {
    public $timestamps = false;

    public static $rules = array(
        'title' => 'required'
    );

}

And then a test to see if it saves:

Route::get('/', function()
{
    $post = new Post;
    var_dump($post->save()); // true
});

Why is that returning true??

Packagist version

I believe it's time for an update in the versions, since 1.0.3 isn't compatible with Laravel 4 and it's the latest stable version.

When #65 got merged it broke my application since I'm extending Ardents save() in my base model and the new declaration made it break.

I'm just happy right now that my CI server caught it before it could do any damage :)

Problem when creating a rule in beforeSave

I don't know if it is the best way to do it, but since I need to pass a date to the 'after' validation, I'm doing this:

public function beforeSave( $forced = false ) {

    if(!empty($this->final_date)) {
        static::$rules['final_date'] = 'date_format:Y-m-d|after:' . $this->initial_date;
    }

    return true;
}

But this validation isn't working, take a look at the screenshot:

Screen Shot 2013-03-20 at 22 57 41

(I've put print_r(static::$rules); at the end of beforeSave(); method to do this print)

Am I doing it wrong? How can I accomplish this?

Thanks a lot !

Ardent doesn't validate when using autoHydrateEntityFromInput

I created a simple User object that has autoHydrateEntityFromInput=true. I tested with no input at all, and then I then called save() on this object. None of the validation on the object seemed to trigger, and result was true.

I then set one attribute on this object manually before calling save. This did trigger the validation rules on save.

I next tried passing in one of the fields via Input that should of validated to true, but it seems to be getting auto-hydrated into the object as intended. Something is definitely not quite right here.

Ardent defined as abstract throws error with Artisan db:seed

Although things seem to be working fine with normal use in controllers etc, but as soon as I try to use Ardent objects in a seed process with db:seed I get the error:

<span>1/1</span> <abbr title="Symfony\Component\HttpKernel\Exception\FatalErrorException">FatalErrorException</abbr>: Error: Cannot instantiate abstract class LaravelBook\Ardent\Ardent in /Volumes/Users/rhuk/Projects/git/l4-timeslice/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php line 1451

When i remove the "abstract" keywords from the Ardent class definition things work fine again.

Error at the docs

Hi guys, I guess there's a error on the docs at this line:

Retrieve the validation errors message collection instance with Ardent->errors() method or Ardent->validationErrors property.

I wasn't able to use the method Ardent->errors() (method undefined).

I guess that this method would be the getErrors(), or am I missing something?

Bye.

Installation with Illuminate 4.1

When trying to install ardent under Illuminate 4.1 i get the following errors:

Your requirements could not be resolved to an installable set of packages.

Problem 1
- Installation request for laravelbook/ardent dev-master -> satisfiable by l
aravelbook/ardent[dev-master].
- Conclusion: remove laravel/framework 4.1.x-dev
- laravelbook/ardent dev-master requires illuminate/support 4.0.x -> satisfi
able by laravel/framework[4.0.x-dev, v4.0.0, v4.0.0-BETA2, v4.0.0-BETA3, v4.0.0-
BETA4, v4.0.1, v4.0.2, v4.0.3, v4.0.4, v4.0.5], illuminate/support[4.0.x-dev, v4
.0.0, v4.0.0-BETA2, v4.0.0-BETA3, v4.0.0-BETA4, v4.0.1, v4.0.2, v4.0.3, v4.0.4,
v4.0.5].
- Can only install one of: laravel/framework[4.1.x-dev, 4.0.x-dev].
- Can only install one of: laravel/framework[v4.0.0, 4.1.x-dev].
- Can only install one of: laravel/framework[v4.0.0-BETA2, 4.1.x-dev].
- Can only install one of: laravel/framework[v4.0.0-BETA3, 4.1.x-dev].
- Can only install one of: laravel/framework[v4.0.0-BETA4, 4.1.x-dev].
- Can only install one of: laravel/framework[v4.0.1, 4.1.x-dev].
- Can only install one of: laravel/framework[v4.0.2, 4.1.x-dev].
- Can only install one of: laravel/framework[v4.0.3, 4.1.x-dev].
- Can only install one of: laravel/framework[v4.0.4, 4.1.x-dev].
- Can only install one of: laravel/framework[v4.0.5, 4.1.x-dev].
- don't install illuminate/support 4.0.x-dev|don't install laravel/framework
4.1.x-dev
- don't install illuminate/support v4.0.0|don't install laravel/framework 4.
1.x-dev
- don't install illuminate/support v4.0.0-BETA2|don't install laravel/framework 4.1.x-dev
- don't install illuminate/support v4.0.0-BETA3|don't install laravel/framework 4.1.x-dev
- don't install illuminate/support v4.0.0-BETA4|don't install laravel/framework 4.1.x-dev
- don't install illuminate/support v4.0.1|don't install laravel/framework 4.1.x-dev
- don't install illuminate/support v4.0.2|don't install laravel/framework 4.1.x-dev
- don't install illuminate/support v4.0.3|don't install laravel/framework 4.1.x-dev
- don't install illuminate/support v4.0.4|don't install laravel/framework 4.1.x-dev
- don't install illuminate/support v4.0.5|don't install laravel/framework 4.1.x-dev
- Installation request for laravel/framework 4.1.* -> satisfiable by laravel/framework[4.1.x-dev].

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.