

・テーブル構成  
itemは記事テーブルで、channelはサイトテーブルとなっております。  
channel対itemは一対多となっております。  
item:記事テーブル  
channel:サイトテーブル

やりたいこととしてはカテゴリごとの記事を取得したいと思っております。  
現在left joinを用いる以下のコードで取得はできておりますが、  
この状態ですと取得に時間がかかってしまいます。

[code]

    $items = Item::leftJoin('channel', 'item.channel_id', '=', 'channel.id')
    ->select(                                                               
        'item.id',                                                          
        'item.title',                                                       
        'item.description',                                                 
        'item.link',                                                        
        'item.pub_date',                                                    
        'item.channel_id',                                                  
        'channel.title as channel_title',                                   
    )                                                                       
    ->orderBy('pub_date', 'desc')                                           
    ->where('category_id', '=', $category->id)                              
    ->paginate(200);                                                        
    
[/code]

そこで withを用いて取得しようとおもっております。

[code]

    $items = Item::with('channel')
    ->select(                                                               
        'item.id',                                                          
        'item.title',                                                       
        'item.description',                                                 
        'item.link',                                                        
        'item.pub_date',                                                    
        'item.channel_id',                                                  
        'channel.title as channel_title',                                   
    )                                                                       
    ->orderBy('pub_date', 'desc')                                           
    ->where('channel.category_id', '=', $category->id)                              
    ->paginate(200);                                                        
    
[/code]

しかし、 withでは itemにcategory_idをもっていないため  
`->where('channel.category_id', '=', $category->id)`  
が使用できません。  
スマートな方法があれば教えていただけませんか？

テーブル構成は以下です。

channelテーブル

[code]

    CREATE TABLE `channel` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `title` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
      `description` varchar(1000) COLLATE utf8_unicode_ci DEFAULT NULL,
      `link` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
      `rss_link` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
      `sort` int(11) NOT NULL,
      `category_id` int(11) NOT NULL DEFAULT '0',
      `created_at` timestamp NULL DEFAULT NULL,
      `updated_at` timestamp NULL DEFAULT NULL,
      `deleted_at` timestamp NULL DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=122 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
    
[/code]

itemテーブル

[code]

    CREATE TABLE `item` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
      `description` varchar(1000) COLLATE utf8_unicode_ci NOT NULL,
      `link` varchar(512) COLLATE utf8_unicode_ci NOT NULL,
      `pub_date` datetime NOT NULL,
      `channel_id` int(11) NOT NULL,
      `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
      `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
      `deleted_at` timestamp NULL DEFAULT NULL,
      PRIMARY KEY (`id`),
      KEY `channel_id` (`channel_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=183691 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
    
[/code]


CC BY-SA 3.0
2015-08-18T05:44:21.010
14572
2015-08-27T05:04:49.770
2015-08-27T05:04:49.770
7641
7641
question
laravel
Laravel eloquant の with にて結合先テーブルのカラムを where 条件にしたい


whereHas()を組み合わせてはいかがでしょうか。

[code]

    // Categoryテーブルに対するEloquentオブジェクトを想定
    $category = (object) ['id' => 1];
    
    $with = function ($q) use ($category) {
        $q->select(['id', 'title'])->where('category_id', $category->id);
    };
    
    $whereHas = function ($q) use ($category) {
        $q->where('category_id', $category->id);
    };
    
    $columns = [
        'id',
        'title',
        'description',
        'link',
        'pub_date',
        'channel_id',
    ];
    
    $items = \App\Item::with(['channel' => $with])
        ->whereHas('channel', $whereHas)
        ->select($columns)
        ->orderBy('pub_date', 'desc')
        ->paginate(200);
    
[/code]

尚、検証に使用したEloquentクラスは以下の通りです。

\App\Channel

[code]

    <?php
    
    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    
    class Channel extends Model
    {
        protected $table = 'channel';
    
        public function items()
        {
            return $this->hasMany(Item::class);
        }
    }
    
[/code]

\App\Item

[code]

    <?php
    
    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    
    class Item extends Model
    {
        protected $table = 'item';
    
        public function channel()
        {
            return $this->belongsTo(Channel::class);
        }
    }
    
[/code]


CC BY-SA 3.0
2015-08-20T12:04:23.760
14675
2015-08-25T13:30:58.600
2015-08-25T13:30:58.600
589
589
14572
answer