Laravel 6雄辩的多类别关系

时间:2020-06-29 19:56:00

标签: php laravel

我创建了3个数据库模型。一种是保存父类别,另一种是子类别,第三种是属于这些类别的帖子。

层次结构如下:

Parent
--Subcategory
----Post1
----Post2
----etc

我在模型上创建了以下关系:

子类别模型:

public function getCategoryDetails() 
{
    return $this->hasOne('App\Models\Categories' , 'id' ,'catId');
}

public function getPosts() 
{
    return $this->hasMany('App\Models\Posts' , 'catId' ,'id');
}

帖子模型:

public function getSubcategoryDetails() 
{
    return $this->hasOne('App\Models\Subcategories' , 'id' ,'catId');
}

这是视图中的代码:

    <div class="card mt-2">
    <h5 class="card-header bg-dark text-white d-flex align-items-center">Tillgänliga Kurser från denna arrangör</h5>
        <div class="card-body"> 
        @foreach($posts as $post)
        <div class="card-title">
        {{ $post->getSubcategoryDetails->getCategoryDetails->name }}
        </div>
        <div class="card-title">
        {{ $post->getSubcategoryDetails->name }}
        </div>
        <a href="/kategorier/{{ $post->getSubcategoryDetails->getCategoryDetails->slug }}/kurser/{{ $post->getSubcategoryDetails->slug }}/annons/{{ $post->slug }}">{{ $post->name }}</a>
        <br>
        @endforeach            
        </div>
            <!-- //Project Description Section End -->
    </div>  

现在这段代码几乎可以完全满足我的要求:显示每个帖子的类别,然后为每个帖子创建一个有效的链接。

但是,上面的代码在每次迭代时都重复类别,这是不希望的。我希望它只显示每个类别一次,结果显示在其下方。预期结果的示例:

Parent Category 1
--Subcategory 1
----Post1
----Post2
Parent Category 2
--Subcategory 1
----Post1
--Subcategory 2
----Post1

但是,即使帖子属于类别/子类别的相同组合,我的代码也始终在每次迭代的每个帖子上方显示类别和子类别。现在如何工作的示例:

Parent Category 1
--Subcategory 1
----Post1
Parent Category 1
--Subcategory 1
----Post2
Parent Category 2
--Subcategory 1
----Post1
Parent Category 2
--Subcategory 2
----Post1

2 个答案:

答案 0 :(得分:0)

您可以在map上使用groupByCollection(Laravel查询返回集合)。

$posts->map(function($post, $key) {
    $post['category'] = [
        'name' => $post->getSubcategoryDetails->getCategoryDetails->name,
        'slug' => $post->getSubcategoryDetails->getCategoryDetails->slug,
    ];
    $post['subcategory'] = [
        'name' => $post->getSubcategoryDetails->name,
        'slug' => $post->getSubcategoryDetails->slug,
    ];

    return $post;
})->groupBy(['category.slug', 'subcategory.slug']);

最小示例

假设您的 Post 收藏是这样的。

$posts = collect([
    [
        'title' => 'post title 1',
        'slug' => 'post-title-1',
        'category_id' => 1,
        'subcategory' => 1,
    ],
    [
        'title' => 'post title 2',
        'slug' => 'post-title-2',
        'category' => 2,
        'subcategory' => 2,
    ],
    [
        'title' => 'post title 3',
        'slug' => 'post-title-3',
        'category' => 1,
        'subcategory' => 3,
    ],
    [
        'title' => 'post title 4',
        'slug' => 'post-title-4',
        'category' => 2,
        'subcategory' => 4,
    ],
]);

使用map检索每个 Post category subcategory Post 集合将被这样修改。

$posts = collect([
    [
        'title' => 'post title 1',
        'slug' => 'post-title-1',
        'category_id' => 1,
        'subcategory' => 1,
        'category' => [
            'name' => 'category 1',
            'slug' => 'category-1',
        ],
        'subcategory' => [
            'name' => 'subcategory 1',
            'slug' => 'subcategory-1',
        ],
    ],
    [
        'title' => 'post title 2',
        'slug' => 'post-title-2',
        'category' => 2,
        'subcategory' => 2,
        'category' => [
            'name' => 'category 2',
            'slug' => 'category-2',
        ],
        'subcategory' => [
            'name' => 'subcategory 2',
            'slug' => 'subcategory-2',
        ],
    ],
    [
        'title' => 'post title 3',
        'slug' => 'post-title-3',
        'category' => 1,
        'subcategory' => 3,
        'category' => [
            'name' => 'category 1',
            'slug' => 'category-1',
        ],
        'subcategory' => [
            'name' => 'subcategory 3',
            'slug' => 'subcategory-3',
        ],
    ],
    [
        'title' => 'post title 4',
        'slug' => 'post-title-4',
        'category' => 2,
        'subcategory' => 4,
        'category' => [
            'name' => 'category 2',
            'slug' => 'category-2',
        ],
        'subcategory' => [
            'name' => 'subcategory 4',
            'slug' => 'subcategory-4',
        ],
    ],
]);

Post 集合的结果上使用groupBy

$posts->groupBy(['category.slug', 'subcategory.slug']);

在Tinker(php artisan tinker)上运行后的输出。

Illuminate\Support\Collection {#3718
  all: [
    "category-1" => Illuminate\Support\Collection {#3816
      all: [
        "subcategory-1" => Illuminate\Support\Collection {#3817
          all: [
            [
              "title" => "post title 1",
              "slug" => "post-title-1",
              "category" => [
                "name" => "category 1",
                "slug" => "category-1",
              ],
              "subcategory" => [
                "name" => "subcategory 1",
                "slug" => "subcategory-1",
              ],
            ],
          ],
        },
        "subcategory-3" => Illuminate\Support\Collection {#3814
          all: [
            [
              "title" => "post title 3",
              "slug" => "post-title-3",
              "category" => [
                "name" => "category 1",
                "slug" => "category-1",
              ],
              "subcategory" => [
                "name" => "subcategory 3",
                "slug" => "subcategory-3",
              ],
            ],
          ],
        },
      ],
    },
    "category-2" => Illuminate\Support\Collection {#3706
      all: [
        "subcategory-2" => Illuminate\Support\Collection {#3736
          all: [
            [
              "title" => "post title 2",
              "slug" => "post-title-2",
              "category" => [
                "name" => "category 2",
                "slug" => "category-2",
              ],
              "subcategory" => [
                "name" => "subcategory 2",
                "slug" => "subcategory-2",
              ],
            ],
          ],
        },
        "subcategory-4" => Illuminate\Support\Collection {#3721
          all: [
            [
              "title" => "post title 4",
              "slug" => "post-title-4",
              "category" => [
                "name" => "category 2",
                "slug" => "category-2",
              ],
              "subcategory" => [
                "name" => "subcategory 4",
                "slug" => "subcategory-4",
              ],
            ],
          ],
        },
      ],
    },
  ],
}

答案 1 :(得分:0)

嗯,这就是我最后所做的:

帖子模型:

public function Subcategory() 
{
    return $this->belongsTo('App\Models\Subcategories' , 'id' ,'catId');
}

public function getSubcategoryDetails() 
{
    return $this->hasOne('App\Models\Subcategories' , 'id' ,'catId');
}

子类别模型:

public function getCategoryDetails() 
{
    return $this->hasOne('App\Models\Categories' , 'id' ,'catId');
}

public function getPosts() 
{
    return $this->hasMany('App\Models\Posts' , 'catId' ,'id');
}

控制器:

$organizerDetails   = Organizers::where('slug', $slug)->first();
$posts              = Subcategories::with('getCategoryDetails')->with('getPosts')->whereHas('getPosts', function($q) use ($organizerDetails) {
                    $q->where('organizerId', $organizerDetails->id);
                    })->get()->groupBy('getCategoryDetails.name');

查看:

    <div class="card mt-2">
    <h5 class="card-header bg-dark text-white d-flex align-items-center">Tillgänliga Kurser från denna arrangör</h5>
        <div class="card-body">      
        @foreach($posts as $post => $details)           
            {{ $post }}
            <br>
            @foreach ($details as $singlePost)                        
            {{ $singlePost->name }}
                <br>
                @foreach ($singlePost->getPosts as $course)          
                <a href="/kategorier/{{ $singlePost->getCategoryDetails->slug }}/kurser/{{ $course->getSubcategoryDetails->slug }}/annons/{{ $course->slug }}">{{ $course->name }}</a>
                <br>
                @endforeach
            @endforeach
        @endforeach        
        </div>
            <!-- //Project Description Section End -->
    </div>