The issue you're encountering is likely due to the firstOrNew method attempting to access the price attribute on a model instance that has not yet been saved to the database. Since the price attribute is not set (it's null), the getter method for the price attribute fails because it expects an integer value.
To resolve this issue, you can modify the getter method to handle null values gracefully. Here's how you can update your price attribute getter to return null or a formatted string depending on whether the $value is null or an integer:
protected function price(): Attribute
{
return Attribute::make(
get: fn ($value) => is_null($value) ? null : number_format(($value / 100), 2),
);
}
With this change, if $value is null, the getter will simply return null instead of attempting to format it, which should prevent the error you're seeing when using firstOrNew or firstOrCreate.
Additionally, ensure that the price column in your database allows null values if there are cases where a PriceHistory model might be created without a price. If the price column is not nullable and you're trying to create a PriceHistory without a price, you'll need to provide a default value for it.