Skip to content

[12.x] Add createMany mass-assignment variants to HasOneOrMany relation #55262

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 4, 2025

Conversation

onlime
Copy link
Contributor

@onlime onlime commented Apr 2, 2025

In Eloquent's HasOneOrMany relation, we have the following methods: create(), createQuietly(), forceCreate(), and forceCreateQuietly(). But to create a collection of new instances of the related model, we only have createMany() and createManyQuietly. I found myself searching for such mass-assignment variants over and over again.

In data import actions, I do this:

collect($comments)
    ->map(fn (array $comment) => [
        ...$comment,
        // override some attributes here
    ])
    ->each(fn (array $comment) => $post->comments()->forceCreateQuietly($comment));

With this PR, we can use use the lovely splat operator ... to pass all items directly into the forceCreateManyQuietly() method:

collect($comments)
    ->map(fn (array $comment) => [
        ...$comment,
        // override some attributes here
    ])
    ->pipe($post->comments()->forceCreateManyQuietly(...));

This PR adds the missing forceCreateMany() and forceCreateManyQuietly() methods.

@taylorotwell taylorotwell merged commit 98375d1 into laravel:12.x Apr 4, 2025
39 checks passed
@AhmedAlaa4611
Copy link
Contributor

Is this documented yet?

@genesiscz
Copy link

@onlime Hi, I have no idea how would you use this practically, I guess you have to put something into the forceCreateManyQuietly(...) instead of the three dots only. pipe is expecting a callback, doesn't it? How does that work?

@onlime
Copy link
Contributor Author

onlime commented May 26, 2025

@onlime Hi, I have no idea how would you use this practically, I guess you have to put something into the forceCreateManyQuietly(...) instead of the three dots only. pipe is expecting a callback, doesn't it? How does that work?

My example is a fully working example. The 3 dots are not the ones you know from regular life, so they are not any placeholders or anything like that. The ... is called PHP's splat operator and it can really be used like this to pipe the whole Collection of $comments into that method:

collect($comments)
    ->pipe($post->comments()->forceCreateManyQuietly(...));

If you like 1-liners like I do, learn about that splat operator. If you feel it's too much magic, forget about it and do it more explicitly:

collect($comments)
    ->each(fn (array $comment) => $post->comments()->forceCreateQuietly($comment));

100% same end result. Just a matter of preference.

@shaedrich
Copy link
Contributor

The ... is called PHP's splat operator and it can really be used like this to pipe the whole Collection of $comments into that method:

@genesiscz btw fyi: The whole method construct is called "first-class callable"

@genesiscz
Copy link

Oh so it basically creates callable with the same arguments as the method you pass ... into have - then it passes the function into pipe.

So it is the same as

->pipe(fn(iterable $arr) => $post->comments()->forceCreateManyQuietly($arr));

Right?
Today I learned! Thanks a bunch 💕

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants