Skip to content
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

[5.4] Add "make" method to Eloquent Query Builder #19015

Merged
merged 1 commit into from
May 1, 2017

Conversation

calebporzio
Copy link
Contributor

While recording a recent podcast, @DanielCoulbourne and I discussed the benefit of having a make method for models as an alternative to the create method that does the persistence right away. @tillkruss expressed interest in the make method as well.

Simple Example:

Post::make(['title' => 'Hello World!'])->save();

Down the road we both would love to see something like the following:

Post::make(['title' => 'Hello World!'])
    ->withAuthor($author)
    ->withCompany($company)
    ->save();

We are in the process of implementing this functionality as an alternative to:

$author->posts()->save(new Post(['title' => 'Hello World', 'company_id' => $company->id]));

For now, getting the make the make method into Laravel would be a big help in situations where you find yourself doing this: new Post(....

Thanks!

@tillkruss
Copy link
Contributor

We have make() method on model factories, this would make it a little more uniform and Post::newModelInstance() is rather long.

@taylorotwell taylorotwell merged commit 5f79b06 into laravel:5.4 May 1, 2017
@mattstauffer
Copy link
Contributor

👌🏻

* @param array $attributes
* @return \Illuminate\Database\Eloquent\Model
*/
public function make(array $attributes = [])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why isn't this static?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was just having this conversation with @calebporzio because I was accustomed to seeing create() as a static method on Model.php but it has now been moved to a dynamic method on the Eloquent Builder.

Looks like Model's __callStatic() method, which this is hitting, will call it dynamically.

I may be misunderstanding, but it seems safe to me.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless I'm mistaken, __callStatic only works for inaccessible methods, i.e. private/protected and non-existent methods so to leverage that, you'd likely want to make the method protected if going down that path.

Otherwise, yes, as @JosephSilber suggested, it ought to be static. I'm not even certain how it's working as is 🔮

Copy link
Contributor

@DanielCoulbourne DanielCoulbourne May 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It works when called from the Model context because make() (and create(), which is also not static) are non-existent on Model.php, triggering __callStatic() which then does:
return (new static)->$method(...$parameters); calling the dynamic method on Eloquent Builder dynamically. This appears to be indended functionality based on this comment

At least that's how it seems, but I'm kind of a source-diving n00b so I could be reading this wrong.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, TIL. I didn't know that __callStatic worked up the tree like that 👍

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh. Looked too quickly. Thought this was defined on the model.

Of course, since it's on the builder it should not be static.

However, why is it on the builder in the first place?

@antonkomarev
Copy link
Contributor

Hah... just thought to write the same implementation today! Thanks!

@meness
Copy link
Contributor

meness commented May 9, 2017

make() method released with the latest version, is it possible to do like this right now?

Post::make(['title' => 'Hello World!'])
    ->withAuthor($author)
    ->withCompany($company)
    ->save();

@decadence
Copy link
Contributor

@meness No. It was just future wish. This PR adds only one method.

@MasterRO94
Copy link
Contributor

What difference is between make() and fill() methods?

@calebporzio
Copy link
Contributor Author

@MasterRO94 - fill() can't be called statically. makes purpose is to initialize a model by using it as a static method: Post::make() - make sense?

@devcircus
Copy link
Contributor

'Fill' uses an existing instance. 'Make' initializes a new instance and fills it with the provided data.

@orrd
Copy link

orrd commented May 14, 2017

Rather than this:

Post::make(['title' => 'Hello World!'])->save();

We could already just do this right:

(new Post(['title' => 'Hello World!']))->save();

I guess the make() way is just an [arguably] cleaner alternative syntax?

@calebporzio
Copy link
Contributor Author

@orrd - exactly

@calebporzio
Copy link
Contributor Author

I just put it on the builder because that's where create lived. And it made sense to me to keep them both in the same place, especially since the only difference in implementation is the ->save() method.

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.