+5

Build API dùng Laravel và GraphQL (Part 1)

GraphQL is a query language for your API, and a server-side runtime for executing queries by using a type system you define for your data. GraphQL isn't tied to any specific database or storage engine and is instead backed by your existing code and data.

GraphQL có thể tăng tính linh hoạt khi gọi API, chúng ta có thể chỉ định dữ liệu với ngôn ngữ truy vấn giống như viết truy vấn trong cơ sở dữ liệu để truy cập API. GraphQL đã có user interface để giúp chúng ta viết truy vấn và có autocomplete khi chúng ta gõ một số truy vấn, điều này thật tuyệt vời: D nó làm cho việc viết query trở lên dễ dàng.

Cùng xem sơ đồ sau: Sơ đồ dưới đây cho thấy GraphQL giống như Rest, nó cũng chạy bên ngoài lớp business logic. Chi tiết tại đây. Hoặc để có thêm thông tin về Graphql bạn có thể xem thêm tại đây.

Bây giờ sẽ là các bước.

1. Cài đặt Laravel

# run in terminal
composer global require "laravel/installer"
laravel new laravel-graphql

2. Cài đặt Package GraphQL

Sử dụng composer để cài đặt package graphql-laravel, package này rất hữu dụng để tích hợp Laravel và GraphQL. Hướng dẫn chi tiết đã có trong link github.

3. Khởi tạo Model

Tạo model cho bảng user_profiles, products, product_images giống như sơ đồ quan hệ dưới đây và đừng bỏ qua mối quan hệ giữa các model.

4. Tạo Query và Type GraphQL

Query trong graphQL giống như chúng ta định nghĩa endpoint trong API Restful. Query chỉ dùng để lấy dữ liệu phục vụ việc create, update và delete mà chúng ta gọi nó là Mutation. Type trong GraphQL dùng để xác định từng loại field trong Query, type sẽ giúp chúng ta định dạng kiểu field của kết quả từ truy vấn, ví dụ kiểu boolean, string, float, int vv ... chúng ta có thể định nghĩa custom type. Đây là thư mục cấu trúc cho query và type:

Đây là code hoàn chỉnh cho UsersQuery.php Và UsersType.php

<?php

namespace App\GraphQL\Query;

use App\User;
use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Facades\GraphQL;
use Rebing\GraphQL\Support\Query;
use Rebing\GraphQL\Support\SelectFields;

class UsersQuery extends Query
{
    protected $attributes = [
        'name' => 'Users Query',
        'description' => 'A query of users'
    ];
    
    public function type()
    {
        // kết quả của query với paginate của laravel
        return GraphQL::paginate('users');
    }
    
    // arguments to filter query
    public function args()
    {
        return [
            'id' => [
                'name' => 'id',
                'type' => Type::int()
            ],
            'email' => [
                'name' => 'email',
                'type' => Type::string()
            ]
        ];
    }
    
    public function resolve($root, $args, SelectFields $fields)
    {
        $where = function ($query) use ($args) {
            if (isset($args['id'])) {
                $query->where('id',$args['id']);
            }
            
            if (isset($args['email'])) {
                $query->where('email',$args['email']);
            }
        };
        
        $user = User::with(array_keys($fields->getRelations()))
            ->where($where)
            ->select($fields->getSelect())
            ->paginate();
            
        return $user;
    }
}
<?php

namespace App\GraphQL\Type;

use App\User;
use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Facades\GraphQL;
use Rebing\GraphQL\Support\Type as GraphQLType;

class UsersType extends GraphQLType
{
    protected $attributes = [
        'name' => 'Users',
        'description' => 'A type',
        'model' => User::class, // Định nghĩa model cho users type
    ];
    
    // Định nghĩa field của type
    public function fields()
    {
        return [
            'id' => [
                'type' => Type::nonNull(Type::int()),
                'description' => 'The id of the user'
            ],
            'email' => [
                'type' => Type::string(),
                'description' => 'The email of user'
            ],
            'name' => [
                'type' => Type::string(),
                'description' => 'The name of the user'
            ],
            // field relation to model user_profiles
            'user_profiles' => [
                'type' => GraphQL::type('user_profiles'),
                'description' => 'The profile of the user'
            ]
        ];
    }
    
    protected function resolveEmailField($root, $args)
    {
        return strtolower($root->email);
    }
}

Sau khi tạo Query và Type, chúng ta cần register query và type vào schema bằng việc chỉnh sửa file config/graphql.php:

graphql.php

<?php

use App\GraphQL\Query\ProductsQuery;
use App\GraphQL\Query\UsersQuery;
use App\GraphQL\Type\ProductImagesType;
use App\GraphQL\Type\ProductsType;
use App\GraphQL\Type\UserProfilesType;
use App\GraphQL\Type\UsersType;

return [
    'prefix' => 'graphql',
    'routes' => 'query/{graphql_schema?}',
    'controllers' => \Rebing\GraphQL\GraphQLController::class . '@query',
    'middleware' => [],
    'default_schema' => 'default',
    // register query  
    'schemas' => [
        'default' => [
            'query' => [
                'users' => UsersQuery::class,
                'products' => ProductsQuery::class,
            ],
            'mutation' => [
            ],
            'middleware' => []
        ],
    ],
    // register types
    'types' => [
        'product_images' => ProductImagesType::class,
        'products'  => ProductsType::class,
        'user_profiles'  => UserProfilesType::class,
        'users'  => UsersType::class,
    ],
    'error_formatter' => ['\Rebing\GraphQL\GraphQL', 'formatError'],
    'params_key'    => 'params'
];

5. Testing

Chúng ta có thể sử dụng GraphiQL để viết một số query và có được kết quả. Điều này khá dễ dàng vì chúng ta có autocomplete query khi chúng ta viết một số truy vấn hoặc chúng ta có thể sử dụng postman để gọi API, đây là ví dụ về autocomplete query:

Và đây là kết quả:

Trong bài viết sau chúng ta sẽ tiếp tục với Mutation và Authentication.

References

https://medium.com/skyshidigital/easy-build-api-using-laravel-and-graphql-67e2c5c5e150


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí