skip to Main Content

i am trying to retrieve questions based on the category witch they belong with this function inside my questions controller:

public function getByCategoryName($categoryName) {
        $category = Category::where('name', $categoryName)->first();
        return response($category->questions);

    }

the problem is that, even if $category its being correctly set, $questions is null and the browsers returns an empty response to my request

the tables are created like this:

Questions table:

        Schema::create('questions', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
            $table->string('title')->nullable(false);
            $table->string('content')->nullable(false);
            $table->integer('points')->default(0);
            $table->foreignId('user_id')
                ->constrained('users')
                ->onDelete('cascade');

            $table->string('category_name');
            $table->foreign('category_name')
                ->references('name')->on('categories')
                ->onDelete('cascade')
                ->onUpdate(null);

        });

categorie table:

Schema::create('categories', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
            $table->string('name')->nullable(false);
            $table->unique('name');
        });

I have the relatives relationship functions HasMany and BelongsTo seated inside the the models.

Question model:

public function category(): BelongsTo
    {
        return $this->belongsTo(Category::class);
    }

Category model:

public function question() : HasMany {
        return $this->hasMany(Question::class);
    }

What am I doing wrong?

2

Answers


  1. Change this :

        public function question() : HasMany {
            return $this->hasMany(Question::class);
        }
    

    To this :

        public function questions() : HasMany {
            return $this->hasMany(Question::class, 'category_name');
        }
    
    Login or Signup to reply.
  2. As others have pointed out. It’s better to use the primary ID key for efficient mapping. However, for education purposes it is possible and I will explain. Eloquent determines the foreign key name by examining the name of the relationship method and suffixing the method name with _id.
    So, in this case, Eloquent assumes that the Question model has a category_id column.
    However, since the foreign key on the Question model is not category_id, we must pass a custom key name as the second argument to the belongsTo method:

    public function category()
    {
        return $this->belongsTo(Category::class, 'foreign_key'); // If we do not pass this eloquent thinks the foreign key is 'category_id'
    }
    
    // We need to pass our custom foreign key
    public function category()
    {
        return $this->belongsTo(Category::class, 'category_name');
    }
    

    Eloquent assumes the parent model Category will be associated using its primary id. Since this is not our case we need to associate the parent model key to the ‘name’ column.
    So we need to pass a third argument to the belongsTo method specifying the parent tables custom key:

    public function category()
    {
        return $this->belongsTo(Category::class, 'category_name', 'name');
    }
    

    Your complete solution should look something like this.

    // Question model
    public function category()
    {
        return $this->belongsTo(Category::class, 'category_name', 'name');
    }
    
    // Category model
    public function questions()
    {
        return $this->hasMany(Question::class, 'category_name', 'name');
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search