Skip to content

Blog Công Nghệ

MENUMENU
  • Trang chủ
  • Giới Thiệu
  • Lập Trình
    • Lập Trình Website
      • Laravel
        • Phân Tích Dự Án
      • PHP
      • SQL
      • HTML
      • CSS
      • Javascipt
      • My Project
      • Wordpress
    • Luyện Skill
    • Lập trình winform
    • CSDL
    • Lập Trình Android
    • Trí tuệ nhân tạo
    • Khai Khoáng Dữ Liệu
    • Arduino
    • Khác
    • Đồ án
  • Phần Mềm
    • Powerpoint
    • Tool
  • Cuộc sống và Giải trí
    • Hợp âm
    • web5ngay - youtube
    • Công Giáo
    • Kỹ Năng Sống
    • Street Workout
  • Danh sách bài viết
  • Guide line
    • Guild line phỏng vấn
    • Guide lines Laravel
    • Guide line Module Frontend
  • Tóm tắt sách
  • Fanpage

Blog Công Nghệ

Nơi chia sẻ kiến thức

Graphql

12 Tháng Hai, 2022 by admin
Lượt xem: 41

Grapql cách viết api. Cách viết do Facebook lập ra, để gom mọi api về 1 api. Api này có khả năng:

  • Tránh dư thừa dữ liệu
  • Dễ quản lý
  • Có khả năng realtime

Contents

  • 1. Anh Tân chia sẻ
  • 2. Thử Graphql với laravel
    • 2.1 Thư viện rebing/graphql-laravel
    • 2.1 Thư viện lighthouse
  • 3. Kinh nghiệm
    • 3.1 Phần mềm test graphql
    • 3.2 Cài đặt light-house laravel
    • 3.3 light house library
      • 3.3.1 Type
      • 3.3.2 Simple
      • 3.3.3 Có argument
      • 3.3.4 directive
        • 3.3.4.1 Sử dụng local scope
    • 3.4 Vue apollo
      • 3.4.1 Cài đặt
      • 3.4.2 Cấu hình
      • 3.4.3 Sử dụng
        • Query
          • Simple query
          • Param query
        • Loading state
        • Xử lý lỗi
        • Mutation
      • 3.4.4 Tách query apollo ra thành file .gql
    • 3.5 Param query trong graphql
    • 3.6 Đồng bộ relationship giữa laravel và graphql-lighthouse
  • 4. Các ví dụ làm từ course
    • 4.1 Blog
    • 4.2 Trello

1. Anh Tân chia sẻ

2. Thử Graphql với laravel

2.1 Thư viện rebing/graphql-laravel

Cá nhân mình thấy thư viện này dễ hiểu, dễ cấu hình. Tuy nhiên, việc viết code định graphql viết theo một chuẩn mới khá khó viết so với cấu trúc mặc định của graphql.

Tham khảo: https://www.twilio.com/blog/build-graphql-powered-api-laravel-php

Lưu ý: Khi thực hiện code link trên nhớ thay App\Book =>> App\Models\Book. Vì Laravel mới đã chuyển model và folder Models.

2.1 Thư viện lighthouse

Mình thấy thư viện này dùng khá phổ biến. Do cấu trúc code giống cấu trúc của graphql.

Tham khảo: https://www.toptal.com/graphql/laravel-graphql-server-tutorial

3. Kinh nghiệm

3.1 Phần mềm test graphql

Phần mềm tên là GraphiQL khá dễ sử dụng.

Link download: https://www.electronjs.org/apps/graphiql

3.2 Cài đặt light-house laravel

composer require nuwave/lighthouse
php artisan vendor:publish --provider="Nuwave\Lighthouse\LighthouseServiceProvider"

Sau đó sẽ có file config/lighthouse.php để cấu hình cho light-house gồm route,…

'schema' => [
    'register' => base_path('graphql/schema.graphql'),
  	// nơi đăng ký file định nghĩa graphql
],

Chạy test thử:

php artisan serve

// Vào phần mềm graphiQL mục 3.1 để chạy
http://localhost:8000/graphql

3.3 light house library

Schema có nhiều type. Có 3 loại mặc định:

  • Query: lấy dữ liệu
  • Mutation: thay đổi dữ liệu
  • Subscription: realtime

3.3.1 Type

  • Dạng object
  • Scalar: Kiểu dữ liệu
  • Enum
  • Input: Data từ request truyền vào (parameter)
  • Interface
  • Union

3.3.2 Simple

Định nghĩa ở graphql/schema.graphql

type Query {
  hello: String!
}

Tạo query file

php artisan lighthouse:query Hello

Sẽ sinh ra file tương ứng App\GraphQL\Queries. Function __invoke() sẽ xử lý và trả data về

<?php

namespace App\GraphQL\Queries;

class Hello
{
    public function __invoke(): string
    {
        return 'world!';
    }
}

Như vậy, khi gọi

{
  hello
}

// result 
{
  "data": {
    "hello": "world!"
  }
}

3.3.3 Có argument

type Query {
  greet(name: String!): String
  // greet(name: String = "you"): String  => set param mặc định khi không truyển vào
    										// param không bắt buộc
}
<?php

namespace App\GraphQL\Queries;

class Greet
{
    public function __invoke($rootValue, array $args): string
    {
        return "Hello, {$args['name']}!";
    }
}
// gọi api
{
  greet(name: "Foo")
}

// result
{
  "data": {
    "greet": "Hello, Foo!"
  }
}

3.3.4 directive

@all
@paginate
@eq
@orderBy 
@first
@create
@update
@upsert // update or create if not exist
@delete
// relationship
@hasOne
@hasMany
@belongsTo
@belongsToMany
@morphOne
@morphTo
@morphMany
3.3.4.1 Sử dụng local scope

Eloquent

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    public function scopeVerified(Builder $query): Builder
    {
        return $query->whereNotNull('email_verified_at');
    }
}
type Query {
  users: [User]! @all(scopes: ["verified"])
}

3.4 Vue apollo

3.4.1 Cài đặt

npm install vue-apollo@3.0.3 graphql@15.2.0 apollo-boost@0.4.9

3.4.2 Cấu hình

Add apollo Client in app.js

import ApolloClient from 'apollo-boost'

const apolloClient = new ApolloClient({
  // You should use an absolute URL here
  uri: 'http://127.0.0.1:8000/graphql'
})

Import VueApollo

import VueApollo from 'vue-apollo'
  
Vue.use(VueApollo)

Add apolloProvider

const apolloProvider = new VueApollo({
    defaultClient: apolloClient,
  })

Add apoloProvider to app Vue

const app = new Vue({
    el: '#app',
    router,
    apolloProvider
});

3.4.3 Sử dụng

Query
Simple query
<script>
import gql from 'graphql-tag'

export default {
    apollo: {
        // Simple query that will update the 'hello' vue property
        posts: gql`{
            posts {
                id
                title
            }
        }`,
    },
}
</script>
Param query

Trong một query sẽ gồm 2 phần

  • query
  • variables: sẽ return về các biến dynamic
<script>
import gql from 'graphql-tag'

export default {
    apollo: {
        post: {
            query: gql`
                query ($id: ID!) {
                    post(id: $id) {
                        id
                        title
                        content
                        author {
                            id
                            name
                            avatar
                        }
                        topic {
                            name
                            slug
                        }
                    }
                }`,
            variables() {
                return {
                    id: this.$route.params.id
                }
            }
        }
    }
}
</script>
Loading state
// check loading
$apollo.loading
  
// Check a query loading
$apollo.queries.posts.loading
  
//example
<template>
    <div>
        List Post
        <div>Loading: {{ $apollo.loading }}</div>
        <div>Is posts loading: {{ $apollo.queries.posts.loading }}</div>
    </div>
</template>
Xử lý lỗi
<script>
import gql from 'graphql-tag'

export default {
    apollo: {
        post: {
            query: gql`
                ...`,
            variables() {
                return {
                    id: this.$route.params.id
                }
            },
            error() {
                this.$router.push({ name: '404' });
            }
        }
    }
}
</script>
Mutation
import CardAdd from '../graphql/CardAdd.gql'

this.$apollo.mutate({
  mutation: CardAdd,
  variables: {
    title: 'Added through mutation',
    list_id: 1,
    order: 1
    }
});


// Có update
addCard() {
  const self = this;
  this.$apollo.mutate({
    mutation: CardAdd,
    variables: {
      title: this.title,
      list_id: this.list.id,
      order: 1
      },
    update(store, {data: {cardAdd} }) {
      const data = store.readQuery({
        query: BoardQuery,
        variables: { id: Number(self.list.board_id)}
      });

      data.board.lists.find(list => (list.id == self.list.id)).cards.push(cardAdd);

      store.writeQuery({ query: BoardQuery, data });
    }
  });
  this.closed();
},

3.4.4 Tách query apollo ra thành file .gql

Tạo file xxx.gql, lấy đoạn query sang file này

Đặt tên file vào sau query.

Ví dụ: tên file là: BoardWithListsAndCards.gql thì query BoardWithListsAndCards( …

query BoardWithListsAndCards($id: ID!) {
    board(id: $id) {
        title
        color
        lists {
            id
            title
            cards {
                id
                title
            }
        }
    }
}

Import vào component

import BoardQuery from './graphql/BoardWithListsAndCards.gql' // dòng này

export default {
    apollo: {
        board: {
            query: BoardQuery, // dòng này
            variables() {
                return {
                    id: 1
                }
            },
            error() {
                this.$router.push({ name: '404' });
            }
        }
    }
}

Cấu hình lại webpack mix laravel

const mix = require('laravel-mix');

/*============================================
* Thêm đoạn này
*============================================*/
mix.extend(
  'graphql',
  new class {
      dependencies() {
          return ['graphql', 'graphql-tag']
      }

      webpackRules() {
          return {
              test: /\.(graphql|gql)$/,
              exclude: /node_modules/,
              loader: 'graphql-tag/loader'
          }
      }
  }()
);
/*============================================*/

 mix.js("resources/js/app.js", "public/js")
 .postCss("resources/css/app.css", "public/css", [
   require("tailwindcss"),
 ]);

/*============================================
* và thêm đoạn này
*============================================*/
 mix.graphql();
/*============================================*/

Build lại

npm run watch

3.5 Param query trong graphql

query ($id: ID!) {
	 post(id: $id) {
    id
    title
  }
}

3.6 Đồng bộ relationship giữa laravel và graphql-lighthouse

Tên function relationship trong model đặt thế nào thì trong định nghĩa type của graphql cũng sử dụng tên đó định nghĩa, nếu không sẽ bị lỗi:

Call to undefined relationship [lists] on model

Tui mất khá nhiều thời gian vì lỗi này.

4. Các ví dụ làm từ course

4.1 Blog

Repository github: https://github.com/tronghao/learn-graphql-blogql

Cài laravel và các dependences

composer create-project laravel/laravel=7.12.0 blog-ql --prefer-dist
composer require nuwave/lighthouse=4.14.1
composer require mll-lab/laravel-graphql-playground=2.1.0
  
// Nếu laravel version >= 8
composer require --dev barryvdh/laravel-ide-helper
// Nếu laravel version 7
composer require --dev barryvdh/laravel-ide-helper 2.8
composer require laravel/ui
  composer require laravel/ui:^2.4  // với laravel 7
    
php artisan ui vue

Cài nodejs

// check
node -v
npm -v

Run lệnh

npm install && npm run dev

Install tailwindcss

npm install tailwindcss@1.4.6
  
  // delete folder resource/js/sass
  // create file resource/css/app.css
  @tailwind base;
  @tailwind components;
  @tailwind utilities
  
npx tailwindcss init

Chỉnh webpack.mix.js

 mix.js("resources/js/app.js", "public/js")
 .postCss("resources/css/app.css", "public/css", [
   require("tailwindcss"),
 ]);

// sau đó
npm run dev

add version to mix

// thêm vào file webpack.mix.js
if (mix.inProduction()) {
     mix.version();
 }

Publish vendor light-housr

php artisan vendor:publish --provider="Nuwave\Lighthouse\LighthouseServiceProvider" --tag=schema

Create migration and model Post and Topic

  • Post: id, title, lead, content.
  • Topic: id, slug, name

Add relationship model

install vue-router

  • mode: history. Cần cấu hình lại router Laravel toàn bộ là dynamic route, còn route của graphql là real route
Route::get('/{any?}', function () {
    return view('welcome');
})->where('any', '^(?!graphql)[\/\w\.-]*');

install vue apollo

install graphql-tag

npm i graphql-tag@2.10.3

intall extension Tailwind css IntelliSense in vs code

install moment.js

npm i moment@2.27.0

Tạo filter vuejs

Vue.filter("timeago", value => moment(value).fromNow() );
Vue.filter("longDate", value => moment(value).format("MMMM Do YYYY") );

Xử lý 404

const routes = [
    { 
        path: '/',
        name: 'index',
        component: PostList 
    },
    {
        path: '/topics/:slug',
        name: 'topic',
        component: TopicPostList,
    },
    { 
        path: '/post/:id', 
        name: 'post',
        component: Post 
    },
    { 
        path: '/authors/:id', 
        name: 'author',
        component: AuthorPostList 
    },
    {
        path: '*',
        name: '404',
        component: {
          template: '<div>Not Found</div>'
        }
    }
  ];
<script>
import gql from 'graphql-tag'

export default {
    apollo: {
        post: {
            query: gql`
                ...`,
            variables() {
                return {
                    id: this.$route.params.id
                }
            },
            error() {
                this.$router.push({ name: '404' });
            }
        }
    }
}
</script>

4.2 Trello

composer create-project laravel/laravel=7.12.0 laravello --prefer-dist
composer require nuwave/lighthouse=4.15.0
composer require mll-lab/laravel-graphql-playground=2.3.0
composer require laravel/telescope=3.5.0
composer require --dev barryvdh/laravel-ide-helper 2.8
composer require laravel/ui:^2.4

npm i vue-apollo@3.0.3 graphql@15.2.0 apollo-boost@0.4.9

Mutation

type Mutation {
    cardAdd(title: String!, order: Int, list_id: ID!, owner_id: ID!): Card! @create
}

// query
mutation {
  cardAdd(title: "xxx", order: 1, list_id:1, owner_id: 1) {
    id
    title
  }
}

Sử dụng input để gọn hơn.

type Mutation {
    cardAdd(input: CardAddInput! @spread): Card! @create
}


input CardAddInput {
    title: String!
    order: Int
    list_id: ID!
    owner_id: ID!
}


// cách query
mutation CardAdd($list_id: ID!, $title: String!, $order: Int!) {
  cardAdd(input: {title: $title, order: $order, list_id:$list_id, owner_id: 1}) {
    id
    title
  }
}

No related posts.

Post navigation

Previous Post:

Regex Expression

Next Post:

Premiere

Trả lời Hủy

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

Ẩn sidebar

Tìm kiếm

Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages

Blog Công Nghệ

Bài viết mới

  • Master typescript
  • Sendmail trong Laravel sử dụng dịch vụ SES, SQS của Amazon
  • Install SSL in Nginx Ubuntu
  • Docker study
  • Bảo vệ: Hướng dẫn code bot Telegram easy game

Lượng truy cập

0074467
Visit Today : 63
Visit Yesterday : 178
This Month : 738
Who's Online : 4
© 2025 Blog Công Nghệ | WordPress Theme by Superbthemes