Laravel将请求解析为具有关系的Eloquent模型

时间:2017-02-23 17:02:39

标签: php json laravel api laravel-5

我正在开发一个Laravel API,用于托管和管理移动应用程序的数据。我正在编写的应用程序将发出AJAX请求并通过JSON数据发送到Laravel控制器。

这适用于基本模型但是我无法使其适用于嵌套模型。我会解释:

所以我有以下模型结构:

货架 ---- 有很多 ----> 方框 ---- 有很多 ---->的产品

搁板:

class Shelf extends Model
{
    protected $fillable = ['name', 'location'];

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

箱:

class Box extends Model
{
    protected $fillable = ['name', 'size', 'label'];

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

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

产品:

class Product extends Model
{
    protected $fillable = ['name', 'price', 'quantity'];

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

在保存任何内容之前,我的所有模型都会进行验证检查。

我将以下请求发送给我的Laravel控制器:

{
  "name":"Shelf 1",
  "location":"LOC1"
  "boxes":[{
    "name":"box 1",
    "size": 130,
    "label": "B1",
    "products":[
      {"name":"Prod1","price":23.00,"quantity":5},
      {"name":"Prod2","price":13.00,"quantity":2}
    ]
  }, {
    "name":"box 2",
    "size": 130,
    "label": "B2",
    "products":[
      {"name":"Prod3","price":3.00,"quantity":15},
      {"name":"Prod4","price":7.00,"quantity":8}
    ]
  }, {
    "name":"box 3",
    "size": 160,
    "label": "B3",
    "products":[
      {"name":"Prod5","price":103.00,"quantity":9},
      {"name":"Prod6","price":83.00,"quantity":1}
    ]
  }]
}

当我在Laravel控制器中收到上述数据时,我使用:

$shelf = new Shelf;
$shelf->fill($request->all());
$shelf->save();

要获取所有数据,但这只会保存Shelf而不是任何关系。是否有一种常用的方法(或库)可以用来解析Laravel控制器中的JSON?

1 个答案:

答案 0 :(得分:4)

据我所知,Eloquent并没有提供类似的东西。您需要单独保存每个。我可以建议这样的事情:

$shelf = Shelf::create($request->only(['name', 'location']));
foreach ( $request->input('boxes') as $box )
{
    $box = new Box($box);
    $shelf->boxes()->save($box);
    $pTemp = [];
    foreach ( $box['products'] as $product )
    {
        $pTemp[] = new Product($product);
    }
    $box->products()->saveMany($pTemp);
}

更新

为了最大限度地减少运行查询的次数,我们可以循环遍历所有框,创建它们然后再循环遍历它们以创建所有产品。你仍然需要为每个盒子运行一个查询来创建产品,但据我所知,没有办法解决这个问题。

$shelf = Shelf::create($request->only(['name', 'location']));
$bTemp = [];
foreach ( $request->input('boxes') as $i => $box )
{
    $bTemp[$i] = new Box($box);
}
$shelf->boxes()->saveMany($bTemp);
foreach ( $request->input('boxes') as $i => $box )
{
    $pTemp = [];
    foreach ( $box['products'] as $product )
    {
        $pTemp[] = new Product($product);
    }
    $bTemp[$i]->products()->saveMany($pTemp);
}