【问题标题】:Laravel> Using Eloquent Querying many-to-many relationsLaravel> 使用 Eloquent 查询多对多关系
【发布时间】:2017-11-03 10:22:58
【问题描述】:

我试图弄清楚 Eloquent 是如何工作的,以及与使用普通 sql 查询相比的优势(在 columA.id = columnB.id 上连接 A 和 B 表...)

我有两个模型:多对多关系中的渠道和子类别

我创建了一个 channel_subcategory 数据透视表并添加了如下关系:

public function up()
{
    Schema::create('channel_subcategory', function (Blueprint $table) {
        $table->increments('id');
        $table->timestamp('created_at')->useCurrent();
        $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
        $table->integer('channel_id')->unsigned()->nullable();
        $table->foreign('channel_id')->references('id')->on('channels')->onDelete('cascade');
        $table->integer('subcategory_id')->unsigned()->nullable();
        $table->foreign('subcategory_id')->references('id')->on('subcategories') ->onDelete('cascade');
    });
}


I want to get one channel given the slug property and the subcategories it belongs to. So I did this in the ChannelController.php

 public function show($slug)
{
    $channel = Channel::where('channels.slug', '=', $slug)->first();
    foreach ($channel as $subcategory) {
        echo $subcategory->title;
    }
}

I get the error:

ErrorException in ChannelController.php line 107: Trying to get property of non-object


All I want is to show the channel name and the categories it belongs to.

我阅读了很多博客,包括 Laravel 文档,它们总是解释迁移、如何在模型中建立关系(属于自己的),甚至如何保存相关数据。但是我在任何地方都没有找到一个说明(针对假人),现在让我们从两个表中获取一些数据,例如:

  • 获取一个频道所属的所有类别。
    • 获取一个类别中的所有频道
    • 获取属于多个类别的所有频道
    • 获取频道更多的类别。

换句话说,一个关于如何做到这一点的简单解释。

编辑 添加我的频道模型

public function subcategory()
{
    return $this->belongsToMany('App\Subcategory')->withTimestamps();
}

【问题讨论】:

    标签: laravel eloquent many-to-many querying


    【解决方案1】:

    您需要在模型中定义关系。在您的情况下,您应该在 Channel 模型中创建 subcategories 关系。

    public function subcategories()
    {
        return $this->belongsToMany(Subcategory::class, 'channel_subcategory', 'channel_id', 'subcategory_id')->withTimestamps();
    }
    

    SubCategory 更改为您为模型命名的任何名称。

    然后在您的控制器中,您可以像这样访问关系

    $channel = Channel::where('slug', $slug)->first();
    
    foreach ($channel->subcategories as $subcategory) {
        echo $subcategory->title;
    }
    

    虽然上述代码有效,但如果您需要关系数据,则应始终预先加载。这可以防止 N+1 查询问题。

    $channel = Channel::with('subcategories')->where('slug', $slug)->first();
    

    【讨论】:

    • 我用我的频道模型编辑了我的问题。这是不正确的吗?如果我“var_dump”我得到什么,我会看到频道的名称以及 ot 所属类别的名称。我认为,我的问题是试图呼应子类别的名称。因此它说:试图获得非对象的属性
    • 您的问题中的循环循环通过$channel 这不是子类别。检查我显示的循环。还修复了我的代码中的关系。我在更改示例中的关系字段时犯了一个错误。
    • 谢谢哥们!!!。经过几天的尝试,它可以工作了!顺便说一句:您知道任何教程,我可以在其中解释并构建我发布的此类查询吗? (类别中的所有频道,具有更多频道的类别,没有类别的频道等)?我接受你的回答。再次感谢
    • 你要问的很简单。一开始它可能看起来很复杂,但是一旦你写了你的第一个关系,它就变得容易了。官方文档有关于你需要什么的很好的信息laravel.com/docs/5.4/eloquent-relationships#many-to-many。您唯一需要知道的另一件事是急切加载和关系检查,它们是with()load()has()whereHas()。这里有一些很好的教程。
    猜你喜欢
    • 2014-10-31
    • 1970-01-01
    • 2019-06-13
    • 2019-01-15
    • 1970-01-01
    • 1970-01-01
    • 2015-11-10
    • 2021-08-27
    相关资源
    最近更新 更多