7

image

文章转发在专业的Laravel开发者社区,原始链接:https://learnku.com/laravel/t...

在过去的2年时间里,我一直使用 Fractal 来进行 API 开发。

如果说一个我最希望 Laravel可以增加的功能的话,无疑是方便的数据转换,以便开发更好的 API 接口。

别误会, Fractal 很好用,然而我总是希望能只用框架进行开发。如果可以的话,我尽可能不使用类库!我不喜欢使用第三方类库使得开发复杂化。

在过去的一年里,我喜欢使用一些前端框架如 Vue 和 React 来进行开发。因此,我选择只使用 Laravel来建立 API 接口。 而当我需要建立 API 接口 的时候,Fractal是我首选的类库。 现在,情况发生了变化。

在 Laravel 5.5 中,我们有了 API 资源,对此,我真的是非常的兴奋。

在2小时前,Laravel 5.5 发布了,当时我正和朋友一起喝咖啡。当我在半小时前读到这条推的时候,脑子里的第一个想法就是用 API 资源来发布我的第一篇博客文章,我也确实这么做了。

Laravel 的 API 资源是基于 Fractal , 因此,我并没有花太多时间来了解如何使用它。 所以,让我们开始来了解它吧 ...

创建 Laravel 应用

用常用的命令行来创建 Laravel 应用

composer create-project laravel/laravel Laravel55Api

应用创建完成后,将 .env.example 重命名为 .env 并用以下命令生成 Laravel 密钥。

php artisan key:generate

启动服务

php artisan serve

很好,接下来是什么呢?

创建一个 Product 资源

API 资源是在 Laravel 中将你的模型以及模型集合转换为 JSON 的新特性。接下来让我们创建一个 Product 的资源。

php artisan make:resource Product

你可以在 app/Http/Resources 目录下看到你刚刚生成的 Product 资源

当然我们还需要 Product 的数据库迁移、模型和控制器。我们能用这个命令快速的创建这些。

php artisan make:model Product -mc

打开数据库迁移文件然后像这样修改 up 方法里面的内容:

public function up()
{
    Schema::create('products', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name');
        $table->integer('price');
        $table->timestamps();
    });
}

注意这里的价格字段是整型的。 我拜托你们,永远不要用浮点型存储你的价格数据!

一定要用整型来存储!

现在用你的 Laravel 应用连接数据库并运行这个迁移以生成数据表。

本文不是 Laravel 一对一教学贴,所以我不会在连接数据库的问题上浪费你过多的时间。

接下来?

到目前为止,我们已经有模型,控制器,数据库迁移以及用以转换模型和模型集合为 JSON 的资源类。那么接下来呢?

在这之前,什么是资源类?我们在 resources 文件夹中创建的 Product 类又是什么?一个资源类表示了单个模型转换为 JSON 的结构。

结合上面所阐述的,让我们来打开 Product.php 资源类文件。

这里有一个 toArray 方法,这个就是在我们发送响应时返回需要转换为 JSON 的属性数组的方法。

我们来修改它,让我们可以有更好的点子。

public function toArray($request)
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'price' => $this->price,
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
    ];
}

现在表示我们能够获得有 id, name, price, created_atupdated_at 这些字段的响应。

如果我们在 toArray 方法中去掉 price 字段,返回的 JSON 中就不会有 price 。很酷不是吗?

使用 Product 资源

我们刚刚更改了 toArray 方法,让我们继续在我们的控制器中使用 product 资源。

product 控制器是看起来是这样的:

<?php

namespace App\Http\Controllers;

use App\Product;
use App\Http\Resources\Product as ProductResource;

class ProductController extends Controller
{
    public function show ($id)
    {
        return new ProductResource(Product::find($id));
    }
}

为了转换 product ,我们仅仅在 product 资源类中传递了一个 product

让我们创建一个 show 方法的路由,看一看结果。

打开 api.php 文件,在中间件外部创建这个路由。

Route::get('/products/{id}', 'ProductController@show');

现在,手动的在你的 products 表里添加一个新的 product,然后访问http://127.0.0.1:8000/api/pro...看看一个简单的 product

你应该得到这样的结果:

image

现在让我们来修改一点我们的资源,假如你不想公开你的 productprice,你要做的就是简单的从你的 toArray 方法删除它。一旦你从 toArray 方法删除了 price,你应该得到这样的结果,当然不包括 price

image

就这些吗?

当然不是!因为 toArray 方法仅仅是一个方法,它意味着你可以包含额外的信息。

假如我们想要包括一个「test」信息,简单的改变你的 toArray 方法。

public function toArray($request)
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'test' => 'This is just a test',
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
    ];
}

这是结果:

image

然而,非常要重的是,你希望返回的数据类型总是正确的。在第一个截图上看看 price,它返回的是一个 integer,但是通过 (int) $this->price,我们仍然要强制它是一个integer

现在,看看 create_atupdated_at 时间戳。如果你想要的是返回一个实际时间戳的字符串?那么你可以像这个例子中,强制类型转换为字符串:

public function toArray($request)
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'test' => 'This is just a test',
        'created_at' => (string)$this->created_at,
        'updated_at' => (string)$this->updated_at,
    ];
}

现在的结果是这个:

image

结束语

这仅仅是使用 Laravel API 资源的一个小例子。

如果我继续写下去,这篇文章永远也写不完。

所以,这篇文章就写到这吧,正如你所知道的,我们还有更多话题需要讨论,比如分页、资源集合、关联以及数据包裹等。


summerblue
11k 声望15.4k 粉丝

刻意练习,每日精进