简体   繁体   English

如何从Laravel中的远距离关系中挑选田野

[英]How to pluck fields from a distant relationship in Laravel

I have a many to one relationship for getting each product its images, every product should have a lot of images to view it to user. 我有一个多对一的关系来获取每个产品的图像,每个产品都应该有很多图像以供用户查看。 so I tried to get stocks with images when I do 所以我尝试在有图片的时候拿股票

 public function getImages() {
        $stocks = Stocks::with('images', 'tags')->get();
        return $stocks;
    }

it returns this 它返回这个

[
   {
       "id": 7,
       "name": "1",
       "descriptions": "1",
       "price": 1,
       "discount": 1,
       "category": "new",
       "quantity": 1,
       "brand": "1",
       "created_at": "2019-08-04 09:07:25",
       "updated_at": "2019-08-04 09:07:25",
       "images": [
           {
               "id": 6,
               "url": "1564909645iKiw2LkoEcQIIhB4MTZJTUfwTREleWH4wEuvmRPd.png",
               "created_at": "2019-08-04 09:07:25",
               "updated_at": "2019-08-04 09:07:25",
               "pivot": {
                   "stocks_id": 7,
                   "images_id": 6
               }
           },
           {
               "id": 7,
               "url": "1564909645OVxnM0qmoQayZrP7wq82pTmSj1AwQc9gioyC5L7h.png",
               "created_at": "2019-08-04 09:07:25",
               "updated_at": "2019-08-04 09:07:25",
               "pivot": {
                   "stocks_id": 7,
                   "images_id": 7
               }
           }
       ],
       "tags": [
           {
               "id": 1,
               "tag": "عطور",
               "created_at": "2019-08-03 17:45:52",
               "updated_at": "2019-08-03 17:45:52",
               "pivot": {
                   "stocks_id": 7,
                   "tag_id": 1
               }
           }
       ]
   }
]

but I want "images" to have only urls as strings like: 但我希望“图片”仅包含网址,例如字符串:

"images":[1.png,2.png,3.png .....]

what should I do? 我该怎么办?

my relation 我的关系

public function images()
    {
        return $this->belongsToMany('App\Images', 'stock_images');
    }

You can pass a closure when eager loading relationships with the function with() . 当渴望使用with()函数加载关系时,可以传递闭包。

In that closure you can use the select function to filter columns. 在该关闭中,您可以使用select函数来过滤列。

$stocks = Stock::with('tags')
              ->with(['images' => function ($query) {
                  $query->select(['id', 'url']);
              }])
              ->get();

UPDATE 更新

If you want only the values without keys, you cannot use this approach. 如果只需要没有键的值,则不能使用此方法。 You have to do it after fetching the data from the database. 从数据库中获取数据后,您必须执行此操作。 like this.. 像这样..

$stocks = Stock::with('images', 'tags')->get()->map(function ($stock) {
    $stock->images = $stock->images->map->url->values();

    $stock->unsetRelation('images');

    return $stock;
});

You need to make your query like this: 您需要像这样进行查询:

$stocks = Stock::with(['tags','images' => function ($query) {
              $query->get()->pluck('url');
          }])->get();

but I want "images" to have only urls as strings like: 但我希望“图片”仅包含网址,例如字符串:

 "images":[1.png,2.png,3.png .....] 

what should I do? 我该怎么办?

The quickest solution would be to add the $visible property to your App\\Images model, like so: 最快的解决方案是将$visible属性添加到您的App\\Images模型中,如下所示:

public $visible = ['url'];

This will remove all the fields from the json, including the pivot field, except for those defined in the visible property. 这将删除json中的所有字段,包括pivot字段,但visible属性中定义的字段除外。 This solution works fine but it still selects all columns from the images table, if you want it to select only the minimum required fields (so you improve performance) for the relation, you can do: 此解决方案效果很好,但仍会从图像表中选择所有列,如果您希望它仅选择关系的最低要求字段(以便提高性能),则可以执行以下操作:

$stocks = Stocks::with('images:url', 'tags')->get(); // this is a shortcut for selecting only url

Please, be aware that the solution above works fine for ManyToMany (N:N) relationships. 请注意,上述解决方案适用于ManyToMany(N:N)关系。 However, for a hasMany (1:N), you'd have to select the primary key and all related foreign keys as well. 但是,对于hasMany(1:N),您还必须选择主键以及所有相关的外键。

Hope it helps. 希望能帮助到你。

References: 参考文献:

Eloquent: Relationships#Eager-Loading 雄辩的:关系#渴望加载

UPDATE 更新

It worked but how can I remove the key url: and store only values 1,2,3 它有效,但是如何删除键url:并仅存储值1,2,3

->pluck() is the collection function to do that, however, you can't easily pluck fields from a distant relationship without discarding the rest, but this macro will do the trick. ->pluck()是用于执行此操作的收集函数,但是,您不能轻易地从远距离关系中选择字段而不丢弃其余部分,但是此宏可以解决问题。

->pluckDistant()

In your AppServiceProvider , under the boot method, add this macro function: 在您的AppServiceProvider ,在boot方法下,添加以下宏函数:

public function boot()
{
    /**
     * Shortcut to pluck a field in a relationship.
     *
     * @param string $relationship The relationship name
     * @param string|array $value
     * @param string|null $key
     */
    collect()->macro('pluckDistant', function($relationship, $value, $key = null) {
        return $this->map(function($item) use($relationship, $value, $key) {
            $relation = $item->getRelation($relationship);

            if (get_class($relation) == \Illuminate\Support\Collection::class ||
                get_class($relation) == \Illuminate\Database\Eloquent\Collection::class) {
                $item->setRelation($relationship, $relation->pluck($value, $key));
            }

            return $item;
        });
    });
}

And then, you do this: 然后,您执行以下操作:

$stocks = Stocks::with('images:url', 'tags')->get()->pluckDistant('images', 'url');

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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