Skip to content
Advertisement

Laravel object value with Blade statement does not work if model has accessor

i have an Laravel object model with accessor:

class NutritionalPlanRow extends Model
{
    use HasFactory;

    private $nomeAlimento;

    public function __construct($aliment = null,
                                array $attributes = array())  {

        parent::__construct($attributes);

        if($aliment){
            $this->aliment()->associate($aliment);
            $this->nomeAlimento = $aliment->nome;
        }
    }

    public function aliment()
    {
        return $this->belongsTo('AppModelsAliment');
    }

    protected $guarded = [];

    public function getNomeAlimentoAttribute()
    {
        return $this->nomeAlimento;
    }
}

and i want to print the nomeAlimento value in a Blade page with Blade statement, for example:

 .
 .
 <tbody>
     @foreach( $plan->nutritionalPlanRows as $planRow )
     <tr>
         <td>
             {{ $planRow->nomeAlimento}}
         </td>
   .
   .

but the value inside the table cell is not printed, as if $planRow->foodName is null. In reality it is not empty, in fact if I print {{$planRow}} the structure of the object is complete, and all the attributes are set. I noticed that if in the model I remove the accessor (getNomeAlimentoAttribute()), then the value in the blade page is correctly printed.

Why?

Thanks.

Advertisement

Answer

There are a few things that need attention:

First: Why do you need a constructor? You can define a calculated attribute without the constructor

use AppModelsAliment;

class NutritionalPlanRow extends Model
{
    use HasFactory;
  
   

    public function aliment()
    {
        return $this->belongsTo(Aliment::class);
    }

    protected $guarded = [];

    public function getNomeAlimentoAttribute()
    {
        return optional($this->ailment)->nome;
    }
}

Second: It seems like a code smell when using constructor in Eloquent Model class to set relations. Ideally relations should be set/associated from within Controller.

Third: I feel declaring $nomeAlimento as private property on the class is not required. In Laravel calculated properties/attributes can be provided with accessors.

Update:

class Patient extends Model
{
    use HasFactory;


    protected $dates = ['day_born'];
    protected $guarded = [];

    public function getYearsAttribute(){
        
        Log::info('patient all data '.$this);  //Print correct all data
        Log::info('Day'.$this->day_born); //print empty
        
        
        return Carbon::parse($this->day_born)->diffForHumans(now());
    }
}

Read https://carbon.nesbot.com/docs/ for more goodies.

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement