I need to guard the ID column when inserting into a database, however I don't want to guard it when inserting into a different database due to needing to manually set the ID, so that the tables are in sync.
However I can't figure out a way to do it, below is what I have got at the moment, however this doesn't work at all as I just get an error:
Field 'id' doesn't have a default value
This is my current model:
<?php
namespace App\Models\Seasonal;
use Illuminate\Database\Eloquent\Model;
class SeasonalBanner extends Model
{
protected $connection = 'dev';
protected $guarded = [ 'id' ];
protected $appends = [ 'period' ];
public static function boot()
{
parent::boot();
self::creating(function($model){
if ($model->connection === 'live') {
$model->guarded = [];
}
});
}
public function dates() {
return $this->hasMany(SeasonalBannerDates::class);
}
public function getPeriodAttribute() {
return [ $this->start, $this->end ];
}
}
The best way in my opinion is not to use $guarded at all in such case. Just set:
protected $guarded = [];
and in your code depending on which database you use, either fill id or not.
model user
protected $table = "users";
protected $fillable = ['name', 'email', 'password' ];
protected $hidden = [
'password', 'remember_token',
];
public function solicitud(){
return $this->hasMany('App\solicitud');
}
Model tiposolicitud
protected $table = "tiposolicitud";
protected $fillable = ['nombre'];
public function solicitud(){
return $this->hasMany('App\solicitud');
}
Model solicitud ( principal )
protected $table = "solicitud";
protected $fillable = [..extract... 'tiposolicitud_id','users_id'....];
public function tiposolicitud(){
return $this->belongsTo('App\tiposolicitud');
}
public function User(){
return $this->belongsTo('App\User');
}
Controller ( extract)
use App\solicitud as VarModel;
use App\User;
use App\tiposolicitud ;
...
public function index()
{
$var1 = VarModel::all();
return view('private.solicitud.index',compact('var1'));
}
index.php
#foreach ($var1 as $var)
<tr>
<td>{{$var->id}}</td> // OK
<td>{{$var->user->name}}</td> //NOT OK
<td>{{$var->tiposolicitud}}</td> // OK
Trying to get property of non-object (View: C:\wamp64\www\issdgr\resources\views\private\solicitud\index.blade.php)
I have problem with app / user
I have persisted the id of the user but I can not find the name ..
HELP!!!!!
The error is on your blade view with the following statement:
$var->id
I think its a multi-dimension Std Class Object. So before iterating, put a print_r() to check the content of it.
And one more thing, laravel maintain cache of all views inside
your_project/storage/framework/views
with name like 2b026073a4c3afa6c3599efffe5361a356c89d88.php that's why it is showing error here.
In Laravel 5.4 when I try to save User model to the database the values are not saved. I've set the fillable property as well.
It was working in Laravel 5.3. This issue is coming after upgrading the application into Laravel 5.4.
Below is a User model.
class User extends BaseModel implements AuthenticatableContract, CanResetPasswordContract, JWTSubject
{
use SoftDeletes,
UserAccess,
UserAttribute,
UserRelationship,
Authenticatable,
CanResetPassword,
Notifiable;
/**
* Database Table
*
* #var string
*/
protected $table = "users";
/**
* The attributes that are not mass assignable.
*
* #var array
*/
protected $guarded = ['id'];
/**
* Fillable Form Fields
*
* #var array
*/
protected $fillable = [
'name',
'first_name',
'last_name',
'email',
'password',
'status',
'confirmed',
'api_user',
'confirmation_code',
'account_id',
'role_id',
'cw_contact_id',
'all',
'all_locations',
'username',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = ['password', 'remember_token'];
/**
* Select HTML Preference
*
* #var string
*/
protected static $selectHTMLFormat = "[email]";
/**
* #var array
*/
protected $dates = ['deleted_at', 'last_login'];
}
Please note the issue is with User Model only.
I'm saving User as below.
// Create User
$user = $this->model->create([
'first_name' => $input['first_name'],
'last_name' => $input['last_name'],
'username' => $input['username'],
'email' => $input['email'],
'password' => bcrypt($input['password']),
'confirmation_code' => md5(uniqid(mt_rand(), true)),
'confirmed' => 1,
'api_user' => (isset($input['api_user']) ? $input['api_user'] : 0),
'account_id' => $input['account_id'],
'role_id' => (isset($input['role_id']) ? $input['role_id'] : 0),
'all' => (!isset($input['associated-permissions']) || $input['associated-permissions'] == 'all') ? 1 : 0,
'status' => (!isset($input['status']) || $input['status'] ? 1 : 0),
'all_locations' => $input['all_locations']
]);
Then the create method of BaseModel will be called and below is the code of it.
public static function create(array $attributes = Array())
{
$user = access()->user();
if($user)
{
$attributes['account_id'] = (!isset($attributes['account_id']) ? $user->account->id : $attributes['account_id'] );
}
$childClass = get_called_class();
$model = new $childClass;
$model->runActionLogger(false, 'create');
return parent::query()->create($attributes);
}
The reason is most probably the new middleware in Laravel 5.4 called "Request Sanitization Middleware" as explained in https://laravel.com/docs/5.4/releases.
Disable \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, in app/Http/kernel.php and see what you get.
You can also check in /config/database.php and your mysql connection settings: 'strict' => true, if so, set to false.
A good practice is using the model for user input. In this case, instead of $user = $this->model->create(...) populate you model with
$user = new \App\User($input) and update your values from there, f.ex.
$user->confirmation_code = md5(uniqid(mt_rand(), true)); and
$user->password = bcrypt($user->password);
If fields are nullable, indicate as such in your migration file, f.ex. $table->string('all')->nullable();
If done just run $user->save();
From 5.4 the create() function is not more defined in Illuminate\Database\Eloquent\Model:
Is handled as dinamic method call, that is by calling one of these functions (dependig on if it's called statically or not):
public static function __callStatic($method, $parameters)
// or
public function __call($method, $parameters)
In the Illuminate\Database\Eloquent\Model class.
Now I dont have all your code but, IMHO, I will try to change this line in your BaseModel class:
return parent::query()->create($attributes);
to this:
return $model->create($attributes);
or, even better for me, to this:
return (new static)->newQuery()->create($attributes);
In the
documentation
it says:
$post = App\Post::find(1);
$comment = $post->comments()->create([
'message' => 'A new comment.',
]);
So
$user = $this->users()->create([
'first_name' => $input['first_name'],
'last_name' => $input['last_name'],
'username' => $input['username'],
'email' => $input['email'],
'password' => bcrypt($input['password']),
'confirmation_code' => md5(uniqid(mt_rand(), true)),
'confirmed' => 1,
'api_user' => (isset($input['api_user']) ? $input['api_user'] : 0),
'account_id' => $input['account_id'],
'role_id' => (isset($input['role_id']) ? $input['role_id'] : 0),
'all' => (!isset($input['associated-permissions']) || $input['associated-permissions'] == 'all') ? 1 : 0,
'status' => (!isset($input['status']) || $input['status'] ? 1 : 0),
'all_locations' => $input['all_locations']
]);
where users() is your public function but I don't know what is $this in your case but should be the model as in the example from documentation.
Why you're not using resource controllers? Or if you need to populate the db use a seeder
I think It will be more easy to manage.
So 2 things i can think off
1st there is no need to use
protected $guarded = [];
and
protected $fillable = [];
Guarded will assume everything is fillable if its not in here and fillable will assume everything is guarded unless in here.
To quote the docs
While $fillable serves as a "white list" of attributes that should be mass assignable, you may also choose to use $guarded. The $guarded property should contain an array of attributes that you do not want to be mass assignable. All other attributes not in the array will be mass assignable. So, $guarded functions like a "black list". Of course, you should use either $fillable or $guarded - not both.
2nd to rule out any of the $this->model stuff try instantiate the class first and save them
use App\Path\To\Model as user;
$user = new user();
$user->first_name = $input['first_name'];
$user->last_name = $input['last_name'];
$user->username = $input['username'];
$user->email = $input['email'];
$user->password = bcrypt($input['password']);
$user->confirmation_code = md5(uniqid(mt_rand(); true));
$user->confirmed = 1;
$user->api_user = (isset($input['api_user']) ? $input['api_user'] : 0);
$user->account_id = $input['account_id'];
$user->role_id = (isset($input['role_id']) ? $input['role_id'] : 0);
$user->all = (!isset($input['associated-permissions']) || $input['associated-permissions'] == 'all') ? 1 : 0;
$user->status = (!isset($input['status']) || $input['status'] ? 1 : 0);
$user->all_locations = $input['all_locations'];
$user->save();
Guys I'm able to resolve issue by using Fill() method.
public static function create(array $attributes = Array())
{
$user = access()->user();
if($user)
{
$attributes['account_id'] = (!isset($attributes['account_id']) ? $user->account->id : $attributes['account_id'] );
}
$childClass = get_called_class();
$model = new $childClass;
$model->fill($attributes);
$model->save();
$model->runActionLogger($model, 'create');
return $model;
}
Also By mistake I've added Construction on CanResetPassword Trait which causing issue as well. So If i remove that everything will work as before as well.
Yes, you can't use __construct method in Traits.
Please Refer PHP.net for more details about trait, they said "Using AS on a __construct method (and maybe other magic methods) is really, really bad."
You can use trait like following way.
class User extends BaseModel
{
use userRelation
}
Trait userRelation
{
public function getUserName()
{
return "Jhon Doe";
}
}
I have created "userRelation" Trait which contains few useful code to re-use.
Please refer following link for more details - http://php.net/manual/en/language.oop5.traits.php
Please try it and let me know if it won't work.
Thanks
I am getting this error:
MassAssignmentException in Model.php line 448: _token
When I am using create method. Please review code below:
Contacts.php (Model):
class Contacts extends Model
{
protected $table = ['name', 'mobile', 'email', 'address', 'created_at', 'updated_at'];
}
ContactsController.php (Controller):
public function store(Request $request)
{
$inputs = $request->all();
$contacts = Contacts::Create($inputs);
return redirect()->route('contacts.index');
}
For the Mass Assignment Exception: you should specify all the fields of the model that you want to be mass-assignable through create or update operations on the property $fillable:
protected $fillable = ['name', 'mobile', 'email', 'address', 'created_at', 'updated_at'];
Besides, the field $table should contain only the model's table name:
protected $table = 'your_table_name';
This might happen in case if you have used the wrongly imported the class. if you are using the User Model.
Wrong Import
// mostly IDE suggestion
use Illuminate\Foundation\Auth\User;
Correct Model Import
use App\User;
i have gone through this. might help someone.
You can all column fillable:
protected $guarded = array();
Add your model.
You need only to add the following to your Model (Contact):
protected $fillable = ['name', 'mobile', 'email', 'address', 'created_at', 'updated_at'];
For example:
class Contacts extends Model {
protected $table = ['name', 'mobile', 'email', 'address', 'created_at', 'updated_at'];
protected $fillable = [ 'name', 'mobile', 'email', 'address', 'created_at', 'updated_at' ];
}
If all of the above fails, you can try following.
Put following after namespace.
use Eloquent;
Put following at the start of your store method.
Eloquent::unguard();
like:
public function store(Request $request)
{
Eloquent::unguard();
$inputs = $request->all();
$contacts = Contacts::Create($inputs);
return redirect()->route('contacts.index');
}
This is not recommended though, as this makes things vulnerable to attacks. But if you need a quick fix this might help.
Check Model you have Imported or Not. If not then use this.
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\User;
Make sure you are putting the $fillable or $guarded in the app\Contacts.php file and not the app\Http\Controllers\ContactsController.php file. It should be obvious, but it can be overlooked.
I am a bit stuck with the mass assignment. I have an input field (datepicker) which needs to get modififies (apply the strtotime function) before inserting it to the database.
Is there a way to do that while using the mass assignment?
class Customer extends Ardent {
protected $table = 'customers';
public $autoPurgeRedundantAttributes = true;
public $autoHydrateEntityFromInput = true;
public $forceEntityHydrationFromInput = true;
protected $fillable = array(
'email',
);
}
If you just need to change the Input, you can do:
$input = Input::all();
$input['date'] = strtotime($input['date']);
Input::replace($input);