Skip to content

Commit

Permalink
Merge pull request magento-commerce/devdocs#3215 from magento-devdocs…
Browse files Browse the repository at this point in the history
…/COMDOX-83-migrate-graphql

COMDOX-83: Migrate GraphQL Developer Guide from magento/devdocs
  • Loading branch information
jeff-matthews committed Nov 22, 2022
2 parents 63ad082 + 0856ef0 commit 334dd58
Show file tree
Hide file tree
Showing 222 changed files with 4,903 additions and 82 deletions.
5 changes: 5 additions & 0 deletions src/_data/main-nav.yml
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,11 @@

- label: GraphQL Developer Guide
url: /graphql/
include_versions: ["2.3"]

- label: GraphQL Developer Guide
url: https://developer.adobe.com/commerce/webapi/graphql/
include_versions: ["2.4"]

- label: Marketplace EQP API Reference
url: https://developer.adobe.com/commerce/marketplace/guides/eqp/v1/
Expand Down
6 changes: 4 additions & 2 deletions src/guides/v2.4/graphql/authorization-tokens.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ contributor_name: Atwix
contributor_link: https://www.atwix.com/
redirect_from:
- /guides/v2.4/graphql/get-customer-authorization-token.html
migrated_to: https://developer.adobe.com/commerce/webapi/graphql/usage/authorization-tokens/
layout: migrated
---

Adobe Commerce and Magento Open Source provide two mechanisms for authorizing GraphQL calls:
Expand Down Expand Up @@ -43,7 +45,7 @@ mutation {
{
"data": {
"generateCustomerToken": {
"token": "hoyz7k697ubv5hcpq92yrtx39i7x10um"
"token": "hoyz7k697ubv5hcpq92yrtx39i7x10um" #gitleaks:allow
}
}
}
Expand Down Expand Up @@ -76,7 +78,7 @@ mutation{
{
"data": {
"generateCustomerTokenAsAdmin": {
"customer_token": "cr0717abzoagxty1xjn4lj13kim36r6x"
"customer_token": "cr0717abzoagxty1xjn4lj13kim36r6x" #gitleaks:allow
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/guides/v2.4/graphql/caching.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
---
group: graphql
title: GraphQL caching
migrated_to: https://developer.adobe.com/commerce/webapi/graphql/usage/caching/
layout: migrated
---

Magento can cache pages rendered from the results of certain GraphQL queries with [full-page caching]({{page.baseurl}}/extension-dev-guide/cache/page-caching.html). Full-page caching improves response time and reduces the load on the server. Without caching, each page might need to run blocks of code and retrieve large amounts of information from the database. Only queries submitted with an HTTP GET operation can be cached. POST queries cannot be cached.
Expand Down
1 change: 0 additions & 1 deletion src/guides/v2.4/graphql/custom-filters.md

This file was deleted.

146 changes: 146 additions & 0 deletions src/guides/v2.4/graphql/custom-filters.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
---
group: graphql
title: Filtering with custom attributes
migrated_to: https://developer.adobe.com/commerce/webapi/graphql/usage/custom-filters/
layout: migrated
---

As of Magento 2.3.4, the `filter` attribute of the [`products`]({{page.baseurl}}/graphql/queries/products.html) query accepts the `ProductAttributeFilterInput` object. (In previous versions, the `filter` attribute required a `ProductFilterInput` object. This object contained a hard-coded list of filterable attributes, and you could not filter on a custom attribute or any other attribute that was not on the list.)

## Prerequisites

You have several options when enabling a custom attribute (or any attribute that is not listed by default in the `ProductAttributeFilterInput` object) for filtering. Navigate to the attribute's **Storefront Properties** page (**Stores** > Attributes > **Product** > <attribute name> > **Storefront Properties**) in the Admin, then perform one or both of the following actions:

- Set the **Use in Layered Navigation** field to **Filterable (with results)** or **Filterable (no results)**. This field allows the attribute to be used as a filter and returns layered navigation and aggregation data. If this field is set to **No**, then the attribute will not return layered navigation and aggregation data.

- Set the **Use in Search** and **Visible in Advanced Search** fields to **Yes**. These fields primarily allow Magento to index the attribute's contents, making the data available for quick and advanced searches. Setting both these fields also allows the attribute to be used as a filter. These fields do not configure the presence or absence of layered navigation and aggregation data. If you set only one of these fields to **Yes**, the attribute cannot be used as a filter (unless you set the **Use in Layered Navigation** field to a value other than **No**).

## Define the filter for your query

The [`filter`]({{page.baseurl}}/graphql/queries/products.html#ProductFilterInput) definition for your custom attribute requires one of the following input data types:

- `FilterEqualTypeInput` - Specify this data type when the **Catalog Input Type for Store Owner** field for your custom attribute is set to Yes/No, Select, or Multiple select. Your filter can contain the `eq` or `in` attribute. Use the `eq` attribute to exactly match the specified string. Use the `in` attribute to filter on a comma-separated list of values.
- `FilterMatchTypeInput` - Specify this data type when the **Catalog Input Type for Store Owner** field for your custom attribute is set to Text Field or Text Area. Your filter must contain the `match` attribute, which will return all items that partially fuzzy match the specified string.
- `FilterRangeTypeInput` - Specify this data type when the **Catalog Input Type for Store Owner** field for your custom attribute is set to Price or Date. Your filter can contain one or both of the `to` and `from` attributes, which serve to provide a range of values to filter on.

## Example

In this example, the custom attribute `volume` was assigned to the `bags` attribute group. Running the [`customAttributeMetadata` query]({{page.baseurl}}/graphql/queries/custom-attribute-metadata.html) on this custom attribute reveals that the `label` and `value` values for the attribute's options are as follows:

**Request:**

```graphql
{
customAttributeMetadata(
attributes: [
{
attribute_code: "volume"
entity_type: "catalog_product"
}
]
) {
items {
attribute_code
attribute_type
entity_type
input_type
attribute_options {
value
label
}
}
}
}
```

**Response:**

```graphql
{
"data": {
"customAttributeMetadata": {
"items": [
{
"attribute_code": "volume",
"attribute_type": "Int",
"entity_type": "catalog_product",
"input_type": "select",
"attribute_options": [
{
"value": "216",
"label": "Large"
},
{
"value": "217",
"label": "Medium"
},
{
"value": "218",
"label": "Small"
}
]
}
]
}
}
}
```

`label` | `value`
--- | ---
`Large` | `216`
`Medium` | `217`
`Small` | `218`

In this scenario, a [`products`]({{page.baseurl}}/graphql/queries/products.html) search filtered to return items where the `volume` attribute is set to `Large` would be similar to the following:

**Request:**

```graphql
{
products(filter: { volume: { eq: "216" } }) {
total_count
items {
name
sku
}
}
}
```

**Response:**

The response might be similar to the following:

```json
{
"data": {
"products": {
"total_count": 1,
"items": [
{
"name": "Wayfarer Messenger Bag",
"sku": "24-MB05"
}
]
}
}
}
```

## Output attributes

When a product requires a filter attribute that is not a field on its output schema, inject the attribute name into the class in a module's `di.xml` file.

```xml
<type name="Magento\CatalogGraphQl\Model\Resolver\Products\FilterArgument\ProductEntityAttributesForAst" >
<arguments>
<argument name="additionalAttributes" xsi:type="array">
<item name="field_to_sort" xsi:type="string">field</item>
<item name="other_field_to_sort" xsi:type="string">other_field</item>
</argument>
</arguments>
</type>
```

This example adds `field_to_sort` and `other_field_to_sort` attributes to the `additionalAttributes` array defined in the `ProductEntityAttributesForAst` class. The array already contains the `min_price`, `max_price`, and `category_ids` attributes.

This file was deleted.

66 changes: 66 additions & 0 deletions src/guides/v2.4/graphql/develop/create-custom-url-resolver.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
group: graphql
title: Create a custom GraphQL urlResolver service
migrated_to: https://developer.adobe.com/commerce/webapi/graphql/develop/resolvers/
layout: migrated
---

The `Magento\UrlRewrite` module converts URL rewrite requests to canonical URLs. As a result, your custom `urlResolver` module does not require its own class for performing these actions, but it must be able to save and delete entries in the `url_rewrite` table.

## Create observers

You can use the `Magento\CmsUrlRewrite\Observer\ProcessUrlRewriteSavingObserver` class as the basis for saving URL rewrites. For deleting entries, create a `ProcessUrlRewriteDeleteObserver` class similar to the following:

```php
/**
* Generate urls for UrlRewrite and save it in storage
*
* @param \Magento\Framework\Event\Observer $observer
* @return void
*/
public function execute(EventObserver $observer)
{
/** @var \Magento\MyModule\Model\Page $myEntityPage */
$page = $observer->getEvent()->getObject();

if ($page->isDeleted()) {
$this->urlPersist->deleteByData(
[
UrlRewrite::ENTITY_ID => $page->getId(),
UrlRewrite::ENTITY_TYPE => MyEntityPageUrlRewriteGenerator::ENTITY_TYPE,
]
);
}
}
```
See [Events and observers]({{ page.baseurl }}/extension-dev-guide/events-and-observers.html) for more information about creating an observer.

## Configure the custom module

Update the `graphql.xml` and `events.xml` file in your module's `etc` directory to configure your custom GraphQL `urlResolver` service:

* Add lines similar to the following in your module's `graphql.xml` file to define the enumeration. The `UrlRewriteGraphQl` module defines `UrlRewriteEntityTypeEnum`.

```xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_GraphQl:etc/graphql.xsd">
<type xsi:type="Enum" name="UrlRewriteEntityTypeEnum">
<item name="my_entity">MY_ENTITY</item>
</type>
</config>
```

* Define two events similar to the following in your module's `events.xml` file.

```xml
<event name="mymodule_page_save_after">
<observer name="process_url_rewrite_saving" instance="Magento\MyModuleRewrite\Observer\ProcessUrlRewriteSavingObserver" />
</event>
<event name="mymodule_page_delete_after">
<observer name="process_url_rewrite_delete" instance="Magento\MyModuleRewrite\Observer\ProcessUrlRewriteDeleteObserver" />
</event>
```

## Related Topics

* [Events and observers]({{ page.baseurl }}/extension-dev-guide/events-and-observers.html)
* [urlResolver endpoint]({{ page.baseurl }}/graphql/queries/url-resolver.html)
2 changes: 2 additions & 0 deletions src/guides/v2.4/graphql/develop/create-graphqls-file.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
group: graphql
title: Define the GraphQL schema for a module
redirect_from: /guides/v2.4/graphql/develop/configure-graphql-xml.html
migrated_to: https://developer.adobe.com/commerce/webapi/graphql/develop/
layout: migrated
---

Each module that adds to or extends from a GraphQL schema can do so by placing a `schema.graphqls` file in its `etc` directory. Magento Core adds [`GraphQl`]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/GraphQl) modules based on the purpose of the schema being extended/added and the core modules they depend on. For example, the `CustomerGraphQl` module adds a query and multiple mutations to the `graphql` endpoint to view and modify customer data. The `CustomerGraphQl` module relies on the `Customer` core module.
Expand Down
1 change: 0 additions & 1 deletion src/guides/v2.4/graphql/develop/debugging.md

This file was deleted.

34 changes: 34 additions & 0 deletions src/guides/v2.4/graphql/develop/debugging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
group: graphql
title: Debugging GraphQL queries
contributor_name: Atwix
contributor_link: https://www.atwix.com/
migrated_to: https://developer.adobe.com/commerce/webapi/graphql/develop/debugging/
layout: migrated
---

This topic provides recommendations on how to debug GraphQL requests.

## Debugging with PHPStorm and Xdebug

When [using GraphiQL]({{ page.baseurl }}/graphql/index.html#how-to-access-graphql) or any other client for testing GraphQL queries, you might need to debug the request processing.
You can use Xdebug for debugging the PHP execution of a GraphQL query just as you would for other HTTP requests.
To start debugging, add the `?XDEBUG_SESSION_START=PHPSTORM` parameter to the endpoint URL.
The following example shows how to establish a connection between Xdebug and PHPStorm IDE.

```http
http://<magento2-3-server>/graphql?XDEBUG_SESSION_START=PHPSTORM
```

You can also enable an Xdebug connection for a particular request by setting the corresponding header parameter.

```text
Cookie: XDEBUG_SESSION=PHPSTORM
```

As a result, Xdebug within the PHP execution attempts to make a connection to an IDE. If the IDE is listening, it will give the instructions to Xdebug about breakpoints and other relevant information.

## Related Topics

* [GraphQL request headers]({{ page.baseurl }}/graphql/send-request.html)
* [Exception handling]({{ page.baseurl }}/graphql/develop/exceptions.html)
1 change: 0 additions & 1 deletion src/guides/v2.4/graphql/develop/exceptions.md

This file was deleted.

20 changes: 20 additions & 0 deletions src/guides/v2.4/graphql/develop/exceptions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
group: graphql
title: Exception handling
migrated_to: https://developer.adobe.com/commerce/webapi/graphql/develop/exceptions/
layout: migrated
---

The WebApi module has an implementation to "mask" `LocalizedExceptions` so they aren't exposed to the client. GraphQL accomplishes this by restricting verbose output to only those exceptions implementing `\GraphQL\Error\ClientAware`, and only if the system is in developer mode. In these circumstances, Magento returns a full stack trace. Otherwise, Magento writes these exceptions to the system `exception.log` file while returning an "internal server error" to the client.

You should implement the `\GraphQL\Error\ClientAware` interface to handle errors in your module that are directly related to a GraphQL field having an anticipated exception. If you don't, the client will not receive useful messages. However, you should ensure that you don't implement the `ClientAware` interface for too many exceptions. Doing this risks exposing sensitive data to the client.

Magento provides the following exception classes in `Magento\Framework\GraphQl\Exception`.

Class | Exception category | Description
--- | --- | ---
`GraphQlAlreadyExistsException` | `graphql-already-exists` | Thrown when data already exists
`GraphQlAuthenticationException` | `graphql-authentication` | Thrown when an authentication fails
`GraphQlAuthorizationException` | `graphql-authorization` | Thrown when an authorization error occurs
`GraphQlInputException` | `graphql-input` | Thrown when a query contains invalid input
`GraphQlNoSuchEntityException` | `graphql-no-such-entity` | Thrown when an expected resource doesn't exist
1 change: 0 additions & 1 deletion src/guides/v2.4/graphql/develop/extend-existing-schema.md

This file was deleted.

Loading

0 comments on commit 334dd58

Please sign in to comment.