使用PHP中的组件实现GraphQL服务器

使用PHP中的组件实现GraphQL服务器

GraphQL是一种用于API的查询语言,它使客户能够准确地询问他们需要的数据并准确地接收这些数据,仅此而已。这样,单个查询就可以获取渲染组件所需的所有数据。

(相比之下,一个REST API必须触发多次往返以从不同端点的多个资源中获取数据,这可能会变得非常慢,尤其是在移动设备上。)

尽管GraphQL(意为 “Graph Query Language”)使用图数据模型来表示数据,但GraphQL服务器不一定需要使用图作为数据结构来解析查询,而是可以使用任何需要的数据结构。该图只是一个心理模型,而不是实际实现。

GraphQL项目在其网站graphql.org上声明了这一点:

Graph是对许多现实世界现象进行建模的强大工具,因为它们类似于我们的自然心理模​​型和对潜在过程的口头描述。使用GraphQL,您可以通过定义模式将业务领域建模为图形;在您的架构中,您定义不同类型的节点以及它们如何相互连接/关联。在客户端,这会创建一个类似于面向对象编程的模式:引用其他类型的类型。在服务器上,由于GraphQL只定义了接口,你可以自由地将它与任何后端(新的或旧的!)一起使用

这是个好消息,因为处理图或树(它们是图的子集)并非易事,并且可能导致解决查询的指数或对数时间复杂度(即解决查询所需的时间可能会增加几个订单)查询的每个新输入的数量级)。

在本文中,我们将描述PoP在PHP GraphQL中的GraphQL服务器的架构设计,它使用组件作为数据结构而不是图。该服务器的名字来源于PoP,它是在PHP中构建组件的库,它是基于该库的。

本文分为5个部分,解释:

  1. 什么是组件
  2. PoP的工作原理
  3. PoP中如何定义组件
  4. 组件如何自然地适用于GraphQL
  5. 使用组件解决GraphQL查询的性能

1.什么是组件

每个网页的布局都可以使用组件来表示。组件只是一组代码(例如HTML、JavaScript和CSS)组合在一起以创建一个自治实体,该实体可以包装其他组件以创建更复杂的结构,并且自身也可以被其他组件包装。每个组件都有一个用途,可以是非常基本的东西,例如链接或按钮,也可以是非常复杂的东西,例如轮播或拖放图像上传器。

通过组件构建站点类似于玩乐。例如,在下图中的网页中,简单的组件(链接、按钮、头像)被组合成更复杂的结构(小工具、部分、侧边栏、菜单)一直到顶部,直到我们获得网页:

使用PHP中的组件实现GraphQL服务器

页面是一个wrapping组件的组件,如方框所示

组件可以在客户端(例如JS库Vue和React,或CSS组件库Bootstrap和Material-UI)和服务器端以任何语言实现。

2. PoP的工作原理

PoP描述了一种基于服务器端组件模型的架构,并通过组件模型库在PHP中实现。

在以下部分中,术语“组件”和“模块”可互换使用。

组件层次结构

所有模块相互wrapping的关系,从最顶层的模块一直到最后一层,称为组件层次结构。这种关系可以通过服务器端的关联数组(key=>property)来表示,其中每个模块将其名称声明为关键属性,并将其内部模块声明为属性"modules"

PHP数组中的数据也可以直接在客户端使用,编码为JSON对象。

组件层次结构如下所示:

$componentHierarchy = [
‘module-level0’ => [
“modules” => [
‘module-level1’ => [
“modules” => [
‘module-level11’ => [
“modules” => []
],
‘module-level12’ => [
“modules” => [
‘module-level121’ => [
“modules” => []
]
]
]
]
],
‘module-level2’ => [
“modules” => [
‘module-level21’ => [
“modules” => []
]
]
]
]
]
]
$componentHierarchy = [
‘module-level0’ => [
“modules” => [
‘module-level1’ => [
“modules” => [
‘module-level11’ => [
“modules” => […]
],
‘module-level12’ => [
“modules” => [
‘module-level121’ => [
“modules” => […]
]
]
]
]
],
‘module-level2’ => [
“modules” => [
‘module-level21’ => [
“modules” => […]
]
]
]
]
]
]
$componentHierarchy = [
  'module-level0' => [
    "modules" => [
      'module-level1' => [
        "modules" => [
          'module-level11' => [
            "modules" => [...]
          ],
          'module-level12' => [
            "modules" => [
              'module-level121' => [
                "modules" => [...]
              ]
            ]
          ]
        ]
      ],
      'module-level2' => [
        "modules" => [
          'module-level21' => [
            "modules" => [...]
          ]
        ]
      ]
    ]
  ]
]

 

模块之间的关系以严格的自上而下的方式定义:一个模块wrap了其他模块并且知道它们是谁,但它不知道也不关心哪些模块wraps了他。

例如,在上面的组件层次结构中,模块'module-level1'知道它wrap了模块'module-level11''module-level12',并且,它也知道它wrap了'module-level121';但是模块'module-level11'不关心谁在wrap他,因此不知道'module-level1'.

有了基于组件的结构,我们添加了每个模块所需的实际信息,这些信息分为设置(例如配置值和其他属性)和数据(例如查询的数据库对象的ID和其他属性),并且相应地放在条目modulesettingsmoduledata

$componentHierarchyData = [
“modulesettings” => [
‘module-level0’ => [
“configuration” => [],
,
“modules” => [
‘module-level1’ => [
“configuration” => [],
,
“modules” => [
‘module-level11’ => [
…children…
],
‘module-level12’ => [
“configuration” => [],
,
“modules” => [
‘module-level121’ => [
…children…
]
]
]
]
],
‘module-level2’ => [
“configuration” => [],
,
“modules” => [
‘module-level21’ => [
…children…
]
]
]
]
]
],
“moduledata” => [
‘module-level0’ => [
“dbobjectids” => [],
,
“modules” => [
‘module-level1’ => [
“dbobjectids” => [],
,
“modules” => [
‘module-level11’ => [
…children…
],
‘module-level12’ => [
“dbobjectids” => [],
,
“modules” => [
‘module-level121’ => [
…children…
]
]
]
]
],
‘module-level2’ => [
“dbobjectids” => [],
,
“modules” => [
‘module-level21’ => [
…children…
]
]
]
]
]
]
]
$componentHierarchyData = [
“modulesettings” => [
‘module-level0’ => [
“configuration” => […],
…,
“modules” => [
‘module-level1’ => [
“configuration” => […],
…,
“modules” => [
‘module-level11’ => [
…children…
],
‘module-level12’ => [
“configuration” => […],
…,
“modules” => [
‘module-level121’ => [
…children…
]
]
]
]
],
‘module-level2’ => [
“configuration” => […],
…,
“modules” => [
‘module-level21’ => [
…children…
]
]
]
]
]
],
“moduledata” => [
‘module-level0’ => [
“dbobjectids” => […],
…,
“modules” => [
‘module-level1’ => [
“dbobjectids” => […],
…,
“modules” => [
‘module-level11’ => [
…children…
],
‘module-level12’ => [
“dbobjectids” => […],
…,
“modules” => [
‘module-level121’ => [
…children…
]
]
]
]
],
‘module-level2’ => [
“dbobjectids” => […],
…,
“modules” => [
‘module-level21’ => [
…children…
]
]
]
]
]
]
]
$componentHierarchyData = [
  "modulesettings" => [
    'module-level0' => [
      "configuration" => [...],
      ...,
      "modules" => [
        'module-level1' => [
          "configuration" => [...],
          ...,
          "modules" => [
            'module-level11' => [
              ...children...
            ],
            'module-level12' => [
              "configuration" => [...],
              ...,
              "modules" => [
                'module-level121' => [
                  ...children...
                ]
              ]
            ]
          ]
        ],
        'module-level2' => [
          "configuration" => [...],
          ...,
          "modules" => [
            'module-level21' => [
              ...children...
            ]
          ]
        ]
      ]
    ]
  ],
  "moduledata" => [
    'module-level0' => [
      "dbobjectids" => [...],
      ...,
      "modules" => [
        'module-level1' => [
          "dbobjectids" => [...],
          ...,
          "modules" => [
            'module-level11' => [
              ...children...
            ],
            'module-level12' => [
              "dbobjectids" => [...],
              ...,
              "modules" => [
                'module-level121' => [
                  ...children...
                ]
              ]
            ]
          ]
        ],
        'module-level2' => [
          "dbobjectids" => [...],
          ...,
          "modules" => [
            'module-level21' => [
              ...children...
            ]
          ]
        ]
      ]
    ]
  ]
]

接下来,将数据库对象数据添加到组件层次结构中。此信息不是放在每个模块下,而是放在名为databases的共享部分下,以避免在2个或更多不同模块从数据库中获取相同对象时重复信息。

此外,该库以关系的方式表示数据库对象数据,以避免当两个或多个不同的数据库对象与一个共同的对象相关时(例如两个具有相同作者的文章),信息重复。

换句话说,数据库对象数据是标准化的。该结构是一个字典,首先组织在每个对象类型下,然后是对象ID,我们可以从中获取对象属性:

$componentHierarchyData = [
“databases” => [
“dbobject_type” => [
“dbobject_id” => [
“property” => …,
],
],
]
]
$componentHierarchyData = [

“databases” => [
“dbobject_type” => [
“dbobject_id” => [
“property” => …,

],

],

]
]
$componentHierarchyData = [
  ...
  "databases" => [
    "dbobject_type" => [
      "dbobject_id" => [
        "property" => ...,
        ...
      ],
      ...
    ],
    ...
  ]
]

例如,下面的对象包含一个带有两个模块的组件层次结构"page"=> "post-feed",其中模块"post-feed"获取博客文章。请注意以下事项:

  • 每个模块都知道哪些是其从属性dbobjectids(ID49博客文章)中查询的对象
  • 每个模块从属性中知道其查询对象的对象类型dbkeys(每个文章的数据都在下面找到"posts",文章的作者数据,对应于在文章属性下给出的ID的作者,在下面"author"找到"users"):
  • 因为数据库对象数据是关系型的,所以属性"author"包含作者对象的ID,而不是直接打印作者数据
$componentHierarchyData = [

重要声明

本网站的文章部分内容可能来源于网络,如有侵犯你的权益请联系邮箱:wxzn8@outlook.com
站内资源为网友个人学习或测试研究使用,未经原版权作者许可,禁止用于任何商业途径!请在下载24小时内删除!本站资源大多存储在云盘,如发现链接失效请反馈,我们会及时更新。

给TA打赏
共{{data.count}}人
人已打赏
WordPress开发学习

如何创建WordPress网站浮动固定栏(页眉)

2023-1-13 18:17:13

WordPress开发学习

如何在移动设备上预览WordPress网站

2023-1-13 18:17:32

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
今日签到
有新私信 私信列表
搜索