On my User model, I have several fields that need to be populated before the record is created. I don't think this can be done using the User::$attributes property, because you can't specify a method to set a default value.
I could trigger them manually, but that's no fun, and shouldn't be necessary anyway.
The field(s) are complex in the sense that I'm using OpenSsl to generate a key-pair that gets saved to the database. The user's account uses these keys for various activities inside of the app.
So, I created a UserObserver class, and am attempting to populate those attributes using the creating hook.
However, when tinkering, I'm getting the following error when I call User::Create():
Indirect modification of overloaded property has no effect
Can anyone help me figure out the best way to make this happen?
Here is my user class:
<?php namespace App;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use Carbon\Carbon;
use Hash;
class User extends Model implements AuthenticatableContract, CanResetPasswordContract {
use Authenticatable, CanResetPassword;
const STATUS_UNCONFIRMED = false;
const STATUS_ACTIVE = true;
const ROLE_ADMIN = 42;
const ROLE_PUBLISHER = 1;
/**
* The database table used by the model.
*
* @var string
*/
protected $table = 'users';
/**
* Default values for attributes
* @var array an array with attribute as key and default as value
*/
protected $attributes = [
'status' => self::STATUS_UNCONFIRMED,
'role_id' => self::ROLE_PUBLISHER,
];
/**
* Protected attributes that CANNOT be mass assigned.
*
* @var array
*/
protected $guarded = [ 'id', 'role_id', 'status', 'remember_token' ];
/**
* The attributes excluded from the model's JSON form.
*
* @var array
*/
protected $hidden = ['password', 'role_id', 'status', 'confirmation_code', 'private_key', 'public_key', 'remember_token'];
/**
* The attributes that are represented as dates
*
* @var array
*/
protected $dates = ['last_login'];
public function setPasswordAttribute( $pass ) {
$this->attributes['password'] = Hash::make( $pass );
}
}
And here is my UserObserver (registered in the EventServiceProvider boot method per Laravel Documentation):
<?php namespace App\Observers;
use Carbon\Carbon;
class UserObserver {
private $user;
public function creating( \App\User $model )
{
$this->user = &$model;
$this->user->last_login = Carbon::now();
$this->generateKeys();
if( is_null($this->user->private_key) || is_null($this->user->public_key) )
return false;
$this->generateConfirmationCode();
if( is_null($this->user->confirmation_code) )
return false;
}
protected function generateKeys()
{
$pk_res = openssl_pkey_new( array(
'private_key_bits' => 2048,
'private_key_type' => OPENSSL_KEYTYPE_RSA
));
openssl_pkey_export($pk_res, $this->user->private_key);
$pubkey = openssl_pkey_get_details($pk_res);
$this->user->public_key = $pubkey["key"];
openssl_pkey_free($pk_res);
}
protected function generateConfirmationCode()
{
$this->user->confirmation_code = Hash::make( $this->user->email . time() );
}
}
Still learning, here, so please let me know if I got it all wrong, haha. Thanks!