CodeIgniter4 icon indicating copy to clipboard operation
CodeIgniter4 copied to clipboard

Dev: Model needs new method - findOrCreate

Open lonnieezell opened this issue 3 years ago • 10 comments

The Model should provide a new convenience method, findOrCreate that can be given a set of criteria to locate within the db table, or create a new record using that data and an additional set of data that was provided.

Must work with all currently supported databases.

Undecided which version would work fit the project best, so am open to discussion on this one:

$userModel->where('email', '[email protected]')->findOrCreate(['key' => 'value', ...]);

// or

$userModel->findOrCreate(['existing_key' => 'value'], ['new_key' => 'value']);

References:

  • https://zenn-dev.translate.goog/mpyw/articles/laravel-v10-create-or-first?_x_tr_sl=ja&_x_tr_tl=en&_x_tr_hl=ja&_x_tr_pto=wapp&_x_tr_hist=true
  • https://laravel.com/docs/10.x/eloquent#retrieving-or-creating-models
  • https://book.cakephp.org/5/en/orm/saving-data.html#find-or-create-an-entity

lonnieezell avatar Oct 01 '21 03:10 lonnieezell

Either your example is incorrect or the concept is lame. You are talking about implementing a method in a model, but the example shows working with the BaseBuilder class.

In the CI paradigm, the BaseBuilder class provides simple basic methods for base operations (write/read). The new method in this case looks like sugar for sequential operations (read/read + write + read), which is contrary to the paradigm.

Model and BaseBuilder do not have create method, but insert method. This means that the new method must be named findOrInsert.

The second version is more compact, but it seems to me that the first parameter should also accept a string so that you can specify a key from the second palarament.

$data = ['a' => 1, 'b' => 2];
->findOrCreate('a', $data); // IMHO it looks better than
->findOrCreate(['a' => $data['a']), $data); 

iRedds avatar Oct 01 '21 07:10 iRedds

CakePHP has findOrCreate(). https://book.cakephp.org/4/en/orm/saving-data.html#find-or-create-an-entity

kenjis avatar Oct 01 '21 07:10 kenjis

CakePHP has findOrCreate().

Laravel also has it. The difference with Cake's is that we can't always assume an entity is being used, but it's interesting to be able to use one. I don't think that's necessary for this first pass, though.

@iRedds you're right - the example code was wrong. I'll fix that. And I have no problem with it being called findOrInsert.

lonnieezell avatar Oct 01 '21 13:10 lonnieezell

@lonnieezell Do you mean firstOrCreate in Laravel? https://laravel.com/docs/8.x/eloquent#retrieving-or-creating-models

kenjis avatar Oct 02 '21 00:10 kenjis

Isn't that what save() does?

https://codeigniter4.github.io/CodeIgniter4/models/model.html?highlight=save#save

Valkhan avatar Nov 12 '22 20:11 Valkhan

No. save() is to create or update.

kenjis avatar Nov 13 '22 09:11 kenjis

This feature is needed, I recently noticed its absence.

For example, the user may want to log in with Google, so the system first checks whether the user exists or not, and if there is, it is logged in.

If it does not exist, the new user is first registered and then logged in.

If this issue refers to this issue, I agree to add it.

datamweb avatar Nov 13 '22 09:11 datamweb

This method seems to be extremely complex. Do we really need this? See https://zenn-dev.translate.goog/mpyw/articles/laravel-v10-create-or-first?_x_tr_sl=ja&_x_tr_tl=en&_x_tr_hl=ja&_x_tr_pto=wapp&_x_tr_hist=true

kenjis avatar Feb 21 '24 07:02 kenjis

Actually, that article reinforces the idea that we should provide a solution. This is a fairly common pattern developers have to do. I'll admit I never coded for race conditions in those situations. I'm sure most people don't.

lonnieezell avatar Feb 21 '24 14:02 lonnieezell

Okay.

References:

  • https://laravel.com/docs/10.x/eloquent#retrieving-or-creating-models
  • https://book.cakephp.org/5/en/orm/saving-data.html#find-or-create-an-entity

kenjis avatar Feb 22 '24 00:02 kenjis