Laravel 5.4 field doesn't have a default value - php

I am having this error and none of the googled result i checked is similar to my problem.
I have an application with class Deal, User, and Matches
A deal has many matches.
A user has many matches.
A user has many deals.
I am attempting to create a new Match using my Deal object
$deal->matches()->create(['user_id'=>$id]);
This is my match class, i have defined all needed relationships
class Match extends Model
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $guarded = [];
public $timestamps = false;
public $expired_on = "";
public static function boot()
{
parent::boot();
static::creating(function ($model) {
$model->matched_on = $model->freshTimestamp();
});
}
public function __construct(){
$d = (new \DateTime($this->matched_on))->modify('+1 day');
$this->expired_on = $d->format('Y-m-d H:i:s');
}
/**
* Get the user that owns the match.
*/
public function user()
{
return $this->belongsTo('App\User');
}
/**
* Get the deal that owns the match.
*/
public function deal()
{
return $this->belongsTo('App\Deal');
}
}
And i keep getting this error when i attempt to create a new match.
QueryException in Connection.php line 647:
SQLSTATE[HY000]: General error: 1364 Field 'user_id' doesn't have a default value (SQL: insert into matches (deal_id) values (1))
I have my guarded to be an empty array, what could be the problem?

Remove the guarded array and add the fillable instead:
protected $fillable = ['user_id', 'deal_id'];

If you would like to revert to previous behavior, update your
config/database.php
file and set 'strict' => false for your connection.

Since it was a unique field in my case, I could not make it nullable.
For me, I had an empty constructor which was causing the issue don't know why.
Please comment if anyone knows the reason.
public function __construct(){
}
Commenting/removing it resolved the issue.

If you have a constructor in your model, just make sure it has a call to a parent constructor as well:
public function __construct( array $attributes = array() ) {
// mandatory
parent::__construct($attributes);
//..
}
Otherwise, it will break some functionality like Model::create.

Alexey Mezenin's Answer is correct and a good one.
Another way i used around it, for those who want to maintain the guarded empty array is to create a new Match object and put in the attributes and save.
$match->user_id = $id;
$match->deal_id = $deal->id;
$match->matched_on = $match->freshTimestamp();
$match->save();

I am using Laravel 8 and fixed this error thorugh this two steps:
move the word from $guarded array to $fillable array in User Mode
Config.database.php: 'strict' => false in the array of 'mysql'

Another way around this error is to include
'strict' => false,
into config/database.php within mysql array

When manually importing / exporting the databases, check if the transfer of all table settings was successful. If you forget to add an auto increment primary key, Laravel doesn't fill the value for you.
Adding the AUTO_INCREMENT afterwards will solve the problem.

I had this error but my wrong was making class model:
$book = new Book();
While this is true
$book = new Book($request->all());

changing your "config/database.php" won't help.
If you're getting this error, you're not sending the data to database correctly.
check your function in your controller, the create() method is probably being blocked by an if statement or something.
or
if it's an API, check the post request from the frontend that's where your issue is.
make sure the form is correctly passed into to request.

Related

how does laravel UPDATE method work

I am working on this laravel project where user can upload an avatar image. My users table does not have any column yet to store the file location. So i was testing this in phpunit following the TDD series in laracast.
After the file is uploaded successfully and moved to the desired location in the server, i called the update method on the authenticated user like below:
$user = auth()->user();
$user->update(['avatar_location' => 'avatars/avatar.jpg']);
Note that avatar_location is not yet there on the users table. I expected this to fail but it didn't. I tried to find out what was going on so i followed through to the update() method in the model class:
//file Illuminate/Database/Eloquent/Model.php
public function update(array $attributes = [], array $options = [])
{
//dd($attributes); //prints 'avatar_location"=>"avatars/avatar.jpg'
if (! $this->exists) {
//dd($attributes);
return false;
}
return $this->fill($attributes)->save($options);
}
till this point the dd($attribute) prints the value that i passed to the update() method.
So i followed into the fill() method that is being called with the attribute parameter. However when i die dumped the received parameter from inside the fill() method i am not seeing the key=>value pair that i passed. Instead it was showing the other attributes of the user:
/**
* Fill the model with an array of attributes.
*
* #param array $attributes
* #return $this
*
* #throws \Illuminate\Database\Eloquent\MassAssignmentException
*/
public function fill(array $attributes)
{
//dd($attributes);
//does not print 'avatar_location"=>"avatars/avatar.jpg'
//rather, prints:
//array:4 [
// "name" => "Armand Mraz"
// "email" => "akautzer#example.net"
// "password" => "$2y$10$h7OG9/Toh31MsyFQc8lfg.wHeQC7maP4Bh37bea.DXU//IuRuXZi."
// "remember_token" => "X0udISwEEM"
]
$totallyGuarded = $this->totallyGuarded();
foreach ($this->fillableFromArray($attributes) as $key => $value) {
$key = $this->removeTableFromKey($key);
// The developers may choose to place some attributes in the "fillable" array
// which means only those attributes may be set through mass assignment to
// the model, and all others will just get ignored for security reasons.
if ($this->isFillable($key)) {
$this->setAttribute($key, $value);
} elseif ($totallyGuarded) {
throw new MassAssignmentException($key);
}
}
return $this;
}
I spent a lot of time trying to figure out why?
can anyone please explain?
And why the update method is not failing even though i am trying to update a column that does not exist?
Thanks,Yeasir
When you're updating an object, Laravel is trying to match the keys of the array of data and the list of fillable fields. All pairs of key/valye missing from the fillable fields are not considered. It's the reason why it's not failing.
You have to update the fillable field list (property $fillable) in your user model.
Have a look at the documentation.
If you add avatar_location in your fillable fields list and the field doesn't exist, in this case, it will throw an exception.

How to solve Laravel select queries conflicting with the $appends property on models?

I have a situation where I need a specific attribute accessor appended to one of my models automatically:
class Mission extends Eloquent {
protected $appends = ['launch_date_time'];
public function getLaunchDateTimeAttribute() {
return ($this->attributes['launch_approximate'] == null) ? $this->attributes['launch_exact'] : $this->attributes['launch_approximate'];
}
}
As you can see, this launch_date_time property is dependent on two other fields of my model that are actually in my database.
However, I now want to perform a query where only a certain number of fields are returned, as this is going to be sent over AJAX multiple times and I would rather use as few resources as possible:
// AJAX GET
// missions/all
public function all() {
$allMissions = Mission::with('featuredImage')->get(['mission_id', 'name', 'featured_image']);
return Response::json($allMissions);
}
The issue here is that I no longer need the launch_date_time attribute, so I have excluded it, **in doing so, my AJAX request does not work successfully:
Undefined index: launch_approximate on line 78 of H:\myproj\app\models\Mission.php
This is clearly because my model is attempting to append launch_date_time, of which launch_approximate is a dependency of. If I include all the required dependencies, all of them any my attribute that I want to append appear:
$allMissions = Mission::with('featuredImage')->get(['mission_id', 'name', 'featured_image', 'launch_approximate', 'launch_exact', 'launch_date_time']);
This is undesirable. Is there a solution where I can keep both setups?
The reason it is not working is because you are not retrieving the required fields from the database in the get method on your query. That is why you can't access launch_exact and launch_approximate because they are not set in the instance of your model.
So to make it work like you want. You would have to check if launch_exact and launch_approximate are set before you access them.
public function getLaunchDateTimeAttribute() {
if(isset($this->attributes['launch_approximate']) && $this->attributes['launch_exact']) {
return ($this->attributes['launch_approximate'] == null) ? $this->attributes['launch_exact'] : $this->attributes['launch_approximate'];
}
return null;
}
You can also set a whitelist with the $visible property and a black list with $hidden inside your model to not show certain attributes when outputing to json or a array take a look at the docs: http://laravel.com/docs/5.1/eloquent-serialization#hiding-attributes-from-json

Is it possible to map a column name in an Laravel Eloquent model?

I have a DB table with a column "visible" (true/false).
The Eloquent model already has a property visible, see this code snippet taken from Illuminate\Database\Eloquent\Model.
/**
* The attributes that should be visible in arrays.
*
* #var array
*/
protected $visible = array();
When printing out the model, the "visible" property is the already existing array instead of the column value. Is there a way to rename the column in the Model? I already tried this (found here: http://laravel.com/docs/4.2/eloquent#accessors-and-mutators)
public function setVisibleAttribute($value) {
$this->attributes['isvisible'] = $value;
}
public function getVisibleAttribute($value) {
$this->attributes['isvisible'];
}
I know I can solve the problem like this:
User::select('id', 'name', 'visible as isVisible')->get();
I was just wondering if there isn't a really built in mechanism.
Important note: the DB is also used by existing software so renaming it isn't really an option.

eloquent-sluggable build_from is being ignored

I have a class called Vara, where i have a table field called searchname. I want to do a simple setup of cviebrock eloquent sluggable but can't figure out what the issue is.
When i save my model, nothing happens, it rewrite the old value stored.
If i change in build_from to, whatthefuckisgoingon i get the same output. I have a field called handle, also tried changing the field namne to slug but same result. If i leave build_from empty i also get the same output.
If i however change save_to to something that doesn't exist i get an error. The searchname field does have a value of "Hjordnära test 33 liter", so the output is really wierd.
My guess is that build_from is being ignored, and seen as null. How do i fix this?
My Vara.php looks like this
use Cviebrock\EloquentSluggable\SluggableInterface;
use Cviebrock\EloquentSluggable\SluggableTrait;
class Vara extends \Eloquent implements SluggableInterface {
use SluggableTrait;
protected $sluggable = array(
'build_from' => 'searchname',
'save_to' => 'handle'
);
In my VarorController.php
public function saveVara()
{
$id = Input::get('id');
$vara = Vara::find(Input::get('id'));
$vara->edited_by = Auth::user()->id;
$vara->searchname = Input::get('searchname');
$vara->save();
return $vara->getSlug();
Ok a litle update, found this function in SluggableTrait.php
public function sluggify($force=false)
{
$config = \App::make('config')->get('eloquent-sluggable::config');
$this->sluggable = array_merge( $config, $this->sluggable );
if ($force || $this->needsSlugging())
{
$source = $this->getSlugSource();
$slug = $this->generateSlug($source);
$slug = $this->validateSlug($slug);
$slug = $this->makeSlugUnique($slug);
$this->setSlug($slug);
}
return $this;
}
so if i add $vara->sluggify(true); to my controller the slug is being saved, so now the questions is why it does not sluggify automaticly on $vara->save();
Most probably, it's an issue of validation because you're using Ardent:
Ardent is a package that "provides self-validating smart models for Laravel Framework 4's Eloquent ORM"
Check your rules and use if statement:
if(! $vara->save()) // if model is invalid
dd($vara->errors());
If you don't need to check validation , you may use
$vara->forceSave();
To integrate Eloquent sluggable with Ardent, take a look at this link

Troubles storing with laravel (Undefined property)?

I am trying to store data to the server with laravel. I am following a tutorial and I feel like it may be slightly out of date because I was getting a 500 error earlier with an update method.
public function store()
{
$input = Input::json();
return Player::create(array(
'teamName' => $input->teamName, // this is line 35
'teamColor' => $input->teamColor
));
}
The above is what the tutorial's syntax is like, I tried the below as well.
public function store()
{
$input = Input::all();
return Player::create(array(
'teamName' => $input['teamName'], // this is line 35
'teamColor' => $input['teamColor']
));
}
Inside the browser I get this error.
{"error":{"type":"ErrorException","message":"Undefined property: Symfony\\Component\\HttpFoundation\\ParameterBag::$teamName","file":"C:\\wamp\\www\\basketball-app-framework\\app\\controllers\\PlayersController.php","line":35}}
So I feel like these issues I should be able to figure out in a matter of seconds, but I am new and really don't know where to find a clear answer. I tried searching the docs, but I can't find what I am looking for, maybe I am being blind?
Try to use:
public function store()
{
return Player::create(array(
'teamName' => Input::get('teamName'),
'teamColor' => Input::get('teamColor')
));
}
Getting a mass assignment error, means that you need to edit your model and add the $fillable variable to it:
class Player extends Eloquent {
protected $fillable = array('teamName', 'teamColor');
}
Laravel tries to protect you from mass assignments, so you have to tell it which columns are ok to mass assign.
Request (Input) docs: http://laravel.com/docs/requests.
CheatSheet: http://cheats.jesse-obrien.ca/.
Mass assignment: http://laravel.com/docs/eloquent#mass-assignment.

Categories