Jhecht
Jhecht

Reputation: 4435

Laravel Eloquent firstOrNew not populating attributes on "new" condition

I officially tap on this -- I can't wrap my head around what I am doing wrong.

I am trying to use ::firstOrNew to check for the existence of a record or to create the object instance for it. The issue is that when I pass values to it that I know are not in the database, the subsequent model that is created has absolutely no properties set on it. the code looks a bit like this (trimmed down some random bloat)

if($old_value != ''){
    list($old_tag, $oldV) = explode(':', $old_value);
    list($new_tag, $value) = explode(':', $new_value);
    //Get the new tag / old tag, new value / old value

    $tag = CdwTagging::firstOrNew(['tagging'=>$old_tag], [ 'value'=>$old_value, 'segment'=>$tag_section]);

    if(!$tag->exists) {
       //do some logical stuff based on other values, etc.
       $tag->save();
    }
}

My code is based on This Link from the Docs.

If I add in a dd($tag) into this my output is:

I have checked to see if the arrays I am using actually hold values (as in: perhaps I had messed up in gathering the data) and I can assure you that the values are exactly what is sent through the form.

CdwTagging {#320
  #table: "cdw_tagging"
  #fillable: array:3 [
    0 => "segment"
    1 => "tagging"
    2 => "value"
  ]
  #connection: "mysql"
  #primaryKey: "id"
  #keyType: "int"
  +incrementing: true
  #with: []
  #withCount: []
  #perPage: 15
  +exists: false
  +wasRecentlyCreated: false
  #attributes: []
  #original: []
  #casts: []
  #dates: []
  #dateFormat: null
  #appends: []
  #events: []
  #observables: []
  #relations: []
  #touches: []
  +timestamps: true
  #hidden: []
  #visible: []
  #guarded: array:1 [
    0 => "*"
  ]
}

and if I ignore that and say 'well maybe because it's new it doesn't show the properties yet' and call the ->save() method anyway I get an error such as

SQLSTATE[HY000]: General error: 1364 Field 'segment' doesn't have a default value (SQL: insert into cdw_tagging (updated_at, created_at) values (2017-12-01 22:59:11, 2017-12-01 22:59:11))

I feel like I must be doing something wrong in how I am trying to use this method, but I have to be tired or something because I can't figure out what. Thanks for any help or ideas you may have

Upvotes: 1

Views: 2294

Answers (4)

М.Б.
М.Б.

Reputation: 1420

It might be silly, but I had the same issue, and the problem was both of fillable and guarded were improperly configured. So I had this:

public $fillable = ['*'];

instead of:

protected $guarded = ['id']; 

And that solved the issue.

Upvotes: 2

lagbox
lagbox

Reputation: 50491

The constructor for models is as follows:

public function __construct(array $attributes = [])

It takes attributes. New instances can have attributes filled when they are created, which is what happens with firstOrNew.

If you decide for some odd reason to not take those attributes in your constructor, then your attributes wont be assigned to the model instance when it is being created via new Model($attributes).

Upvotes: 5

TalESid
TalESid

Reputation: 2524

I think you have put 'segment' in 2nd parameter (i.e. Optional). You should do something like this:

['tagging'=>$old_tag, 'segment'=>$tag_section], [ 'value'=>$old_value]

One more thing... the variable $tag_section is what I can't see in your code. Maybe it is assigning NULL value in segment.

ref:https://laravel.com/docs/5.5/eloquent#other-creation-methods

Upvotes: 0

Radu
Radu

Reputation: 1031

The error is because it does not send a value for the column segment when you do insert.

If just for testing, you allow NULL or set a default value for column segment in table cdw_tagging, does it work?

Upvotes: 0

Related Questions