Laravel 5.5 ApiResource 简单封装 (类似于 dingo-API 的响应)

直接上代码 artisan 命令来生成资源类
php artisan make:resource UserResource

生成的 UserResource.php

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\Resource;

class UserResource extends Resource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request $request
     * @return array
     */
    public function toArray($request)
    {
        // return parent::toArray($request);
        return [
            'id'         => $this->id,
            'name'       => $this->name,
            'email'      => $this->email,
            'created_at' => $this->created_at->toDateTimeString(),
            'updated_at' => $this->updated_at->toDateTimeString(),
        ];

    }

    // public function with($request)
    // {
    //  return [
    //      'meta' => [
    //          'key' => 'value',
    //      ],
    //  ];
    // }
}

ApiController.php 代码

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Resources\UserResource;
use App\User;

class ApiController extends Controller
{
    protected $user;
    use Helper;

    /**
     * ApiController constructor.
     * @param User $user
     */
    public function __construct(User $user)
    {
        $this->user = $user;
    }

    public function index()
    {

        $user = $this->user->find(1);
        // 响应一个元素
        return $this->item($user, UserResource::class);

        // $users = $this->user->all();
        // // 响应一个元素集合
        // return $this->collection($users,UserResource::class);

        // $users = $this->user->paginate();
        // // 分页响应
        // return $this->paginator($users, UserResource::class);

        // // 无内容响应
        // $this->noContent();
        // // 一个 bad request 错误
        // $this->errorBadRequest();

    }
}

ApiController中用到的 Helper trait 代码

 <?php

namespace App\Http\Controllers\Api;

use Illuminate\Contracts\Pagination\Paginator;
use Illuminate\Http\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;

trait Helper
{
    /**
     * Respond with a created response and associate a location if provided.
     *
     * @param null|string $location
     * @param null        $content
     * @return Response
     */
    public function created($location = null, $content = null)
    {
        $response = new Response($content);
        // 201
        $response->setStatusCode(Response::HTTP_CREATED);
        if (! is_null($location)) {
            $response->header('Location', $location);
        }

        return $response;
    }

    /**
     * Respond with an accepted response and associate a location and/or content if provided.
     *
     * @param null|string $location
     * @param mixed       $content
     *
     * @return Response
     */
    public function accepted($location = null, $content = null)
    {
        $response = new Response($content);
        // 202
        $response->setStatusCode(Response::HTTP_ACCEPTED);

        if (! is_null($location)) {
            $response->header('Location', $location);
        }

        return $response;
    }

    /**
     * Respond with a no content response.
     *
     * @return Response
     */
    public function noContent()
    {
        $response = new Response(null);
        // 204
        return $response->setStatusCode(Response::HTTP_NO_CONTENT);
    }

/**
     * Return a json response.
     * @param array $data
     * @param array $headers
     * @return Response
     */
    public function json($data = [], array $headers = [])
    {
        return new Response(compact('data'),Response::HTTP_OK,$headers);
    }

    /**
     *  Bind an item to a apiResource and start building a response.
     * @param       $data
     * @param       $resourceClass
     * @param array $meta
     * @return mixed
     */
    public function item($data, $resourceClass, $meta = [])
    {
        if (count($meta)) {
            return (new $resourceClass($data))->additional($meta);
        }
        return new $resourceClass($data);
    }

    /**
     * Bind a collection to a apiResource and start building a response.
     *
     * @param       $data
     * @param       $resourceClass
     * @param array $meta
     * @return Response
     */
    public function collection($data, $resourceClass, $meta = [])
    {
        if (count($meta)) {
            return $resourceClass::collection($data)->additional($meta);
        }
        return $resourceClass::collection($data);
    }

    /**
     * Bind a paginator to a apiResource and start building a response.
     *
     * @param Paginator $paginator
     * @param           $resourceClass
     * @param array     $meta
     * @return Response
     */
    public function paginator(Paginator $paginator, $resourceClass, array $meta = [])
    {
        return $this->collection($paginator,$resourceClass,$meta);
    }

    /**
     * Return an error response.
     *
     * @param string $message
     * @param        $statusCode
     * @return void
     */
    public function error($message, $statusCode=400)
    {
        // return new Response(compact('message','status_code'),$status_code,$header);
        throw new HttpException($statusCode, $message);
    }

    /**
     * Return a 404 not found error.
     *
     * @param string $message
     *
     * @throws \Symfony\Component\HttpKernel\Exception\HttpException
     *
     * @return void
     */
    public function errorNotFound($message = 'Not Found')
    {
        // 404
        $this->error($message, Response::HTTP_NOT_FOUND);
    }

    /**
     * Return a 400 bad request error.
     *
     * @param string $message
     *
     * @throws \Symfony\Component\HttpKernel\Exception\HttpException
     *
     * @return void
     */
    public function errorBadRequest($message = 'Bad Request')
    {
        // 400
         $this->error($message, Response::HTTP_BAD_REQUEST);
    }

    /**
     * Return a 403 forbidden error.
     *
     * @param string $message
     *
     * @throws \Symfony\Component\HttpKernel\Exception\HttpException
     *
     * @return void
     */
    public function errorForbidden($message = 'Forbidden')
    {
         // 403
        $this->error($message, Response::HTTP_FORBIDDEN);
    }

    /**
     * Return a 500 internal server error.
     *
     * @param string $message
     *
     * @throws \Symfony\Component\HttpKernel\Exception\HttpException
     *
     * @return void
     */
    public function errorInternal($message = 'Internal Error')
    {
        // 500
        $this->error($message, Response::HTTP_INTERNAL_SERVER_ERROR);
    }

    /**
     * Return a 401 unauthorized error.
     *
     * @param string $message
     *
     * @throws \Symfony\Component\HttpKernel\Exception\HttpException
     *
     * @return void
     */
    public function errorUnauthorized($message = 'Unauthorized')
    {
        // 401
        $this->error($message, Response::HTTP_UNAUTHORIZED);
    }

    /**
     * Return a 405 method not allowed error.
     *
     * @param string $message
     *
     * @throws \Symfony\Component\HttpKernel\Exception\HttpException
     *
     * @return void
     */
    public function errorMethodNotAllowed($message = 'Method Not Allowed')
    {
        // 405
        $this->error($message, Response::HTTP_METHOD_NOT_ALLOWED);
    }

}

异常处理文件中 Handler.php render()方法添加 HttpException处理

<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Http\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;

class Handler extends ExceptionHandler
{
    /**
     * A list of the exception types that are not reported.
     *
     * @var array
     */
    protected $dontReport = [
        //
    ];

    /**
     * A list of the inputs that are never flashed for validation exceptions.
     *
     * @var array
     */
    protected $dontFlash = [
        'password',
        'password_confirmation',
    ];

    /**
     * Report or log an exception.
     *
     * This is a great spot to send exceptions to Sentry, Bugsnag, etc.
     *
     * @param  \Exception $exception
     * @return void
     * @throws Exception
     */
    public function report(Exception $exception)
    {
        parent::report($exception);
    }

    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Exception  $exception
     * @return \Illuminate\Http\Response
     */
    public function render($request, Exception $exception)
    {
        if ($exception instanceof HttpException) {
            $message = $exception->getMessage();
            $status_code = $exception->getStatusCode();
            return new Response(compact('message','status_code'),$status_code);
        }
        return parent::render($request, $exception);
    }
}

本文章首发在 Laravel China 社区