使用 Lighthouse 构建 GraphQL 服务器的入门,从零开始为一个简单博客创建 GraphQL API

1、使用 Lighthouse 构建 GraphQL 服务器的入门。参考网址:https://lighthouse-php.cn/tutorial/

2、从零开始为一个简单博客创建 GraphQL API。通过 Composer 创建一个新的 Laravel 项目:lighthouse-tutorial

PS E:/wwwroot> composer create-project laravel/laravel lighthouse-tutorial
Creating a "laravel/laravel" project at "./lighthouse-tutorial"
Installing laravel/laravel (v8.6.10)
- Installing laravel/laravel (v8.6.10): Extracting archive
Created project in E:/wwwroot/lighthouse-tutorial
> @php -r "file_exists('.env') || copy('.env.example', '.env');"
Loading composer repositories with package information
Updating dependencies
Lock file operations: 110 installs, 0 updates, 0 removals
- Locking asm89/stack-cors (v2.0.5)
- Locking brick/math (0.9.3)
- Locking dflydev/dot-access-data (v3.0.1)
- Locking doctrine/inflector (2.0.4)
- Locking doctrine/instantiator (1.4.0)
- Locking doctrine/lexer (1.2.1)
- Locking dragonmantank/cron-expression (v3.2.3)
- Locking egulias/email-validator (2.1.25)
- Locking facade/flare-client-php (1.9.1)
- Locking facade/ignition (2.17.4)
- Locking facade/ignition-contracts (1.0.2)
- Locking fakerphp/faker (v1.17.0)
- Locking filp/whoops (2.14.5)
- Locking fruitcake/laravel-cors (v2.0.5)
- Locking graham-campbell/result-type (v1.0.4)
- Locking guzzlehttp/guzzle (7.4.1)
- Locking guzzlehttp/promises (1.5.1)
- Locking guzzlehttp/psr7 (2.1.0)
- Locking hamcrest/hamcrest-php (v2.0.1)
- Locking laravel/framework (v8.78.1)
- Locking laravel/sail (v1.12.12)
- Locking laravel/sanctum (v2.13.0)
- Locking laravel/serializable-closure (v1.0.5)
- Locking laravel/tinker (v2.6.3)
- Locking league/commonmark (2.1.1)
- Locking league/config (v1.1.1)
- Locking league/flysystem (1.1.9)
- Locking league/mime-type-detection (1.9.0)
- Locking mockery/mockery (1.4.4)
- Locking monolog/monolog (2.3.5)
- Locking myclabs/deep-copy (1.10.2)
- Locking nesbot/carbon (2.55.2)
- Locking nette/schema (v1.2.2)
- Locking nette/utils (v3.2.6)
- Locking nikic/php-parser (v4.13.2)
- Locking nunomaduro/collision (v5.11.0)
- Locking opis/closure (3.6.2)
- Locking phar-io/manifest (2.0.3)
- Locking phar-io/version (3.1.0)
- Locking phpdocumentor/reflection-common (2.2.0)
- Locking phpdocumentor/reflection-docblock (5.3.0)
- Locking phpdocumentor/type-resolver (1.6.0)
- Locking phpoption/phpoption (1.8.1)
- Locking phpspec/prophecy (v1.15.0)
- Locking phpunit/php-code-coverage (9.2.10)
- Locking phpunit/php-file-iterator (3.0.6)
- Locking phpunit/php-invoker (3.1.1)
- Locking phpunit/php-text-template (2.0.4)
- Locking phpunit/php-timer (5.0.3)
- Locking phpunit/phpunit (9.5.11)
- Locking psr/container (1.1.2)
- Locking psr/event-dispatcher (1.0.0)
- Locking psr/http-client (1.0.1)
- Locking psr/http-factory (1.0.1)
- Locking psr/http-message (1.0.1)
- Locking psr/log (1.1.4)
- Locking psr/simple-cache (1.0.1)
- Locking psy/psysh (v0.10.12)
- Locking ralouphie/getallheaders (3.0.3)
- Locking ramsey/collection (1.2.2)
- Locking ramsey/uuid (4.2.3)
- Locking sebastian/cli-parser (1.0.1)
- Locking sebastian/code-unit (1.0.8)
- Locking sebastian/code-unit-reverse-lookup (2.0.3)
- Locking sebastian/comparator (4.0.6)
- Locking sebastian/complexity (2.0.2)
- Locking sebastian/diff (4.0.4)
- Locking sebastian/environment (5.1.3)
- Locking sebastian/exporter (4.0.4)
- Locking sebastian/global-state (5.0.3)
- Locking sebastian/lines-of-code (1.0.3)
- Locking sebastian/object-enumerator (4.0.4)
- Locking sebastian/object-reflector (2.0.4)
- Locking sebastian/recursion-context (4.0.4)
- Locking sebastian/resource-operations (3.0.3)
- Locking sebastian/type (2.3.4)
- Locking sebastian/version (3.0.2)
- Locking swiftmailer/swiftmailer (v6.3.0)
- Locking symfony/console (v5.4.2)
- Locking symfony/css-selector (v5.4.2)
- Locking symfony/deprecation-contracts (v2.5.0)
- Locking symfony/error-handler (v5.4.2)
- Locking symfony/event-dispatcher (v5.4.0)
- Locking symfony/event-dispatcher-contracts (v2.5.0)
- Locking symfony/finder (v5.4.2)
- Locking symfony/http-foundation (v5.4.2)
- Locking symfony/http-kernel (v5.4.2)
- Locking symfony/mime (v5.4.2)
- Locking symfony/polyfill-ctype (v1.24.0)
- Locking symfony/polyfill-iconv (v1.24.0)
- Locking symfony/polyfill-intl-grapheme (v1.24.0)
- Locking symfony/polyfill-intl-idn (v1.24.0)
- Locking symfony/polyfill-intl-normalizer (v1.24.0)
- Locking symfony/polyfill-mbstring (v1.24.0)
- Locking symfony/polyfill-php72 (v1.24.0)
- Locking symfony/polyfill-php73 (v1.24.0)
- Locking symfony/polyfill-php80 (v1.24.0)
- Locking symfony/polyfill-php81 (v1.24.0)
- Locking symfony/process (v5.4.2)
- Locking symfony/routing (v5.4.0)
- Locking symfony/service-contracts (v2.5.0)
- Locking symfony/string (v5.4.2)
- Locking symfony/translation (v5.4.2)
- Locking symfony/translation-contracts (v2.5.0)
- Locking symfony/var-dumper (v5.4.2)
- Locking theseer/tokenizer (1.2.1)
- Locking tijsverkoyen/css-to-inline-styles (2.2.4)
- Locking vlucas/phpdotenv (v5.4.1)
- Locking voku/portable-ascii (1.5.6)
- Locking webmozart/assert (1.10.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 110 installs, 0 updates, 0 removals
- Downloading nunomaduro/collision (v5.11.0)
- Installing doctrine/inflector (2.0.4): Extracting archive
- Installing doctrine/lexer (1.2.1): Extracting archive
- Installing symfony/polyfill-ctype (v1.24.0): Extracting archive
- Installing webmozart/assert (1.10.0): Extracting archive
- Installing dragonmantank/cron-expression (v3.2.3): Extracting archive
- Installing symfony/polyfill-php80 (v1.24.0): Extracting archive
- Installing symfony/polyfill-mbstring (v1.24.0): Extracting archive
- Installing symfony/var-dumper (v5.4.2): Extracting archive
- Installing symfony/polyfill-intl-normalizer (v1.24.0): Extracting archive
- Installing symfony/polyfill-intl-grapheme (v1.24.0): Extracting archive
- Installing symfony/string (v5.4.2): Extracting archive
- Installing symfony/deprecation-contracts (v2.5.0): Extracting archive
- Installing psr/container (1.1.2): Extracting archive
- Installing symfony/service-contracts (v2.5.0): Extracting archive
- Installing symfony/polyfill-php73 (v1.24.0): Extracting archive
- Installing symfony/console (v5.4.2): Extracting archive
- Installing psr/log (1.1.4): Extracting archive
- Installing monolog/monolog (2.3.5): Extracting archive
- Installing voku/portable-ascii (1.5.6): Extracting archive
- Installing phpoption/phpoption (1.8.1): Extracting archive
- Installing graham-campbell/result-type (v1.0.4): Extracting archive
- Installing vlucas/phpdotenv (v5.4.1): Extracting archive
- Installing symfony/css-selector (v5.4.2): Extracting archive
- Installing tijsverkoyen/css-to-inline-styles (2.2.4): Extracting archive
- Installing symfony/routing (v5.4.0): Extracting archive
- Installing symfony/process (v5.4.2): Extracting archive
- Installing symfony/polyfill-php72 (v1.24.0): Extracting archive
- Installing symfony/polyfill-intl-idn (v1.24.0): Extracting archive
- Installing symfony/mime (v5.4.2): Extracting archive
- Installing symfony/http-foundation (v5.4.2): Extracting archive
- Installing psr/event-dispatcher (1.0.0): Extracting archive
- Installing symfony/event-dispatcher-contracts (v2.5.0): Extracting archive
- Installing symfony/event-dispatcher (v5.4.0): Extracting archive
- Installing symfony/error-handler (v5.4.2): Extracting archive
- Installing symfony/http-kernel (v5.4.2): Extracting archive
- Installing symfony/finder (v5.4.2): Extracting archive
- Installing symfony/polyfill-iconv (v1.24.0): Extracting archive
- Installing egulias/email-validator (2.1.25): Extracting archive
- Installing swiftmailer/swiftmailer (v6.3.0): Extracting archive
- Installing symfony/polyfill-php81 (v1.24.0): Extracting archive
- Installing ramsey/collection (1.2.2): Extracting archive
- Installing brick/math (0.9.3): Extracting archive
- Installing ramsey/uuid (4.2.3): Extracting archive
- Installing psr/simple-cache (1.0.1): Extracting archive
- Installing opis/closure (3.6.2): Extracting archive
- Installing symfony/translation-contracts (v2.5.0): Extracting archive
- Installing symfony/translation (v5.4.2): Extracting archive
- Installing nesbot/carbon (2.55.2): Extracting archive
- Installing league/mime-type-detection (1.9.0): Extracting archive
- Installing league/flysystem (1.1.9): Extracting archive
- Installing nette/utils (v3.2.6): Extracting archive
- Installing nette/schema (v1.2.2): Extracting archive
- Installing dflydev/dot-access-data (v3.0.1): Extracting archive
- Installing league/config (v1.1.1): Extracting archive
- Installing league/commonmark (2.1.1): Extracting archive
- Installing laravel/serializable-closure (v1.0.5): Extracting archive
- Installing laravel/framework (v8.78.1): Extracting archive
- Installing facade/ignition-contracts (1.0.2): Extracting archive
- Installing facade/flare-client-php (1.9.1): Extracting archive
- Installing facade/ignition (2.17.4): Extracting archive
- Installing fakerphp/faker (v1.17.0): Extracting archive
- Installing asm89/stack-cors (v2.0.5): Extracting archive
- Installing fruitcake/laravel-cors (v2.0.5): Extracting archive
- Installing psr/http-message (1.0.1): Extracting archive
- Installing psr/http-client (1.0.1): Extracting archive
- Installing ralouphie/getallheaders (3.0.3): Extracting archive
- Installing psr/http-factory (1.0.1): Extracting archive
- Installing guzzlehttp/psr7 (2.1.0): Extracting archive
- Installing guzzlehttp/promises (1.5.1): Extracting archive
- Installing guzzlehttp/guzzle (7.4.1): Extracting archive
- Installing laravel/sail (v1.12.12): Extracting archive
- Installing laravel/sanctum (v2.13.0): Extracting archive
- Installing nikic/php-parser (v4.13.2): Extracting archive
- Installing psy/psysh (v0.10.12): Extracting archive
- Installing laravel/tinker (v2.6.3): Extracting archive
- Installing hamcrest/hamcrest-php (v2.0.1): Extracting archive
- Installing mockery/mockery (1.4.4): Extracting archive
- Installing filp/whoops (2.14.5): Extracting archive
- Installing nunomaduro/collision (v5.11.0): Extracting archive
- Installing phpdocumentor/reflection-common (2.2.0): Extracting archive
- Installing phpdocumentor/type-resolver (1.6.0): Extracting archive
- Installing phpdocumentor/reflection-docblock (5.3.0): Extracting archive
- Installing sebastian/version (3.0.2): Extracting archive
- Installing sebastian/type (2.3.4): Extracting archive
- Installing sebastian/resource-operations (3.0.3): Extracting archive
- Installing sebastian/recursion-context (4.0.4): Extracting archive
- Installing sebastian/object-reflector (2.0.4): Extracting archive
- Installing sebastian/object-enumerator (4.0.4): Extracting archive
- Installing sebastian/global-state (5.0.3): Extracting archive
- Installing sebastian/exporter (4.0.4): Extracting archive
- Installing sebastian/environment (5.1.3): Extracting archive
- Installing sebastian/diff (4.0.4): Extracting archive
- Installing sebastian/comparator (4.0.6): Extracting archive
- Installing sebastian/code-unit (1.0.8): Extracting archive
- Installing sebastian/cli-parser (1.0.1): Extracting archive
- Installing phpunit/php-timer (5.0.3): Extracting archive
- Installing phpunit/php-text-template (2.0.4): Extracting archive
- Installing phpunit/php-invoker (3.1.1): Extracting archive
- Installing phpunit/php-file-iterator (3.0.6): Extracting archive
- Installing theseer/tokenizer (1.2.1): Extracting archive
- Installing sebastian/lines-of-code (1.0.3): Extracting archive
- Installing sebastian/code-unit-reverse-lookup (2.0.3): Extracting archive
- Installing phpunit/php-code-coverage (9.2.10): Extracting archive
- Installing doctrine/instantiator (1.4.0): Extracting archive
- Installing phpspec/prophecy (v1.15.0): Extracting archive
- Installing phar-io/version (3.1.0): Extracting archive
- Installing phar-io/manifest (2.0.3): Extracting archive
- Installing myclabs/deep-copy (1.10.2): Extracting archive
- Installing phpunit/phpunit (9.5.11): Extracting archive
70 package suggestions were added by new dependencies, use `composer suggest` to see details.
Package swiftmailer/swiftmailer is abandoned, you should avoid using it. Use symfony/mailer instead.
Generating optimized autoload files
> Illuminate/Foundation/ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
Discovered Package: facade/ignition
Discovered Package: fruitcake/laravel-cors
Discovered Package: laravel/sail
Discovered Package: laravel/sanctum
Discovered Package: laravel/tinker
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Package manifest generated successfully.
77 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
> @php artisan vendor:publish --tag=laravel-assets --ansi --force
No publishable resources for tag [laravel-assets].
Publishing complete.
> @php artisan key:generate --ansi
Application key set successfully.

3、创建数据库:lighthouse_tutorial,配置 .env 中的数据库连接。运行数据库迁移以创建 users 表

PS E:/wwwroot/lighthouse-tutorial> php artisan migrate
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (42.37ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (36.39ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (40.11ms)
Migrating: 2019_12_14_000001_create_personal_access_tokens_table
Migrated:  2019_12_14_000001_create_personal_access_tokens_table (53.85ms)

4、在数据库中植入一些假的用户数据。factory(‘App/User’, 10)->create(); 在 Laravel 8 已经不可用。需要使用 User::factory()->count(10)->create();。如图1

在数据库中植入一些假的用户数据。factory('App/User', 10)->create(); 在 Laravel 8 已经不可用。需要使用 User::factory()->count(10)->create();

图1

PS E:/wwwroot/lighthouse-tutorial> php artisan tinker
Psy Shell v0.10.12 (PHP 7.4.27 — cli) by Justin Hileman
>>> factory('App/User', 10)->create();
PHP Fatal error:  Call to undefined function factory() in Psy Shell code on line 1
>>> App/Factory('App/User', 10)->create();
PHP Fatal error:  Call to undefined function App/Factory() in Psy Shell code on line 1
>>> User::factory()->count(50)->create();
[!] Aliasing 'User' to 'App/Models/User' for this Tinker session.
=> Illuminate/Database/Eloquent/Collection {#3581
all: [
App/Models/User {#3585
name: "Ashton Tremblay",
email: "letha42@example.net",
email_verified_at: "2022-01-12 05:51:41",
#password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
#remember_token: "k1o1mrmP7o",
updated_at: "2022-01-12 05:51:41",
created_at: "2022-01-12 05:51:41",
id: 1,
},
App/Models/User {#3592
name: "Rene Powlowski",
email: "hkovacek@example.org",
email_verified_at: "2022-01-12 05:51:41",
#password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
#remember_token: "64Cl19QXs3",
updated_at: "2022-01-12 05:51:41",
created_at: "2022-01-12 05:51:41",
id: 2,
},
...
],
}
>>>                                                                                                                     

5、安装 Lighthouse,将使用 Lighthouse 作为 GraphQL 服务器。

PS E:/wwwroot/lighthouse-tutorial> composer require nuwave/lighthouse
Using version ^5.35 for nuwave/lighthouse
./composer.json has been updated
Running composer update nuwave/lighthouse
Loading composer repositories with package information
Updating dependencies
Lock file operations: 5 installs, 0 updates, 0 removals
- Locking haydenpierce/class-finder (0.4.3)
- Locking laragraph/utils (v1.1.1)
- Locking nuwave/lighthouse (v5.35.0)
- Locking thecodingmachine/safe (v1.3.3)
- Locking webonyx/graphql-php (v14.11.3)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 5 installs, 0 updates, 0 removals
- Downloading nuwave/lighthouse (v5.35.0)
- Installing webonyx/graphql-php (v14.11.3): Extracting archive
- Installing thecodingmachine/safe (v1.3.3): Extracting archive
- Installing laragraph/utils (v1.1.1): Extracting archive
- Installing haydenpierce/class-finder (0.4.3): Extracting archive
- Installing nuwave/lighthouse (v5.35.0): Extracting archive
6 package suggestions were added by new dependencies, use `composer suggest` to see details.
Package swiftmailer/swiftmailer is abandoned, you should avoid using it. Use symfony/mailer instead.
Generating optimized autoload files
> Illuminate/Foundation/ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
Discovered Package: facade/ignition
Discovered Package: fruitcake/laravel-cors
Discovered Package: laravel/sail
Discovered Package: laravel/sanctum
Discovered Package: laravel/tinker
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Discovered Package: nuwave/lighthouse
Package manifest generated successfully.
79 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
> @php artisan vendor:publish --tag=laravel-assets --ansi --force
No publishable resources for tag [laravel-assets].
Publishing complete.
PS E:/wwwroot/lighthouse-tutorial>

6、使用 Altair GraphQL Client 作为 GraphQL 查询的 IDE (在线调试工具)。它就好像 GraphQL 专用的 Postman,拥有很多神奇的功能。在 Chrome 浏览器的网上应用商店中搜索:GraphQL,排名第一的就是。如图2

使用 Altair GraphQL Client 作为 GraphQL 查询的 IDE (在线调试工具)。它就好像 GraphQL 专用的 Postman,拥有很多神奇的功能。在 Chrome 浏览器的网上应用商店中搜索:GraphQL,排名第一的就是。

图2

7、将默认模式发布到 graphql/schema.graphql。报错:No publishable resources for tag [schema].

PS E:/wwwroot/lighthouse-tutorial> php artisan vendor:publish --provider="Nuwave/Lighthouse/LighthouseServiceProvider" --tag=schema
No publishable resources for tag [schema].
Publishing complete.
PS E:/wwwroot/lighthouse-tutorial>

8、建议参考英文的最新文档:https://lighthouse-php.com/tutorial 。将默认模式发布到 graphql/schema.graphql。发布完成。

PS E:/wwwroot/lighthouse-tutorial> php artisan vendor:publish --tag=lighthouse-schema
Copied File [/vendor/nuwave/lighthouse/src/default-schema.graphql] To [/graphql/schema.graphql]
Publishing complete.
PS E:/wwwroot/lighthouse-tutorial>

9、在 Nginx 中配置虚拟主机:lighthouse-tutorial.local 。在 Altair GraphQL Client 中打开网址:http://lighthouse-tutorial.local/graplql 。如图3

在 Nginx 中配置虚拟主机:lighthouse-tutorial.local 。在 Altair GraphQL Client 中打开网址:http://lighthouse-tutorial.local/graplql

图3

server {
listen 80;
server_name lighthouse-tutorial.local;
root E:/wwwroot/lighthouse-tutorial/public;
access_log  logs/lighthouse-tutorial.local.access.log;
error_log   logs/lighthouse-tutorial.local.error.log;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt  { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ /.php$ {
# fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ //.(?!well-known).* {
deny all;
}
}

请求:

query{
user(id: 1){
id
name
email
created_at
updated_at
}
}

响应:

{
"data": {
"user": {
"id": "1",
"name": "Ashton Tremblay",
"email": "letha42@example.net",
"created_at": "2022-01-12 05:51:41",
"updated_at": "2022-01-12 05:51:41"
}
}
}

10、为我们的 posts 和 comments 定义模型和迁移。运行迁移。将 posts 模型添加到 app/User.php。

11、The Schema,修改 graphql/schema.graphql 并根据我们创建的有说服力的模型来定义我们的 posts 的模式。我们添加了两个用于查询文章到 Query 类型的最后面。 @all 返回所有内容的列表 Post 模型 。 @find 和 @eq 是通过其 ID 组合检索单个 Post。我们还可以通过添加额外的类型定义,明确定义我们的数据模型。如图4

我们还可以通过添加额外的类型定义,明确定义我们的数据模型。

图4

"A date string with format `Y-m-d`, e.g. `2011-05-23`."
scalar Date @scalar(class: "Nuwave//Lighthouse//Schema//Types//Scalars//Date")
"A datetime string with format `Y-m-d H:i:s`, e.g. `2018-05-23 13:43:32`."
scalar DateTime @scalar(class: "Nuwave//Lighthouse//Schema//Types//Scalars//DateTime")
type Query {
users: [User!]! @paginate(defaultCount: 10)
user(id: ID @eq): User @find
posts: [Post!]! @all
post(id: Int! @eq): Post @find
}
type User {
id: ID!
name: String!
email: String!
created_at: DateTime!
updated_at: DateTime!
posts: [Post!]! @hasMany
}
type Post {
id: ID!
title: String!
content: String!
author: User! @belongsTo
comments: [Comment!]! @hasMany
}
type Comment {
id: ID!
reply: String!
post: Post! @belongsTo
}

12、最终测试,在你的数据库中插入一些假数据,你可以使用 Laravel seeders 来完成。编辑模型工厂文件:database/factories/PostFactory.php、database/factories/CommentFactory.php。
database/factories/PostFactory.php

<?php
namespace Database/Factories;
use Illuminate/Database/Eloquent/Factories/Factory;
use App/Models/Post;
class PostFactory extends Factory
{
protected $model = Post::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
$sentence = $this->faker->sentence();
return [
'author_id' => rand(1, 100),
'title' => $sentence,
'content' => $this->faker->text(),
];
}
}

database/factories/CommentFactory.php

<?php
namespace Database/Factories;
use Illuminate/Database/Eloquent/Factories/Factory;
use App/Models/Comment;
class CommentFactory extends Factory
{
protected $model = Comment::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'post_id' => rand(1, 100),
'reply' => $this->faker->sentence(),
];
}
}

13、完成数据工厂的定制后,接下来我们开始书写填充部分。编辑数据填充文件:database/seeders/UsersTableSeeder.php、database/seeders/PostsTableSeeder.php、database/seeders/CommentsTableSeeder.php。
database/seeders/UsersTableSeeder.php

<?php
namespace Database/Seeders;
use Illuminate/Database/Seeder;
use App/Models/User;
class UsersTableSeeder extends Seeder
{
/**
* Seed the application's database.
*
* @return void
*/
public function run()
{
User::factory()->count(100)->create();
}
}

database/seeders/PostsTableSeeder.php

<?php
namespace Database/Seeders;
use Illuminate/Database/Seeder;
use App/Models/Post;
class PostsTableSeeder extends Seeder
{
/**
* Seed the application's database.
*
* @return void
*/
public function run()
{
Post::factory()->count(100)->create();
}
}

database/seeders/CommentsTableSeeder.php

<?php
namespace Database/Seeders;
use Illuminate/Database/Seeder;
use App/Models/Comment;
class CommentsTableSeeder extends Seeder
{
/**
* Seed the application's database.
*
* @return void
*/
public function run()
{
Comment::factory()->count(100)->create();
}
}

14、注册数据填充。编辑 database/seeders/DatabaseSeeder.php

<?php
namespace Database/Seeders;
use Illuminate/Database/Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* @return void
*/
public function run()
{
$this->call(UsersTableSeeder::class);
$this->call(PostsTableSeeder::class);
$this->call(CommentsTableSeeder::class);
}
}

15、执行数据填充命令:php artisan migrate:refresh –seed,报错:Call to undefined method App/Models/Post::factory()。如图5

执行数据填充命令:php artisan migrate:refresh --seed,报错:Call to undefined method App/Models/Post::factory()

图5

PS E:/wwwroot/lighthouse-tutorial> php artisan migrate:refresh --seed
Rolling back: 2022_01_12_062416_create_comments_table
Rolled back:  2022_01_12_062416_create_comments_table (16.76ms)
Rolling back: 2022_01_12_062104_create_posts_table
Rolled back:  2022_01_12_062104_create_posts_table (8.20ms)
Rolling back: 2019_12_14_000001_create_personal_access_tokens_table
Rolled back:  2019_12_14_000001_create_personal_access_tokens_table (9.17ms)
Rolling back: 2019_08_19_000000_create_failed_jobs_table
Rolled back:  2019_08_19_000000_create_failed_jobs_table (8.87ms)
Rolling back: 2014_10_12_100000_create_password_resets_table
Rolled back:  2014_10_12_100000_create_password_resets_table (9.72ms)
Rolling back: 2014_10_12_000000_create_users_table
Rolled back:  2014_10_12_000000_create_users_table (7.01ms)
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (28.61ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (31.30ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (31.69ms)
Migrating: 2019_12_14_000001_create_personal_access_tokens_table
Migrated:  2019_12_14_000001_create_personal_access_tokens_table (39.67ms)
Migrating: 2022_01_12_062104_create_posts_table
Migrated:  2022_01_12_062104_create_posts_table (17.16ms)
Migrating: 2022_01_12_062416_create_comments_table
Migrated:  2022_01_12_062416_create_comments_table (20.25ms)
Seeding: Database/Seeders/UsersTableSeeder
Seeded:  Database/Seeders/UsersTableSeeder (1,839.80ms)
Seeding: Database/Seeders/PostsTableSeeder
BadMethodCallException
Call to undefined method App/Models/Post::factory()
at E:/wwwroot/lighthouse-tutorial/vendor/laravel/framework/src/Illuminate/Support/Traits/ForwardsCalls.php:71
67▕      * @throws /BadMethodCallException
68▕      */
69▕     protected static function throwBadMethodCallException($method)
70▕     {
➜  71▕         throw new BadMethodCallException(sprintf(
72▕             'Call to undefined method %s::%s()', static::class, $method
73▕         ));
74▕     }
75▕ }
• Bad Method Call: Did you mean App/Models/Post::author() ?
1   E:/wwwroot/lighthouse-tutorial/vendor/laravel/framework/src/Illuminate/Support/Traits/ForwardsCalls.php:36
Illuminate/Database/Eloquent/Model::throwBadMethodCallException("factory")
2   E:/wwwroot/lighthouse-tutorial/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:2132
Illuminate/Database/Eloquent/Model::forwardCallTo(Object(Illuminate/Database/Eloquent/Builder), "factory", [])
PS E:/wwwroot/lighthouse-tutorial>

16、编辑数据模型文件,app/Models/Post.php、app/Models/Comment.php,引入 HasFactory。
app/Models/Post.php

<?php
namespace App/Models;
use Illuminate/Database/Eloquent/Factories/HasFactory;
use Illuminate/Database/Eloquent/Model;
use Illuminate/Database/Eloquent/Relations/HasMany;
use Illuminate/Database/Eloquent/Relations/BelongsTo;
class Post extends Model
{
use HasFactory;
public function author(): BelongsTo
{
return $this->belongsTo(User::class, 'author_id');
}
public function comments(): HasMany
{
return $this->hasMany(Comment::class);
}
}

app/Models/Comment.php

<?php
namespace App/Models;
use Illuminate/Database/Eloquent/Factories/HasFactory;
use Illuminate/Database/Eloquent/Model;
use Illuminate/Database/Eloquent/Relations/BelongsTo;
class Comment extends Model
{
use HasFactory;
public function post(): BelongsTo
{
return $this->belongsTo(Post::class);
}
}

17、执行数据填充成功后,访问 /graphql 并尝试以下的查询。获取到数据库中所有 posts 的列表,以及全部 comments 和 user 的 name。符合预期。如图6

执行数据填充成功后,访问 /graphql 并尝试以下的查询。获取到数据库中所有 posts 的列表,以及全部 comments 和 user 的 name。符合预期

图6

请求:

query {
posts {
id
title
author {
name
}
comments {
id
reply
}
}
}

响应:

{
"data": {
"posts": [
{
"id": "1",
"title": "Optio earum deserunt fuga qui quia hic.",
"author": {
"name": "Mrs. Lottie Kuhlman IV"
},
"comments": []
},
{
"id": "2",
"title": "Soluta eius quisquam consequatur accusantium distinctio minima.",
"author": {
"name": "Otilia Marvin"
},
"comments": []
},
{
"id": "3",
"title": "Unde harum commodi rerum nam dolores vel eligendi.",
"author": {
"name": "Alfreda Crooks"
},
"comments": [
{
"id": "14",
"reply": "Laborum exercitationem odit voluptas cumque adipisci."
}
]
},
{
"id": "4",
"title": "Praesentium iste nisi aut reprehenderit aliquam.",
"author": {
"name": "Hassan Goyette MD"
},
"comments": []
},
{
"id": "5",
"title": "Atque illo consequatur eveniet.",
"author": {
"name": "Estevan Mann"
},
"comments": []
},
{
"id": "6",
"title": "Praesentium et eaque soluta.",
"author": {
"name": "Prof. Rosalia Cartwright Sr."
},
"comments": [
{
"id": "5",
"reply": "Omnis doloremque tempore ut laboriosam nihil."
}
]
},
{
"id": "7",
"title": "Assumenda consequatur quo perspiciatis reiciendis.",
"author": {
"name": "Nestor Bauch"
},
"comments": [
{
"id": "70",
"reply": "Error quia natus inventore aliquid praesentium et."
}
]
},
{
"id": "8",
"title": "Nesciunt eos enim minus ipsa non sed minus.",
"author": {
"name": "Reggie Batz"
},
"comments": [
{
"id": "22",
"reply": "Magnam et cum reiciendis et."
}
]
},
{
"id": "9",
"title": "In et quasi dolorem aliquam nemo sequi.",
"author": {
"name": "Carroll Cartwright"
},
"comments": [
{
"id": "73",
"reply": "Cumque harum id officiis eum cumque."
}
]
},
{
"id": "10",
"title": "Consequatur modi enim fugit ut eos.",
"author": {
"name": "Kiley Connelly"
},
"comments": [
{
"id": "71",
"reply": "Aut harum fuga quos veniam quia perspiciatis."
},
{
"id": "90",
"reply": "Harum unde debitis sunt sint tenetur temporibus voluptates."
}
]
},
...
]
}
}

18、随机选择 posts 的 id 等于 10 的数据验证,响应与数据库中一致。如图7

随机选择 posts 的 id 等于 10 的数据验证,响应与数据库中一致。

图7

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/250703.html

(0)
上一篇 2022年5月1日
下一篇 2022年5月1日

相关推荐

发表回复

登录后才能评论