基于以上原因,我们需要一个中间层,在我们输出model成为JSON的时候,可以进行一次信息的过滤及加工。
那么还是使用我们上面的应用场景。要输出自定义的字段再简单不过了。我们不需要在model里定义各种accessor,也不需要使用黑白名单过滤字段,只需要新建一个Resource类:
$ php artisan make:resource Customer
然后我们可以看到,在app/Http文件夹下,多出了一个名为Resources文件夹下,其中含有一个名为Customer.php的文件:
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class Customer extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return parent::toArray($request);
}
}
这里我们看到其中有且仅有一个名为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表中的字段。
接着,我们只需要简单修改一下我们的控制器:
<?php
namespace App\Http\Controllers;
use App\Customer;
use App\Http\Resources\Customer as CustomerResource;
use App\Http\Controllers\Controller;
class CustomerController extends Controller
{
/**
* Simple function to fetch all customers with their shipping addresses
*
* @return String
*/
public function index()
{
$customers = Customer::with(['shippingAddress', 'shippingAddress.country', 'shippingAddress.province', 'shippingAddress.city'])->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);
}
要了解更多关于API Resources的详情,请戳官网文档:
