简体   繁体   中英

Laravel 5 Eloquent hasManyThrough

I have three models. Fairs, Category and Content. Fairs have many Contents and Contents belongs to a Category.

I need to retrieve all the Categories that are related to the Contents that belong to the Fair.

eg Content::with('category', 'subCategory', 'fair', 'fair.coordinates', 'fair.categories')->get()->toArray();

From the Laravel docs, this seemed like it could do what I need: http://laravel.com/docs/5.1/eloquent-relationships#has-many-through

When trying: return $this->hasManyThrough('App\\Content', 'App\\Category', 'category_id');

I get this error:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'categories.category_id' in 'field list' (SQL: select `contents`.*, `categories`.`category_id` from `contents` inner join `categories` on `categories`.`id` = `contents`.`category_id` where `categories`.`category_id` in (1))

Is this possible?

Models:

Category

namespace App;

use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    protected $fillable = ['type', 'name', 'description'];
    protected $hidden = ['created_at', 'updated_at'];

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

Content

namespace App;

use Illuminate\Database\Eloquent\Model;

class Content extends Model
{
    protected $fillable = [
        'type',
        'title',
        'location',
        'latitude',
        'longitude',
        'date',
        'price',
        'position',
        'vip',
        'schedule',
        'content',
        'image',
        'fair_id',
        'category_id',
        'sub_category_id',
    ];

    protected $hidden = ['updated_at', 'category_id', 'sub_category_id', 'fair_id'];

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

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

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

Fair:

namespace App;

use Illuminate\Database\Eloquent\Model;

class Fair extends Model
{

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


    public function categories()
    {
        return $this->hasManyThrough('App\Content', 'App\Category', 'category_id');
    }

    public function coordinates()
    {
        return $this->belongsTo('App\Coordinate', 'coordinate_id')->select(['id', 'longitude', 'latitude']);
    }
}

See below table structure:

fairs

+---------------+------------------+------+-----+---------------------+----------------+
| Field         | Type             | Null | Key | Default             | Extra          |
+---------------+------------------+------+-----+---------------------+----------------+
| id            | int(10) unsigned | NO   | PRI | NULL                | auto_increment |
| name          | varchar(255)     | NO   |     | NULL                |                |
| city          | varchar(255)     | NO   |     | NULL                |                |
| startAt       | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
| stopAt        | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
| availableAt   | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
| color         | varchar(255)     | NO   |     | NULL                |                |
| link          | varchar(255)     | NO   |     | NULL                |                |
| image         | varchar(255)     | NO   |     | NULL                |                |
| ads           | varchar(255)     | NO   |     | NULL                |                |
| created_at    | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
| updated_at    | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
| coordinate_id | int(11)          | YES  |     | NULL                |                |
+---------------+------------------+------+-----+---------------------+----------------+

categories

+-------------+------------------+------+-----+---------------------+----------------+
| Field       | Type             | Null | Key | Default             | Extra          |
+-------------+------------------+------+-----+---------------------+----------------+
| id          | int(10) unsigned | NO   | PRI | NULL                | auto_increment |
| type        | varchar(255)     | NO   |     | NULL                |                |
| name        | varchar(255)     | NO   |     | NULL                |                |
| description | text             | NO   |     | NULL                |                |
| created_at  | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
| updated_at  | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
+-------------+------------------+------+-----+---------------------+----------------+

contents

+-----------------+------------------+------+-----+---------------------+----------------+
| Field           | Type             | Null | Key | Default             | Extra          |
+-----------------+------------------+------+-----+---------------------+----------------+
| id              | int(10) unsigned | NO   | PRI | NULL                | auto_increment |
| type            | varchar(255)     | NO   |     | NULL                |                |
| title           | varchar(255)     | YES  |     | NULL                |                |
| location        | varchar(255)     | NO   |     | NULL                |                |
| latitude        | varchar(255)     | YES  |     | NULL                |                |
| longitude       | varchar(255)     | YES  |     | NULL                |                |
| date            | timestamp        | YES  |     | NULL                |                |
| price           | varchar(255)     | YES  |     | NULL                |                |
| position        | varchar(255)     | YES  |     | NULL                |                |
| vip             | varchar(255)     | YES  |     | NULL                |                |
| schedule        | varchar(255)     | YES  |     | NULL                |                |
| content         | text             | NO   |     | NULL                |                |
| image           | varchar(255)     | YES  |     | NULL                |                |
| fair_id         | int(11)          | NO   |     | NULL                |                |
| category_id     | int(11)          | NO   |     | NULL                |                |
| sub_category_id | int(11)          | NO   |     | NULL                |                |
| created_at      | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
| updated_at      | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
+-----------------+------------------+------+-----+---------------------+----------------+

HasManyThrough 仅在有两个 hasMany 关系时才有效,例如:公平的 hasMany 内容 => 内容有很多类别 然后你可以跳转内容但没有第二个 hasMany 它将不起作用

@RDelorier is correct, but you also have another problem.

Your models are switched in your hasManyThrough() call. The first parameter is the model that you are trying to load, so that one should be App\\Category; the second parameter is the intermediate model, so that one should be App\\Content.

If it is going to work at all, it will work like this:

return $this->hasManyThrough('App\Category', 'App\Content', 'fair_id', 'content_id');

The remaining issue as described by @RDelorier is that this definition expects your Category model to have a content_id attribute, consistent with a hasMany() relationship.

The cleanest way to accomplish what you're after is to just extend the dot-notation chain, using "fair.content.category" instead of "fair.categories".

With your models, if you need a Collection of Category models, you'll have to manually parse the resulting Fair and Content Collections.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM