'int', 'weight' => 'float', ]; /** * Nutrient per serving methods. */ private array $nutrientPerServingMethods = [ 'caloriesPerServing', 'carbohydratesPerServing', 'cholesterolPerServing', 'fatPerServing', 'proteinPerServing', 'sodiumPerServing', ]; /** * @inheritdoc */ protected $appends = [ 'serving_weight', ]; /** * Get the serving weight (rounded). */ public function getServingWeightAttribute(): ?float { if (empty($this->weight)) { return null; } return round($this->weight / $this->servings, 2); } /** * Get the steps for this Recipe. */ public function steps(): HasMany { return $this->hasMany(RecipeStep::class)->orderBy('number'); } /** * Add nutrient calculations handling to overloading. * * @param string $method * @param array $parameters * * @return mixed * * @noinspection PhpMissingParamTypeInspection */ public function __call($method, $parameters): mixed { if (in_array($method, $this->nutrientTotalMethods)) { return $this->sumNutrient(substr($method, 0, -5)); } elseif (in_array($method, $this->nutrientPerServingMethods)) { $sum = $this->sumNutrient(substr($method, 0, -10)) / $this->servings; // Per-serving calculations are rounded, though actual food label // rounding standards are more complex. if ($sum > 1) { return round($sum); } else { return round($sum, 2); } } else { return parent::__call($method, $parameters); } } }