mafortis
mafortis

Reputation: 7128

Laravel relation issue

I have problem with getting products options they show in separate fields instead of being grouped.

Logic

  1. Option group gets type and values
  2. Options belongs to groups also to products
  3. Products gets Options

Models

Product

public function options(){
  return $this->belongsToMany(Option::class, 'product_options', 'product_id', 'option_id');
}

Option Group

public function values(){
  return $this->hasMany(Option::class, 'option_id');
}

Option

public function group(){
  return $this->belongsTo(OptionGroup::class, 'option_id');
}

public function products(){
  return $this->belongsToMany(Product::class);
}

Blade view

@if(count($product->options)>0)
<!-- options -->
<div class="tt-swatches-container">
    <div class="tt-wrapper">
    @foreach($product->options as $option)
        <div class="tt-title-options">{{$option->group->title}}:</div>
        @if($option->group->type == 'color')
            <ul class="tt-options-swatch options-large">
                <li><a class="options-color" style="background-color: {{$option->color}}" href="#"></a></li>
            </ul>
        @elseif($option->group->type == 'dropdown')
            <form class="form-default">
                <div class="form-group">
                    <select class="form-control">
                        <option>{{$option->title}}</option>
                    </select>
                </div>
            </form>
        @else
            <ul class="tt-options-swatch options-large">
                <li><a href="#">{{$option->title}}</a></li>
            </ul>
        @endif
    @endforeach
    </div>
</div>
<!-- options -->
@endif

Results

one

As you see I have duplicated data in my view, colors must show in one group next to each other, and drop-down options must become one as well.

Anyone can tell where I did mistake?

Update

I've added mapToGroups in my controller now results are much more cleaner but yet has issue with drop-down

Controller

$options = $product->options->mapToGroups(function ($item, $key) {
  return [$item->group->title => $item];
});

Blade

@if(count($options)>0)
<!-- options -->
<div class="tt-swatches-container">
    @foreach($options as $group => $option)
    <div class="tt-wrapper">
        <div class="tt-title-options">{{$group}}:</div>
        @foreach($option as $opt)
        @if($opt->group->type == 'color')
            <ul class="tt-options-swatch options-large">
                <li><a class="options-color" style="background-color: {{$opt->color}}" href="#"></a></li>
            </ul>
        @elseif($opt->group->type == 'dropdown')
            <form class="form-default">
                <div class="form-group">
                    <select class="form-control">
                         <option>{{$opt->title}}</option>
                    </select>
                </div>
            </form>
        @else
            <ul class="tt-options-swatch options-large">
                <li><a href="#">{{$opt->title}}</a></li>
            </ul>
        @endif
        @endforeach
    </div>
    @endforeach
</div>
<!-- options -->
@endif

Result

two

Upvotes: 0

Views: 96

Answers (1)

Mojtaba Hn
Mojtaba Hn

Reputation: 456

Your iteration is quiet wrong. What you are doing is creating a complete ul for each color, a complete select for each dropdown, and also a complete ul for each swatch.

easiest way to achieve your goal is using blade's magical stacks; We just push every option to it's own stack(color,dropdown,swatch) and finally print the stack:

@if(count($product->options)>0)
    @foreach($product->options as $option)
        @if($option->group->type == 'color')
            @push('color')
                <li>
                    <a class="options-color" style="background-color: {{$option->color}}" href="#"></a>
                </li>
            @endpush
        @elseif($option->group->type == 'dropdown')
            @push('dropdown')
                <option>{{$option->title}}</option>
            @endpush
        @else
            @push('swatch')
                <li>
                    <a href="#">{{$option->title}}</a>
                </li>
            @endpush
        @endif
    @endforeach
@endif


<div class="tt-swatches-container">
    <div class="tt-wrapper">
        <div class="tt-title-options">color:</div>
        <ul class="tt-options-swatch options-large">
            @stack('color')
        </ul>
        <div class="tt-title-options">option:</div>
        <form class="form-default">
            <div class="form-group">
                <select class="form-control">
                    @stack('dropdown')
                </select>
            </div>
        </form>
        @if($__env->yieldPushContent('swatch'))
           <div class="tt-title-options">swatch:</div>
           <ul class="tt-options-swatch options-large">
               @stack('swatch')
           </ul>
        @endif
    </div>
</div>

Good Luck.

Upvotes: 1

Related Questions