Ardent
A Collections library for PHP.
I use lavarel with ardent package.
I have some problem when i want to update a row.
I have 2 model Client and Address related by morphone relation.
This relation work well, when i want to get a client this line return expected result :
Client::with('address')->find($id);
But i can't understand how to update a client with a clean solution. Somebody can answer to these questions :
- With Ardent how could you autoHydrate related model ?
- When you update some data, what is the best practice in lavarel ? Use update methdod ? Use save ? Use push ? Fill all model ? Use auto hydrate ?
When i log Input::all() in my update method i get that :
[2014-05-31 15:52:56] production.INFO: {"id":983,"firstName":"Susanne","lastName":"Adam","birthDate":"18\/06\/1982","inscriptionDate":"08\/09\/2013","status":3,"created_at":"2014-05-31 14:26:25","updated_at":"2014-05-31 14:26:25","email":"bernard.alix@free.fr","address":{"id":983,"address":"avenue Etienne","address2":"","ville":"Cordierboeuf","cp":"25 10","phone":"0403983157","mobile":"+33 (0)3 0","addressable_id":983,"addressable_type":"Client","created_at":"2014-05-31 14:27:58","updated_at":"2014-05-31 14:27:58"}} [] []
As you see address data are inside client data.
3.When I use update, save or push (eloquent's method) eloquent does not understand that he should update Address model then update related Client model. My data's format isn't well formed ?
Thanks.
UPDATE :
When i do Log::info(Input::all()), i get the following json data in my controller :
[2014-06-01 18:10:46] production.INFO: {"id":284,"firstName":"Andr\u00e9e","lastName":"Adam","birthDate":"23\/07\/1944","inscriptionDate":"22\/11\/2013","status":2,"created_at":"2014-06-01 15:41:22","updated_at":"2014-06-01 18:06:44","email":"monique17@normand.com","address":{"id":284,"streetAddress":"93, avenue Lefort","streetAddress2":"","city":"Boulay-sur-Leger","zipCode":"14054","phone":"09 51 03 1","mobile":"+33 6 00 6","addressable_id":284,"addressable_type":"Client","created_at":"2014-06-01 15:42:50","updated_at":"2014-06-01 18:06:44"}} [] []
With ardent's autohydratation that doesn't work... Client autohydrate successfully but Address does not, maybe due to the polymorphic relation (one-to-one) between them.
I try to fill my models this way :
$client = Client::with('address')->find($id);
$client->update(Input::except('address'));
$client->address->update(Input::only('address'));
but this doesn't work because Input::only('address') gives wrong formed data, when i log this i get that :
Log::info(Input::except('address'));
Log::info(Input::only('address'));
//output
[2014-06-01 18:20:34] production.INFO: {"id":284,"firstName":"Andr\u00e9e","lastName":"Adam","birthDate":"23\/07\/1944","inscriptionDate":"22\/11\/2013","status":2,"created_at":"2014-06-01 15:41:22","updated_at":"2014-06-01 18:10:46","email":"monique17@normand.com"} [] []
[2014-06-01 18:20:34] production.INFO: {"address":{"id":284,"streetAddress":"93, avenue Lefort","streetAddress2":"","city":"Boulay-sur-Leger","zipCode":"14054","phone":"09 51 03 1","mobile":"+33 6 00 6","addressable_id":284,"addressable_type":"Client","created_at":"2014-06-01 15:42:50","updated_at":"2014-06-01 18:06:44"}} [] []
So i mix two methods :
$inputs = Input::except('_method');
$client = Client::with('address')->find($id);
$client->update(Input::except('address'));
$client->address->update($inputs['address']);
This work pretty well !
But i can't understand why ardent's autohydration fails...
Thanks.
Source: (StackOverflow)
I am in the progress of making a form to edit an existing entry in the database. I am using the Form::model approach to do this, however it doesn't seem to work. The fields just stay empty.
ServerController.php
/**
* Editing servers
*/
public function edit($name)
{
$server = Server::find($name);
$keywords = ($server->getKeywords()) ? $server->getKeywords() : array();
$countries = $this->getCountries();
return View::make('server/edit', array('server' => $server, 'countries' => $countries));
}
public function update($name)
{
$server = Server::find($name);
// Did it succeed?
if($server->save()) {
Session::flash('success', 'You server was edited!');
return Redirect::route('server.view', array($name));
}
// Did not validate
if(Input::get('keywords')) {
$keywords = Input::get('keywords');
Session::flash('keywords', $keywords);
}
Session::flash('danger', "<b>Oops! There were some problems processing your update</b><br/>" . implode("<br/>", $server->errors()->all()));
return Redirect::route('server.edit', array($name))->withInput()->withErrors($server->errors());
}
The Form
{{ Form::model($server, array('route' => array('server.update', $server->name), 'class' => 'form-horizontal', 'role' => 'form', 'files' => true)) }}
<div class="form-group {{ $errors->has('email') ? 'has-error' : '' }}">
{{ Form::label('email', 'Email', array('class' => 'control-label col-md-4')) }}
<div class="col-md-4">
{{ Form::text('email', '', array('class' => 'form-control')) }}
{{ $errors->first('email', '<br/><div class="alert alert-danger">:message</div>') }}
</div>
</div>
(some more fields)
{{ Form::close() }}
Source: (StackOverflow)
I'm running though the Laravel 4 Ardent package found here:
https://github.com/laravelbook/ardent
I'm trying to integrate the code found in Ardent's README within my User Model:
public function beforeSave( $forced )
{
// if there's a new password, hash it
if($this->changed('password'))
{
$this->password = Hash::make($this->password);
}
return true;
}
My User Model Test:
public function testSetPassword()
{
// Create a new User
$user = new User;
$user->email = "joe@smalls.com";
$user->password = "password";
$user->password_confirmation = "password";
$user->save();
/* Test #1 - Test to make sure password is being hashed */
$this->assertTrue(Hash::check('password', $user->password), "the set_password() function did not return TRUE");
}
When I test via PhpUnit, it is telling me that '$this->changed()' is undefined.
BadMethodCallException: Call to undefined method Illuminate\Database\Query\Builder::changed()
I'm basically trying to do as the tutorial says, and check to make sure the password has changed before saving it to the DB. Any help would be greatly appreciated.
Source: (StackOverflow)
Is there a simpler way to use custom validation error messages in Laravel rather than listing each field and attribute in an array? I don't mind the typing, I just feel it looks rather dirty.
Here is my two blocks of code now...
public static $rules = array(
'first_name' => 'required|alpha',
'last_name' => 'required|alpha',
'email' => 'required|email',
'password' => 'required|alpha_num|min:8|confirmed',
'password_confirmation' => 'required|alpha_num'
);
public static $messages = array(
'first_name.required' => 'You must enter your First Name!',
'first_name.alpha' => 'Your first name must contain alphabetical characters only!',
'...and so on' => 'for the rest...'
);
in the public static $messages
block, I'm wondering if there's any way I can clean that up without typing each field name and attribute? Can I, for example, do something like this instead?
public static $messages = array(
'first_name' => array(
'required' => 'msg',
'alpha' => 'msg'
),
'and so on' => array(
'for the' => 'rest'
)
);
To me, that seems cleaner. Thanks for any input you can provide.
Source: (StackOverflow)
I'm using ardent to validate my User model but for some reason it's always returning the two following errors:
- The password confirmation does not match.
- The password confirmation field is required.
I've been stumped on the one for a while so any help is appreciated. Guessing it has do to with my setup or Ardent but can't figure it out. My unit tests are passing the follow test route also passes:
Route::get('testuser', function() {
$user = new User;
$user->first_name = 'John';
$user->last_name = 'Doe';
$user->birthday = '11/11/11/';
$user->email = 'johndoe@gmail.com';
$user->password = 'password';
$user->password_confirmation = 'password';
var_dump($user->save());
});
I'm not creating the user this way on form submit though. My controller action looks like this:
$user = $this->user->create(Input::all());
if ($user->save()) {
return Redirect::route('users.index')
->with('flash', 'The new user has been created');
}
return Redirect::route('register.index')
->withInput()
->withErrors($user->errors());
With the Input::all() array equalling:
array (
'_token' => 'removed',
'first_name' => 'John',
'last_name' => 'Doe',
'birthday' => '11/11/11',
'email' => 'johndoe@gmail.com',
'password' => 'password',
'password_confirmation' => 'password',
)
And finally my User model is set up like so:
class User extends Ardent implements UserInterface, RemindableInterface {
protected $table = 'users';
protected $hidden = array();
protected $fillable = array(
'email',
'first_name',
'last_name',
'birthday',
'password',
'password_confirmation'
);
protected $guarded = array('id');
public static $passwordAttributes = array('password');
public $autoPurgeRedundantAttributes = true;
public $autoHydrateEntityFromInput = false;
public static $rules = array(
'email' => 'required|email|unique:users',
'first_name' => 'required',
'last_name' => 'required',
'birthday' => 'required',
'password' => 'required|alpha_num|min:6|confirmed',
'password_confirmation' => 'required|alpha_num|min:8',
);
Source: (StackOverflow)
I'm trying to perform an .ajax get to populate a table using Knockout/Jquery in Laravel 4. I use Ardent and it keeps responding with the following json response.
{"throwOnFind":false}
Controller:
public function getData()
{
$roles = Role::select(array('roles.id', 'roles.name', 'roles.id as users', 'roles.created_at'));
return Response::json($roles, 200, array('Content-Type' => 'application/json'));
}
JavaScript:
function Role(data) {
this.id = ko.observable(data.id);
this.name = ko.observable(data.name);
this.users = ko.observable(data.users);
this.created_at = ko.observable(data.created_at);
}
function ViewModel() {
var self = this;
self.roles = ko.observableArray([]);
$.ajax({
type: "GET",
url: "{{ URL::to('admin/roles/data') }}",
complete: function(allData) {
var mappedRoles = $.map(allData, function(item) {
return new Role(item);
});
}
}, "json");
self.roles(mappedRoles);
}
ko.applyBindings(new ViewModel());
I don't really know where to go from here. I think the problem may be in Ardent.
Source: (StackOverflow)
I'm new to Laravel and am trying to figure out how to validate user input.
I have a form with several text fields, a textarea and a checkbox:
{{ Form::text('firstname', '', ['placeholder' => 'First Name', 'class' => 'form-control']) }}
{{ Form::text('lastname', '', ['placeholder' => 'Last Name', 'class' => 'form-control']) }}
{{ Form::email('email', '', ['placeholder' => 'Email', 'class' => 'form-control']) }}
{{ Form::textarea('question', '', ['placeholder' => 'Question', 'class' => 'form-control']) }}
{{ Form::checkbox('terms_and_conditions', 'yes') }}
{{ Form::label('terms_and_conditions', 'I agree to terms and conditions') }}
The validation rules are:
public static $rules = array(
'firstname' => 'required|between:2,20',
'lastname' => 'required|between: 2,30',
'email' => 'required|email',
'question' => 'required|max: 5000',
'terms_and_conditions' => 'required|accepted',
);
The text fields are all validating as expected, but I cannot get the checkbox field to validate. I echoed the json of $input to the view and can verify that the model is receiving the terms_and_conditions checkbox value, so I don't understand why it won't validate?
If I add any new fields or change a field's name those fields won't validate as well.
Am I missing something?
Source: (StackOverflow)
I started a project last night in Laravel and am using Ardent and Entrust packages to help make my User model more secure and easy to use. I have set everything up but am not able to seed my database. No errors are thrown but it is definitely not saving to my database.
This is my User model.
<?php
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
use LaravelBook\Ardent\Ardent;
use Zizaco\Entrust\HasRole;
class User extends Ardent implements UserInterface, RemindableInterface {
use HasRole;
public static $rules = array(
'username' => 'required|alpha_num|between:6,18|unique:users',
'email' => 'required|email|unique:users',
'password' => 'required|alpha_num|min:8',
'password_confirmation' => 'required|alpha_num|min:8',
'first_name' => 'alpha',
'last_name' => 'alpha',
'city' => 'alpha',
'state' => 'alpha',
'rate' => 'numeric',
'profile_pic' => 'image',
'commitment' => 'string'
);
public static $passwordAttributes = array('password');
public $autoHydrateEntityFromInput = true;
public $forceEntityHydrationFromInput = true;
public $autoPurgeRedundantAttributes = true;
public $autoHashPasswordAttributes = true;
protected $table = 'users';
protected $hidden = array('password');
public function getAuthIdentifier()
{
return $this->getKey();
}
public function getAuthPassword()
{
return $this->password;
}
public function getReminderEmail()
{
return $this->email;
}
}
This is my users
schema in my migrations.
Schema::create(
'users',
function (Blueprint $table) {
$table->increments('id');
$table->string('username');
$table->string('email');
$table->string('password', 60);
$table->string('first_name')->nullable();
$table->string('last_name')->nullable();
$table->string('city')->nullable();
$table->string('state', 2)->nullable();
$table->string('zip', 9)->nullable();
$table->float('rate', 10, 2)->nullable();
$table->boolean('listed')->default(false);
$table->string('profile_pic')->nullable();
$table->string('commitment')->nullable();
$table->timestamps();
$table->softDeletes();
}
);
Lastly, here is my seed data.
$admin = User::create(
array(
'username' => 'admin',
'email' => 'admin@example.com',
'password' => 'admin',
'password_confirmation' => 'admin',
'first_name' => 'Admin',
'last_name' => 'User',
'city' => 'Cincinnati',
'state' => 'OH',
'zip' => '45243'
)
);
User::create(
array(
'username' => 'user',
'email' => 'user@example.com',
'password' => 'user',
'password_confirmation' => 'user',
'first_name' => 'Normal',
'last_name' => 'User'
)
);
I have narrowed it down to the fact that I'm extending Ardent in my User model, but I don't know why.
Source: (StackOverflow)
I am using Ardent and I faced strange behaviour of ignoring $fillable list while inserting/updating related models.
I have the following models defined:
class User extends LaravelBook\Ardent\Ardent
{
protected $table = 'users';
public static $relationsData = [
'contacts' => [self::HAS_MANY, 'Contact'],
];
}
class Contact extends LaravelBook\Ardent\Ardent
{
protected $table = 'user_contacts';
protected $guarded = ['*'];
protected $fillable = [
'user_id',
'type',
'value'
];
public static $relationsData = [
'user' => [self::BELONGS_TO, 'User'],
];
}
Now I am trying to add new contact to user:
$user->contacts()->create([
'type' => 'some type',
'value' => 'some value',
'unknown_field' => 'unknown value'
]);
... and I got SQL insert error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'unknown_field' in 'field list' (SQL: insert into `user_contacts` (`type`, `value`, `unknown_field`, `user_id`, `updated_at`, `created_at`) values (?, ?, ?, ?, ?, ?)) (Bindings: array ( 0 => 'some type', 1 => 'some value', 2 => 'unknown value', 3 => 2, 4 => '1384854899', 5 => '1384854899', ))
In the same time this is working fine:
UserContact::create([
'user_id' => 2,
'type' => 'some type',
'value' => 'some value',
'unknown_field' => 'unknown value'
]);
I didn't get any SQL errors and 'unknown_field' was just ignored.
Any ideas why $fillable fields could be ignored while working via builder?!
Source: (StackOverflow)
I'm doing user editing facility for my admin panel. I want to ignore empty password on update, but not on create.
I have following validation rules for User model:
public static $rules = array(
'login' => 'required|max:255|alpha_dash|unique',
'displayname' => 'required|max:255|unique',
'email' => 'required|email|max:255|unique',
'password' => 'required|confirmed',
'password_confirmation' => 'required',
);
But it doesn't let me update user model when I don't pass password to it. It just complains about not having a password.
How to make it work?
Source: (StackOverflow)
I have $autoHydrateEntityFromInput = true
and $forceEntityHydrationFromInput = false
because I want the input elements not in the model rules to be dropped during hydration. If they aren't dropped, there is a "column not found" error for the model on update because some of the form fields are supplemental.
However, when these two settings are used in this way, Ardent will not update any of the fields. It will only update fields when $forceEntityHydrationFromInput = true
, which does not appear to be the functionality described in the documentation.
Am I wrong? If so, how do I get the fields auto-hydrated while excluding any not found in the rules?
I can use Ardent::$purgeFilters
to specifically exclude each supplemental field that isn't in the model, but that seems like it should be unnecessary given the documented functionality for auto-hydration.
Source: (StackOverflow)
I have a form that represents two instances of a same Address
class (let's say main address and billing address), which in turn inherits from Ardent
.
The form is defined as:
Form::model($data, ...)
where:
$data = [ 'mainAddress' => [instance A of Address],
'billingAddress' => [instance B of Address] ];
The fields in the form have names that follow an array notation, such as:
Form::text('mainAddress[zipcode]')
...
Form::text('billingAddress[zipcode')
in order to pull out both models with ease with Input::get('mainAddress')
and Input::get('billingAddress')
.
I have some problems to find a concise way to check the validation errors for both the models.
Checking both the instances is no big deal, the problem is in the view where I must display the appropriate error next to the field; in normal cases I'd use a simple $errors->has('fieldName')
, but with two instances I have problems in pulling out with ease the error message.
Note: I know that a solution would be to flatten the field names (f.ex. mainAddress_zipcode
) and define a custom ruleset that comprises the fields of both the instances, but it seems likely that I'm missing a more concise and elegant way to do this.
Source: (StackOverflow)
I'm attempting to test relationships between models using Ardent
and FactoryMuff
. I'm able to test the relationship in the belongs_to
direction, but I'm having trouble testing it in the has_many
direction.
The models I'm testing are a residential real estate rental application and it's corresponding rental history. A very simplified db schema:
+--------------+
| applications |
+--------------+
| id |
| name |
| birthday |
| income |
+--------------+
+----------------+
| history |
+----------------+
| id |
| application_id |
| address |
| rent |
+----------------+
This is my history model:
class History extends Ardent
{
protected $table = 'history';
public static $factory = array(
'application_id' => 'factory|Application',
'address' => 'string',
'rent' => 'string',
);
public function application()
{
return $this->belongsTo('Application');
}
}
This is my test to make sure that a history object belongs to a rental application:
class HistoryTest extends TestCase
{
public function testRelationWithApplication()
{
// create a test rental history object
$history = FactoryMuff::create('History');
// make sure the foreign key matches the primary key
$this->assertEquals($history->application_id, $history->application->id);
}
}
This works just fine. However, I can't figure out how to test the relationship in the other direction. In the project requirements, a rental application MUST have at least one rental history object associated with it. This is my application model:
class Application extends Ardent
{
public static $rules = array(
'name' => 'string',
'birthday' => 'call|makeDate',
'income' => 'string',
);
public function history()
{
return $this->hasMany('History');
}
public static function makeDate()
{
$faker = \Faker\Factory::create();
return $faker->date;
}
}
This is how I'm attempting to test the has_many
relationship:
class ApplicationTest extends TestCase
{
public function testRelationWithHistory()
{
// create a test rental application object
$application = FactoryMuff::create('Application');
// make sure the foreign key matches the primary key
$this->assertEquals($application->id, $application->history->application_id);
}
}
This results in ErrorException: Undefined property: Illuminate\Database\Eloquent\Collection::$application_id
when I run my unit tests. It makes sense to me. Nowhere have I told FactoryMuff
to create at least one corresponding History
object to go along with my Application
object. Nor have I written any code to enforce the requirement that an Application
object must have at least one History
object.
Questions
- How do I enforce the rule "an
application
object MUST have at least one history
object"?
- How do I test the
has_many
direction of the relationship?
Source: (StackOverflow)
Goal
I have an Ardent model called User in Laravel.
I want to have a custom validation rule called confirm_if_dirty
.
This would only run if the User->password
attribute is dirty. It would expect there to be a User->password_confirmation
field.
Below is an example of how this rule might look.
Validator::extend('confirm_dirty', function($attribute, $value, $parameters) use($model)
{
//If field is not dirty, no need to confirm.
if($model->isDirty("{$attribute}")){
//Confirmation field should be present.
if(!$model->__isset($attribute."_confirmation")){
return false;
}
//Values should match.
$confirmedAttribute = $model->getAttribute($attribute."_confirmation");
if( $confirmedAttribute !== $value){
return false;
}
//Check to see if _confirmation field matches dirty field.
}
return true;
});
Question
How can I make it so that $model in my case is passed in or is the model instance in question?
Source: (StackOverflow)
I'm doing user editing facility for my admin panel. I'm using updateUniques() in my code, as recommended by Ardent when having 'unique' rules in the model.
When I do it, it passes with no problem, but model hasn't changed.
My code:
$user = User::findOrFail($id);
if ($user->exists)
{
$user::$rules['password'] = (Input::get('password')) ? 'required|confirmed' : '';
$user::$rules['password_confirmation'] = (Input::get('password')) ? 'required' : '';
}
if ($user->updateUniques())
{
Session::flash('successes', array_merge((array) Session::get('successes'), ['Pomyślnie zmieniono użytkownika']));
return Redirect::route('users.show', ['users' => $user->id]);
}
else
{
return Redirect::route('users.edit', ['users' => $user->id])
->withErrors($user->errors())
->withInput(Input::except('password'));
}
Source: (StackOverflow)