Laravel5.5+ 怎么使用API Resources快速输出自定义JSON
创始人
2024-11-30 00:23:19
0次

JS是什么

JS是JavaScript的简称,它是一种直译式的脚本语言,其解释器被称为JavaScript引擎,是浏览器的一部分,主要用于web的开发,可以给网站添加各种各样的动态效果,让网页更加美观。


从Laravel 5.5+开始,加入了API Resources这个概念。

我们先来看一下官网如何定义这个概念的:

When building an API, you may need a transformation layer that sits between your Eloquent models and the JSON responses that are actually returned to your application's users. Laravel's resource classes allow you to expressively and easily transform your models and model collections into JSON.

可能看完这个概念之后,你仍然有点不明白,毕竟这个定义说的有点含糊。

如果你熟悉使用API进行输出,构架前后端分离的网络应用,那么你应该会发现,当我们使用Eloquent从数据库中取出数据后,如果想以JSON格式进行输出,那么我们可以使用->toJson()这个方法,这个方法可以直接将我们的model序列化(这个方法从Laravel 5.1+开始就可以使用了):

$user = App\User::find(1);

return $user->toJson();

使用多了,我们会发现,在model较为复杂,或者model中有很多我们API输出可能用不到的字段的情况下,toJson()仍然会忠实地帮我们把这些字段序列化出来。

这个时候,我们会想,如何将model中的某些字段隐藏起来,不输出到JSON中。另外一种情况,比如字段是password等一些敏感信息的时候,我们不希望JSON数据里包含这样的敏感信息。

要解决这个问题,我们可以在model里定义$hidden或者$visible这两个数组来进行字段的隐藏或者显示:

那么你可能会想,我们已经有了可以自动序列化的方法,以及可以隐藏或者显示指定字段的方法,这样不就足够了吗?

现在我们来假设一个简单的应用场景。假设我们在输出一个客户列表,里面包含了客户名字和送货地址。我们使用Customer这个model定义客户,使用ShippingAddress这个model进行定义送货地址。为了简化场景,我们的客户只有一个送货地址,所以只会出现一一对应的情况。

那么在ShippingAddress对应的数据库表shipping_addresses中,我们可能会有如下定义:

| id | country_id | province_id | city_id | address |

字段类型我就不赘述了,其中country_id、province_id以及city_id这三个外键分别对应了国家、省份以及城市表中的id。

而Customer对应的customers表中,会有shipping_address_id这个外键指向shipping_addresses表中的id。

那么我们要输出顾客和送货地址,我们需要先在model中定义好relationship:

belongsTo(ShippingAddress::class);
  }
}
belongsTo(Country::class);
  }
  
  public function province()
  {
    return $this->belongsTo(Province::class);
  }
  
  public function city()
  {
    return $this->belongsTo(City::class);
  }
}

在我们的控制器中,我们拉取出所有客户:

get();
    
    //这里可以直接返回Eloquent Collections或Objects,toJson()将自动被调用
    return $customers;
  }
}

那么输出的JSON将会包含了多个层级的关系,那么在我们前端调用的时候,将会非常麻烦,因为我们需要一层一层剥开Object关系。

但是如果你熟悉Laravel,你可能会说,慢着!这个情况我可以用accessor不就完事儿了吗?

是的,我们确实可以使用accessor来简化我们的数据层级:

/**
 * Get the customer's full shipping address
 *
 * @return string
 */
public function getFullShippingAddressAttribute()
{
  return "{$this->shippingAddress->country->name} {$this->shippingAddress->province->name} {$this->shippingAddress->city->name} {$this->shippingAddress->address}";
}

但是我们还需要一步操作。由于customers这张表本身没有full_shipping_address这个字段,要使我们的JSON输出包含full_shipping_address,我们需要添加$appends数组:

对于每一个我们想自定义的JSON字段,我们都需要进行上面两部的操作。这样一来其实非常麻烦,并且不利于代码的维护,因为这会让原本简洁的model显得很复杂。

基于以上原因,我们需要一个中间层,在我们输出model成为JSON的时候,可以进行一次信息的过滤及加工。

那么还是使用我们上面的应用场景。要输出自定义的字段再简单不过了。我们不需要在model里定义各种accessor,也不需要使用黑白名单过滤字段,只需要新建一个Resource类:

$ php artisan make:resource Customer

然后我们可以看到,在app/Http文件夹下,多出了一个名为Resources文件夹下,其中含有一个名为Customer.php的文件:

这里我们看到其中有且仅有一个名为toArray的方法。这就是我们要自定字段的地方:

 public function toArray($request)
  {
    return [
      'fullName' => $this->first_name . $this->last_name,
      'fullShippingAddress'  => $this->shippingAddress->country->name . $this->shippingAddress->province->name . $this->shippingAddress->city->name . $this->shippingAddress->address,
    ];
  }

注意到,无论是fullName还是fullShippingAddress,都是不存在于customers表中的字段。

接着,我们只需要简单修改一下我们的控制器:

get();
    
    //这里我们使用了新的Resource类
    return CustomerResource::collection($customers);
  }
}

这样就OK了!我们输出的JSON数据中,将会仅仅含有以上两个字段,即fullName和fullShippingAddress,非常干净,并且前端直接可用,不需要二次再加工。

唯一需要注意的是,这里由于我们拉取了多个Customer,所以我们用了每个Resource类都自带有的collection方法,将一个Collection中的所有对象都进行处理。而若要处理单个对象,我们需要使用以下代码:

public function show($id)
{
  $customer = Customer::findOrFail($id);
  return new CustomerResource($customer);
}

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...