siusiak1000's avatar

How return subcategories

Hey! I create a system of categories and sub-categories.

Category migration:

    public function up()
    {
        Schema::create('magazine_categories', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->timestamps();
        });
    }

Subcategory migration:

        Schema::create('magazine_subcategories', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->timestamps();
        });

Category model:

class Magazine_category extends Model
{
    protected $fillable = [ 'name' ];

    public function subcategories()
    {
        return $this->hasMany('App\Magazine_subcategory');
    }
}


Subcategory model:

class Magazine_subcategory extends Model
{
    protected $fillable = [ 'name' ];

        public function categories()
    {
        return $this->belongsTo('App\Magazine_category');
    }
}

Pivot table (connect category with subcategory):

    public function up()
    {
        Schema::create('magazine_category_subcategory', function (Blueprint $table) {
             $table->increments('id');
             $table->integer('category_id')->unsigned();
             $table->integer('subcategory_id')->unsigned();
        });

        Schema::table('magazine_category_subcategory', function (Blueprint $table) {
             $table->foreign('category_id')->references('id')->on('magazine_categories');
        });

        Schema::table('magazine_category_subcategory', function (Blueprint $table) {
             $table->foreign('subcategory_id')->references('id')->on('magazine_subcategories');
        });
    }

I want to display the category and the sub-category below. I'm not sure if relationships are correct.

How can I return a subcategory for a given category?

        <ul>
            @foreach($categories as $category)
            <li>{{ $category->name }}
                <ul>
                    @foreach($subcategories as $subcategory) // I dont know how to do it here
                    <li>{{ $subcategory->name }}</li> // I dont know how to do it here
                    @endforeach
                </ul>
            </li>
            @endforeach
        </ul>

0 likes
5 replies
rodrigo.pedra's avatar

As you are using a pivot table, you have a many-to-many relationship, so the relations in your models should be using the belongsToManymethod in both models.

class Magazine_category extends Model
{
    protected $fillable = [ 'name' ];

    public function subcategories()
    {
        return $this->belongsToMany('App\Magazine_subcategory', 'magazine_category_subcategory', 'category_id', 'subcategory_id' );
    }
}

And

class Magazine_subcategory extends Model
{
    protected $fillable = [ 'name' ];

    public function categories()
    {
        return $this->belongsToMany('App\Magazine_category', 'magazine_category_subcategory',  'subcategory_id', 'category_id');
    }
}

Then change your view to use the relationship method:

        <ul>
            @foreach($categories as $category)
            <li>{{ $category->name }}
                <ul>
                    @foreach($category->subcategories as $subcategory)
                    <li>{{ $subcategory->name }}</li>
                    @endforeach
                </ul>
            </li>
            @endforeach
        </ul>

Read more about using many-to-many relationships is the docs: https://laravel.com/docs/5.6/eloquent-relationships#many-to-many

1 like
tykus's avatar

You have a pivot table, but are not using belongsToMany relations?

Do you really need two separate tables for categories and sub-categories; they are essentially the same thing.

FWIW, I would have a single Category model (and table); and (presuming a Sub-Category belong to more than one Category), a pivot table which makes the relationships.

siusiak1000's avatar

Thanks! I have one more problem. How can I add an id from the form to the pivot table? Using Model :: create it does not work.

I have two multiple input fields.

        <div class="row">
            <div class="col-lg-6">
                <h6>Kategorie</h6>
                <div class="form-group">
                    <select multiple class="form-control" id="kategoria" name="kategoria[]">
                    @foreach($categories as $category)
                      <option value="{{ $category->id }}">{{ $category->name }}</option>
                    @endforeach
                    </select>
                </div>
            </div>
            <div class="col-lg-6">
                <h6>Subkategorie</h6>
                <div class="form-group">
                    <select multiple class="form-control" id="subkategoria" name="subkategoria[]">
                    @foreach($subcategories as $subcategory)
                      <option value="{{ $subcategory->id }}">{{ $subcategory->name }}</option>
                    @endforeach
                    </select>
                </div>
            </div>
        </div>
rodrigo.pedra's avatar
Level 56

I don't think I understand what you want, do you want to create multiple associations at once?

If so, in your controller try this:

public function store() {
    $categoriesIds = request()->input('kategoria', []);
    $subcategoriesIds = request()->input('subkategoria', []);

    $categories = \App\Magazine_category::findMany($categoriesIds)
        ->each(function ($category) use ($subcategoriesIds) {
            $category->subcategories()->sync( $subcategoriesIds );
        });

    return redirect()->back(); // or wherever you want to redirect
}
1 like

Please or to participate in this conversation.