ellipsesynergie/api-response

简单包,用于正确处理API中的响应

1.0.0 2024-02-05 21:09 UTC

README

Latest Version Software License Api Response Tests Total Downloads

简单包,用于正确处理API中的响应。此包使用 Fractal,并基于 Build APIs You Won't Hate 一书。

安装

通过 Composer

$ composer require ellipsesynergie/api-response

要求

此版本支持以下PHP版本

>= PHP 8.1

在 Laravel 中安装

将以下服务提供者添加到您的 config/app.php 文件中。

EllipseSynergie\ApiResponse\Laravel\ResponseServiceProvider::class

在 Lumen 中安装

由于请求对象变更(参见参考),您现在无法在服务提供者中正确访问 Request 对象。为了方便,我们创建了一个用于解析 include 参数的中间件。

将此服务提供者注册到您的 bootstrap/app.php 文件中。

$app->register('EllipseSynergie\ApiResponse\Laravel\LumenServiceProvider');

bootstrap/app.php 文件中注册全局中间件。

$app->middleware([
    'EllipseSynergie\ApiResponse\Laravel\Middleware\ParseInclude'
]);

在您喜欢的框架或纯 PHP 中安装

此包可以用于 任何 框架或纯 PHP。您只需扩展 EllipseSynergie\ApiResponse\AbstractResponse 并在您的自定义类中实现 withArray() 方法。您可以通过查看 EllipseSynergie\ApiResponse\Laravel\Response::withArray() 来获取示例。

您还需要使用 fractal 管理器实例来实例化响应类。

// Instantiate the fractal manager
$manager = new \League\Fractal\Manager;

// Set the request scope if you need embed data
$manager->parseIncludes(explode(',', $_GET['include']));

// Instantiate the response object, replace the class name by your custom class
$response = new \EllipseSynergie\ApiResponse\AbstractResponse($manager);

有关 fractal 管理器的更多选项,您可以通过查看 官方 Fractal 网站

在 Laravel 或 Lumen 控制器中的示例

<?php

use EllipseSynergie\ApiResponse\Contracts\Response;

class BookController extends Controller {

    /**
     * @param Response $response
     */
    public function __construct(Response $response)
    {
        $this->response = $response;
    }

    /**
    * Example returning collection
    */
    public function index()
    {
        //Get all books
        $books = Book::all();
    
        // Return a collection of $books
        return $this->response->withCollection($books, new BookTransformer);
    }

    /**
    * Example returning collection with custom key
    */
    public function index()
    {
        //Get all books
        $books = Book::all();
        
        //Custom key
        $customKey = 'books';
    
        // Return a collection of books
        return $this->response->withCollection($books, new BookTransformer, $customKey);
    }

    /**
    * Example returning collection with paginator
    */
    public function index()
    {
        //Get all books
        $books = Book::paginate(15);
       
       // Return a collection of $books with pagination
       return $this->response->withPaginator(
           $books,
           new BookTransformer
       );
    }

    /**
    * Example returning collection with paginator with custom key and meta
    */
    public function index()
    {
        //Get all books
        $books = Book::paginate(15);
        
        //Custom key
        $customKey = 'books';
        
        //Custom meta
        $meta = [
            'category' => 'fantasy'
        ];
       
       // Return a collection of $books with pagination
       return $this->response->withPaginator(
           $books,
           new BookTransformer,
           $customKey,
           $meta
       );
    }

    /**
    * Example returning item
    */
    public function show($id)
    {
        //Get the book
        $book = Book::find($id);
    
        // Return a single book
        return $this->response->withItem($book, new BookTransformer);
    }

    /**
    * Example returning item with a custom key and meta
    */
    public function showWithCustomKeyAndMeta($id)
    {
        //Get the book
        $book = Book::find($id);
        
        //Custom key
        $customKey = 'book';
        
        //Custom meta
        $meta = [
            'readers' => $book->readers
        ];
    
        // Return a single book
        return $this->response->withItem($book, new BookTransformer, $customKey, $meta);
    }
    
    /**
    * Example resource not found
    */
    public function delete($id)
    {
        //Try to get the book
        $book = Book::find($id);

        //Book not found sorry !
        if(!$book){
            return $this->response->errorNotFound('Book Not Found');
        }
    }
    
    /**
    * Example method not implemented
    */
    public function whatAreYouTryingToDo()
    {
        return $this->response->errorMethodNotAllowed("Please don't try this again !");
    }
}

输出示例

一本书

{
    "data": {
        "id": 1,
        "title": "My name is Bob!.",
        "created_at": {
            "date": "2014-03-25 18:54:18",
            "timezone_type": 3,
            "timezone": "UTC"
        },
        "updated_at": {
            "date": "2014-03-25 18:54:18",
            "timezone_type": 3,
            "timezone": "UTC"
        },
        "deleted_at": null
    }
}

书籍集合

{
    "data": [
        {
           "id": 1,
           "title": "My name is Bob!",
           "created_at": {
               "date": "2014-03-25 18:54:18",
               "timezone_type": 3,
               "timezone": "UTC"
           },
           "updated_at": {
               "date": "2014-03-25 18:54:18",
               "timezone_type": 3,
               "timezone": "UTC"
           },
           "deleted_at": null
        },
        {
           "id": 2,
           "title": "Who's your dady ?",
           "created_at": {
               "date": "2014-03-26 18:54:18",
               "timezone_type": 3,
               "timezone": "UTC"
           },
           "updated_at": {
               "date": "2014-03-26 18:54:18",
               "timezone_type": 3,
               "timezone": "UTC"
           },
           "deleted_at": null
        }
    ]
}

错误

{
    "error": {
        "code": "GEN-NOT-FOUND",
        "http_code": 404,
        "message": "Book Not Found"
    }
}

测试包

$ phpunit

在 Laravel 中测试

根据问题 #31,我们发现测试 include 查询参数值时存在一些问题。如果您想在测试中解决这个问题,您必须使用 trait EllipseSynergie\ApiResponse\Testing\Laravel\AddTestingSupportForInclude。要替换 call 方法从 Illuminate\Foundation\Testing\Concerns\MakesHttpRequests::call

贡献

有关详细信息,请参阅 CONTRIBUTING

鸣谢

许可

MIT 许可证(MIT)。有关更多信息,请参阅 许可文件