Search code examples
laravelrelationshiplaravel-9eloquent-relationship

Problem with laravel relationships (many to many + one to many), cant access them for some reason


so, i have this database

one "user" has many "inputs" and "input" has only one "habitos" and "sentimentos", so we can say that one user has many "habitos", and "sentimentos" too.

and i should be able to do something like {{$user->inputs->habitos}}, but for some reason i can't, and somehow {{$users->input}} works and {{$input->habitos}} also works, here is the code

user model:

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
        'telefone',
        'hotmart_id'
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    public function input(){
        return $this->hasmany(Input::class, 'user_id', 'id');
    }


}

input model:

class Input extends Model
{
    use HasFactory;

    public function habito(){
        return $this->belongsto(Habito::class, 'habito_id', 'id');
    }

    public function sentimento(){
        return $this->belongsto(Sentimento::class, 'sentimento_id', 'id');
    }

    public function user(){
        return $this->belongsto(User::class, 'user_id', 'id');
    }
}

habito model:

class Habito extends Model
{
    use HasFactory;

    protected $fillable = ['nome', 'categoria'];

    public function input(){
        return $this->hasmany(Input::class, 'habito_id', 'id');
    }
}

i've been searching for someone with the same problem, but i cant seem to find nothing on this, thanks in advance :).


Solution

  • I had the same issue, well.. almost the same. I had Meals that has a pivot table with tags - so it's a many to many relationship and tags have a translation.

    Picture this, when fetching the data and you use a query "with=tags", you actually fetch tagtranslations based on the Locale (en, de, fr, etc.), so you go through "meal_tag" pivot table, through "tag" table and finally you get to "tagtranslations" and fetch translations of the tag_id connected to the meal.

    I don't think you have to use has This is how I did it:

    Meal Class:

     public function tags(){
            return $this->belongsToMany(Tag::class, 'meal_tags')->withTrashed();
        }
    

    MealTag class:

     public function meals()
        {
            $this->hasMany(Meal::class, 'meal_id')->withTrashed();
        }
    
        public function tags()
        {
            $this->hasMany(Tag::class, 'tag_id')->withTrashed();
        }
    

    Tag class:

    public function meals()
    {
        return $this->belongsToMany(Meal::class, 'meal_tags')->withTrashed();
    } 
    
    public function translations()
    {
        return $this->hasOne(TagTranslation::class)->where('locale', app()->getLocale())->withTrashed();
    }
    

    **ignore the middleware for translations because you don't need it, just use withTrashed if you use softDeletes

    and finally TagTranslations class:

    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Factories\HasFactory;
    use Illuminate\Database\Eloquent\Model;
    use Illuminate\Database\Eloquent\SoftDeletes;
    use Staudenmeir\EloquentHasManyDeep\HasRelationships;
    
    class TagTranslation extends Model
    {
        use HasFactory, SoftDeletes, HasRelationships;
    
    public function tag(){
        return $this->belongsTo(Tag::class)->withTrashed();
    }
    
    public function meals(){
        return $this->hasManyDeep(Meal::class, [Tag::class, 'tag_id','meal_id'])->withTrashed;
    }
    

    }

    notice I'm using hasManyDeep, for that you have to install staudenmeir package: Click here to view on github .. but the thing is, Eloquent should recognize everything you need even without hasManyDeep, but if it works like that, who am I to argue :D

    this worked for me - if something goes wrong I'm sure it's just a matter of some slight adjustment.