I would be very reluctant to override any of these core Eloquent methods; if you want something custom, then write your own function.
Overriding firstOrNew() of a model
Is there a way to override firstOrNew() of a model?
I would like to associate a few models during the New() phase.
Thank you.
The good english terms have been used up, so I just wanna reuse them. What I'm trying to do is for example I have the Sales model, I will have Sales_online and Sales_offline models and they extend the Sales with additional custom behavior
probably better to call your Models SalesOnline & SalesOffline rather than using an underscore to separate.
Is that the official naming convention? I have been struggling with this and ended up using the style of Sales_online for my models.
I dont think laravel give an official view but best practice is
'A model should be in singular, no spacing between words, and capitalised.'
https://webdevetc.com/blog/laravel-naming-conventions/#section_naming-models-in-laravel
This is also a good resource : https://github.com/alexeymezenin/laravel-best-practices
thanks @automica
sorry 1 more question about this, if another model references SalesLead model, how should the method be named?
-
salesLead()andsalesLeads() -
sales_lead()andsales_leads()
1 or 2? Thanks.
@laracoft Did you read those links which @automica gave you?
https://www.php-fig.org/psr/psr-2/
https://github.com/alexeymezenin/laravel-best-practices#follow-laravel-naming-conventions
Yes, I glanced through them as there was a lot to go through. Anyway thanks.
always camel case for method and relationship names. so 1)
I just came across official docs, https://laravel.com/docs/8.x/eloquent#table-names it gives examples of how model names are converted to tables, implying how both should be named.
Yep. The docs say the table will be snake case plural of the class.
Eg CustomClass will be looking for a table called custom_classes.
It doesn’t say you should use snake case class names.
You can use whatever class name and table names you like if you specify the table name in the model.
Is there a way to override firstOrNew() of a model?
Yes, just inside of your model (or maybe better trait) define a method with same name.
This did not work. I did some tracing and it was infinitely recursing.. and I don't understand why.
public static function firstOrCreate(array $attributes, array $joining = [], $touch = true)
{
$result = parent::firstOrCreate($attributes, $joining = [], $touch = true);
return $result;
}
Shouldn't it be:
public function firstOrCreate(array $attributes = [], array $values = [])
{
$result = parent::firstOrCreate(array $attributes = [], array $values = []);
// top secret work
return $result;
}
Model::firstOrCreate() cannot be called statically error.
public static function firstOrCreate(array $attributes = [], array $values = [])
{
$result = parent::query()->firstOrCreate($attributes, $values);
// top secret work
return $result;
}
Overriding of built in functions/methods as firstOrxxx() is NOT RECOMMENDED.
Might be useful:
Thanks, could you
- Update
$result = parent::query()->firstOrCreate($attributes, $values); - Add that overriding
firstOrxxx()is NOT RECOMMENDED - Add that https://github.com/calebporzio/parental and related article https://tighten.co/blog/extending-models-in-eloquent/ might be more useful
And I will mark yours as best answer.
@laracoft updated per your liking sir 🥳
@laracoft Don’t override core Eloquent methods in your models. Create a service class instead if you need to do additional logic around creating models.
Just don't do it @bugsysha - it is not a benign method - there is a lot going on under the surface.
Don't get me wrong. I don't suggest it.
Alright guys, I accept that we should not override firstOrXXX() given the infinite recursion and other weird errors.
Let me test out some code and see if I have other questions. My aim was to have SalesOnline and SalesOffline behave like models but pointing to the sales table. But I think service class probably can't achieve the same effect.
Perhaps Promotion, PromotionGoogle and PromotionAmazon better explains my use case. The idea is I can easily encapsulate the new promotion logic in another class when it comes along.
Thank you for the help so far.
Anyone used https://github.com/calebporzio/parental before?
Related article https://tighten.co/blog/extending-models-in-eloquent/
Please or to participate in this conversation.