Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

redkoda's avatar

How to use firstOrNew?

Hi,

Would you tell me whether I could use findOrNew or firstOrNew to replace the following cumbersome code?

public function store(Request $request)
{
    $test = Test::where('test_name', $request->test_name)
        ->first();
    if ($test == null) {
        $test = new Test($request->all());
        $test->save();
    } else {
        Test::where('id', $test->id)->update($request->all());
    }
}
0 likes
7 replies
RachidLaasri's avatar
public function store(Request $request)
{ 
    $test = Test::firstOrNew('test_name', $request->test_name); 
    
    $test->update($request->all()); 
}
bobbybouwmann's avatar

@RachidLaasri firstOrNew will not work, because it returns a new instance and now a new object!

You need to use firstOrCreate instead

public function store(Request $request) { 
    $test = Test::firstOrCreate('test_name', $request->test_name); 

    $test->update($request->all()); 
}

The difference in the code below

    /**
     * Get the first record matching the attributes or create it.
     *
     * @param  array  $attributes
     * @return static
     */
    public static function firstOrCreate(array $attributes)
    {
        if (! is_null($instance = static::where($attributes)->first())) {
            return $instance;
        }

        // This returns a model object from the database
        return static::create($attributes);
    }

    /**
     * Get the first record matching the attributes or instantiate it.
     *
     * @param  array  $attributes
     * @return static
     */
    public static function firstOrNew(array $attributes)
    {
        if (! is_null($instance = static::where($attributes)->first())) {
            return $instance;
        }

        // This returns only an instance (new Test)
        return new static($attributes); 
    }
2 likes
thomaskim's avatar
Level 41

Wouldn't updateOrCreate be better in this instance since he's either creating a new instance or updating it? :)

$test = Test::updateOrCreate(['test_name' => $request->test_name, $request->all()]);
1 like
bobbybouwmann's avatar

@thomaskim That should work too. However I find it in two lines more readable then in one line. So many ways to achieve one thing ;)

Maartencast's avatar

Due to this post I was able to go from 3 lines to 2 lines saving my model, tnx!

@bobbybouwmann , what is your input on saving relationships and keeping it readable? Atm I have this function:

    public function storeOrUpdate( ContactRequest $request, $id )
    {
        $contact = Contact::firstOrCreate( ['id' => $id] );
        $contact->update( $request->all() );

        $address = Address::firstOrNew( ['contact_id' => $contact->id] );
        $address->fill( $request->input('address') );
        $contact->address()->save($address);

        return redirect()->route( 'contacts.index' );
    }

In order to get the 'contact_id' set properly I had to save it this way, leaving me with 3 lines xD. I could also set the 'contact_id' manually, but this looks real stupid?

Also I ran into a situation where I had to save 3 models: $profile->person->address. At my current internship they use only separate functions store() & update(), I was wondering if I should just do this or create a nice looking single function like the one above.

using a single function, I can go with this in my form:

    route( 'contacts.storeOrUpdate', $contact->id ?? 0)

and with this in my function:

$profile = Profile::updateOrCreate( ['id' => $id], $request->all() );

$person = Person::updateOrCreate( ['profile_id' => $profile->id], $request->input('person') );
$profile->person()->save($person);

$address = Address::updateOrCreate( ['person_id' => $person->id], $request->input('person.address') );
$person->address()->save($address);

using separate functions, I need to check which route and method to use in the form, but I can go with easy function content:

//for the store function:
$profile = Profile::create( $input );
$person = $profile->person()->create( $input );
$person->address()->create( $input );

//for the update function:
$profile = Profile::withTrashed()->find($id);
$profile->fill( $input );
$profile->person->fill( $input );
$profile->person->address->fill( $input );
$profile->push();

As a beginner, I can screw around for hours, not knowing what I should use and why xD.

Please or to participate in this conversation.