Solution 1:

firstOrCreate() checks for all the arguments to be present before it finds a match. If not all arguments match, then a new instance of the model will be created.

If you only want to check on a specific field, then use firstOrCreate(['field_name' => 'value']) with only one item in the array. This will return the first item that matches, or create a new one if not matches are found.

The difference between firstOrCreate() and firstOrNew():

  • firstOrCreate() will automatically create a new entry in the database if there is not match found. Otherwise it will give you the matched item.
  • firstOrNew() will give you a new model instance to work with if not match was found, but will only be saved to the database when you explicitly do so (calling save() on the model). Otherwise it will give you the matched item.

Choosing between one or the other depends on what you want to do. If you want to modify the model instance before it is saved for the first time (e.g. setting a name or some mandatory field), you should use firstOrNew(). If you can just use the arguments to immediately create a new model instance in the database without modifying it, you can use firstOrCreate().

Solution 2:

As of Laravel 5.3 it's possible to do this in one step with firstOrCreate using a second optional values parameter used only if a new record is created, and not for the initial search. It's explained in the documentation as follows:

The firstOrCreate method will attempt to locate a database record using the given column / value pairs. If the model cannot be found in the database, a record will be inserted with the attributes resulting from merging the first array argument with the optional second array argument.

Example

$user = User::firstOrCreate([
    'email' => '[email protected]'
], [
    'firstName' => 'Taylor',
    'lastName' => 'Otwell'
]);

This returns the User for the specified email if found, otherwise creates and returns a new user with the combined array of email, firstName, and lastName.


This technique requires Mass Assignment to be set up, either using the fillable or guarded properties to dictate which fields may be passed into the create call.

For this example the following would work (as a property of the User class):

/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['email', 'firstName', 'lastName'];

Solution 3:

firstOrCreate() checks for all the arguments to be present before it finds a match.

If you only want to check on a specific field, then use firstOrCreate(['field_name' => 'value']) like:

$user = User::firstOrCreate([
    'email' => '[email protected]'
], [
    'firstName' => 'abcd',
    'lastName' => 'efgh',
    'veristyName'=>'xyz',
]);

Then it checks only the email.