commercetools / commercetools-sdk
commercetools Composable Commerce API 的官方 PHP SDK
Requires
- php: >=7.2
- ext-json: *
- guzzlehttp/guzzle: ^6.0 || ^7.0
- guzzlehttp/psr7: ^1.7 || ^2.0.0
- psr/cache: ^1.0 || ^2.0 || 3.0
- psr/http-client: ^1.0
- psr/http-message: ^1.0 || ^2.0
- psr/log: ^1.0 || ^2.0 || 3.0
- psr/simple-cache: ^1.0 || ^2.0 || 3.0
- ramsey/uuid: ^4.0
- symfony/cache: ^3.0 || ^4.0 || ^5.0 || ^6.0
Requires (Dev)
- cache/array-adapter: ^1.0
- commercetools/php-sdk: ^2.16
- monolog/monolog: ^1.3 || ^2.0
- phpunit/phpunit: ^9.0 | 8.5.22
- symplify/easy-coding-standard: 12.0.7
- vimeo/psalm: ^4.26
- dev-master
- 10.6.0
- 10.5.0
- 10.4.0
- 10.3.0
- 10.2.0
- 10.1.0
- 10.0.0
- 9.6.1
- 9.6.0
- 9.5.0
- 9.4.0
- 9.3.0
- 9.2.0
- 9.1.0
- 9.0.0
- 8.1.0
- 8.0.0
- 7.1.1
- 7.1.0
- 7.0.0
- 6.0.2
- 6.0.1
- 6.0.0
- v5.0.x-dev
- 5.0.1
- 5.0.0
- 4.4.0
- 4.3.0
- 4.2.0
- 4.1.0
- 4.0.0
- 3.5.0
- 3.4.0
- 3.3.0
- 3.2.0
- 3.1.0
- 3.0.0
- 2.4.0
- 2.3.0
- 2.2.0
- 2.1.1
- 2.1.0
- 2.0.0
- 1.5.0
- 1.4.0
- 1.3.0
- 1.2.0
- 1.1.0
- 1.0.0
- 0.7.1
- 0.7.0
- 0.6.0
- 0.5.1
- 0.5.0
- 0.4.1
- 0.4.0
- 0.3.0
- 0.2.0
- 0.1.0
- dev-bugfix-doxygen-doc
- dev-newrelic-update-config
- dev-test-for-doc
- dev-CUT-1091-mcg
- dev-new-product-search-dfd
- dev-test-order
- dev-raml-remove-java-extends
- dev-TQL-282-docs-check-product-type-exists
- dev-update-order-by-import
- dev-feat-product-selection-variants
- dev-raml-api-reviews
- dev-raml-api-product-types
- dev-raml-api-subscriptions
- dev-raml-api-shipping-methods
- dev-raml-api-stores
- dev-psalm-fix
- dev-raml-api-common-types
- dev-variant_accessor
- dev-test-product-projection-variantsku
- dev-camelCase-restructure-processing-states
- dev-user-agent
- dev-exception_details
- dev-address_draft_support
This package is auto-updated.
Last update: 2024-09-23 09:45:40 UTC
README
主题索引
简介
此存储库包含从 Composable Commerce API 参考生成的 PHP SDK。
客户端和请求构建器,用于向 Commercetools 发送 API 请求。
包和安装
composer require commercetools/commercetools-sdk
技术概述
SDK 包含以下项目
lib/commercetools-base/src
: 包含与 Composable Commerce 通信以执行请求的客户端,还包括与客户端相关的类,如令牌、中间件和处理器,以及映射器和异常。lib/commercetools-api/src
: 包含与 Composable Commerce HTTP API 通信的所有生成的模型和请求构建器。lib/commercetools-import/src
: 包含与 Import API 通信的所有生成的模型和请求构建器。lib/commercetools-history/src
: 包含与 Change History API 通信的所有生成的模型和请求构建器。
此外,SDK 还有以下目录
examples/symfony-app
: 展示如何在启用 NewRelic 监控的 Docker 环境中使用 PHP SDK,以用于 Symfony 应用程序。test/integration
: SDK 的集成测试。任何使用 PHP SDK 的人都通过这种方式更深入地了解它。test/unit
: 单元测试lib/commercetools-api-tests
: 为 api 目录中的每个类生成的单元测试lib/commercetools-history-tests
: 为 history 目录中的每个类生成的单元测试lib/commercetools-import-tests
: 为 import 目录中的每个类生成的单元测试
PHP SDK 利用各种标准接口和组件来确保一致性和互操作性
- JSON 序列化器
- PSR-3 - LoggerInterface
- PSR-4 - Autoloader
- PSR-6 - CachingInterface
- PSR-7 - HTTP Message Interface
- PSR-16 - 缓存库的通用接口
- PSR-18 - HTTP 客户端
- PHP 日期 API
占位符值
本指南中的示例代码使用占位符,应替换为以下值。
如果您没有API客户端,请遵循我们的获取您的API客户端指南。
入门指南
创建客户端
以下示例展示了如何创建一个在创建客户端时传递自定义URI的客户端。您可以在导入API文件夹中找到相同的类。
namespace Commercetools; use Commercetools\Api\Client\ClientCredentialsConfig; use Commercetools\Api\Client\Config; use Commercetools\Client\ClientCredentials; use Commercetools\Client\ClientFactory; require_once __DIR__ . '/vendor/autoload.php'; /** @var string $clientId */ /** @var string $clientSecret */ /** @var string $scope * Provide the scope when you want to request a specific ones for the client. * Can be omitted to use all scopes of the oauth client. * Format: `<the scope name>:<the project key>`. * Example: `manage_products:project1`. $authConfig */ $authConfig = new ClientCredentialsConfig( new ClientCredentials('{clientID}', '{clientSecret}', '{scope}'), [], 'https://auth.{region}.commercetools.com/oauth/token' ); $client = ClientFactory::of()->createGuzzleClient( new Config([], 'https://api.{region}.commercetools.com'), $authConfig );
为不同地区定制端点
默认情况下,库使用api.europe-west1.gcp.commercetools.com
端点。如果您使用不同的区域,可以配置客户端使用自定义端点。以下是us-central1
区域的示例
$authConfig = new ClientCredentialsConfig( new ClientCredentials('{clientId}', '{clientSecret}'), [], 'https://auth.us-central1.gcp.commercetools.com/oauth/token' ); $config = new Config([], 'https://api.us-central1.gcp.commercetools.com'); $client = ClientFactory::of()->createGuzzleClient( $config, $authConfig, );
请注意,认证端点应包含/oauth/token
后缀,但API端点则不需要。
执行请求
产品API所有可用方法的详细信息可以在这里找到
有关导入API的信息可以在这里找到。
获取项目信息的示例
use Commercetools\Api\Client\ApiRequestBuilder; use GuzzleHttp\ClientInterface; /** @var ClientInterface $client */ $builder = new ApiRequestBuilder($client); $request = $builder->withProjectKey('{projectKey}')->get();
为了避免为每个请求指定项目密钥,可以使用Commercetools\Client
命名空间中的实例
use Commercetools\Client\ApiRequestBuilder; use Commercetools\Client\ImportRequestBuilder; use GuzzleHttp\ClientInterface; /** @var ClientInterface $client */ $builder = new ApiRequestBuilder('{projectKey}', $client); $request = $builder->categories()->get(); $importBuilder = new ImportRequestBuilder('{projectKey}', $client); $request = $importBuilder->importSinks()->get();
以下是一些关于如何执行请求的示例
use Commercetools\Client\ApiRequestBuilder; use GuzzleHttp\ClientInterface; /** @var ClientInterface $client */ $builder = new ApiRequestBuilder('{projectKey}', $client); $request = $builder->with()->get(); // executing the request and mapping the response directly to a domain model $project = $request->execute(); // send the request to get the response object $response = $request->send(); // map the response to a domain model $project = $request->mapFromResponse($response); // send the request asynchronously $promise = $request->sendAsync(); // map the response to a domain model $project = $request->mapFromResponse($promise->wait()); // send the request using a client instance $response = $client->send($request); $project = $request->mapFromResponse($response);
配置
应用 PSRs
PHP SDK 利用各种标准接口和组件来确保一致性和互操作性
$authHandler = HandlerStack::create(); $authHandler->push( MiddlewareFactory::createLoggerMiddleware(new Logger('auth', [new StreamHandler('./logs/requests.log')])) ); $authConfig = new ClientCredentialsConfig(new ClientCredentials($clientId, $clientSecret), [ 'handler' => $authHandler, ]); $logger = new Logger('client', [new StreamHandler('./logs/requests.log')]); $client = ClientFactory::of()->createGuzzleClientForHandler( new Config(['maxRetries' => 3]), OAuthHandlerFactory::ofAuthConfig($authConfig), $logger );
use Symfony\Component\Cache\Adapter\FilesystemAdapter; $filesystemCache = new FilesystemAdapter(); $config = new Config(['timeout' => 30]); $client = ClientFactory->createGuzzleClientForHandler( $config, OAuthHandlerFactory::ofAuthConfig($authConfig, $cache) );
//set up the client something like the examples before // create a guzzle request /** @var CategoryBuilder $category */ $request = $client->with()->categories()->withId($category->getId())->get()->withExpand('parent'); $result = $request->execute(); $request = new \GuzzleHttp\Psr7\Request('GET', '{projectKey}/categories/{ID}'); $response = $client->send($request);
use Symfony\Component\Cache\Simple\FilesystemCache; use Symfony\Component\Cache\Psr16Cache; $filesystemCache = new FilesystemAdapter(); $cache = new Psr16Cache($filesystemCache); $config = new Config(['timeout' => 30]); $client = ClientFactory->createGuzzleClientForHandler( $config, OAuthHandlerFactory::ofAuthConfig($authConfig, $cache) );
错误处理
错误处理已由ExceptionFactory类提供。此类中包含的方法封装了将Guzzle异常转换为基于HTTP响应状态码的您自定义异常的逻辑。这些方法可以直接在请求中调用,也可以由专门用于错误处理的中间件调用。在请求处理中直接调用或在中间件中直接处理
if ($e->getCode() >= 500) { throw ExceptionFactory::createServerException($e, $apiRequest, $response, $result); } else { throw ExceptionFactory::createClientException($e, $apiRequest, $response, $result); }
身份验证
工厂类ProviderFactory用于管理认证和令牌处理。
创建令牌存储
要生成一个使用不同流程(刷新流程和匿名流程)管理令牌的TokenStorageProvider,您可以使用ProviderFactory::createTokenStorageProvider($anonTokenUrl, $refreshTokenUrl, $clientCredentials, $client, $tokenStorage, $anonymousIdProvider);
。
密码流程
ProviderFactory::createPasswordFlowProvider($passwordTokenUrl, $clientCredentials, $client, $tokenStorage);
方法创建一个密码流程令牌提供程序,用于使用用户名和密码认证用户,并安全地获取令牌。
匿名流程
createAnonymousFlowProvider($anonTokenUrl, $clientCredentials, $client, $refreshFlowTokenProvider, $anonymousIdProvider);
方法构建一个匿名流程令牌提供程序,用于管理匿名用户的令牌,并与API的匿名令牌端点集成。
刷新流程
createRefreshFlowProvider($refreshTokenUrl, $clientCredentials, $client, $tokenStorage)
方法设置一个刷新流程令牌提供程序,以无缝处理令牌刷新操作,确保持续访问API资源。
中间件
我们在PHP SDK中引入了中间件来添加功能。
您可以在创建PHP SDK客户端时添加中间件。可以使用中间件数组添加多个中间件。
中间件工厂(属于工厂模式)的范围是处理所有可用的中间件,并有机会对它们进行自定义。
此类中包含的方法旨在创建一个中间件数组。
默认中间件
createDefaultMiddlewares方法创建一个包含默认值的数组,包括OAuth处理器、认证、日志、重试和关联ID。
$authConfig = new ClientCredentialsConfig(new ClientCredentials($clientId, $clientSecret), [ 'handler' => $authHandler, ]); $oauthHandler = OAuthHandlerFactory::ofAuthConfig($authConfig), $logger = new Logger('client', [new StreamHandler('./logs/requests.log')]); $maxRetries = 3; $correlationIdProvider = new DefaultCorrelationIdProvider(); $middlewares = MiddlewareFactory::createDefaultMiddlewares( $oauthHandler, $logger, $maxRetries, $correlationIdProvider );
CorrelationId中间件
createCorrelationIdMiddleware方法创建一个中间件,该中间件会将关联ID添加到HTTP请求的头部中。
$correlationIdProvider = new DefaultCorrelationIdProvider(); $correlationIdMiddleware = MiddlewareFactory::createCorrelationIdMiddleware( $correlationIdProvider );
RetryNAMiddleware
方法 createRetryNAMiddleware 旨在创建满足特定条件时重试 HTTP 请求的中介。这种中介在可能出现暂时性错误(如临时服务器不可用)的场景中特别有用。
$maxRetries = 3; $retryMiddleware = MiddlewareFactory::createRetryNAMiddleware($maxRetries);
OAuthHandlerMiddleware
方法 createMiddlewareForOAuthHandler 创建用于处理 OAuth2 认证的中介,确保包括必要的 OAuth 凭证。
$tokenProvider = new YourTokenProvider(); $oauthHandler = OAuthHandlerFactory::ofProvider($tokenProvider), $oauthMiddleware = MiddlewareFactory::createMiddlewareForOAuthHandler($oauthHandler);
LoggerMiddleware
方法 createLoggerMiddleware 创建用于记录 HTTP 请求和响应的中介。
$logger = new Logger('auth'); $logger->pushHandler(new StreamHandler('./logs/requests.log', Logger::DEBUG)); $loggerMiddleware = MiddlewareFactory::createLoggerMiddleware($logger);
ReauthenticateMiddleware
方法 createReauthenticateMiddleware 创建一个中介,在遇到无效令牌错误(HTTP 401)时自动重新认证 HTTP 请求。它使用 OAuth2Handler 来刷新令牌并重试请求,最多重试指定的次数。
$authConfig = new ClientCredentialsConfig(new ClientCredentials($clientId, $clientSecret), [ 'handler' => $authHandler, ]); $oauthHandler = OAuthHandlerFactory::ofAuthConfig($authConfig), //maxRetries have the default value 1 as a second parameter of the function $reauthMiddleware = MiddlewareFactory::createReauthenticateMiddleware($oauthHandler);
查询
以下是我们提到的示例中,我们设置 $builder
如下
use Commercetools\Client\ApiRequestBuilder; use GuzzleHttp\ClientInterface; /** @var ClientInterface $client */ $builder = new ApiRequestBuilder('{projectKey}', $client);
由于大多数传递给 with()
方法的变量都是标量,这意味着我们可以将数组传递给方法的相关参数,如下面的示例所示。
谓词
系统允许在查询 API 时使用谓词。谓词作为查询参数字符串添加到请求本身中。以下示例显示了输入变量的使用
$builder ->customers() ->get() ->withWhere('lastName=:lastName') ->withPredicateVar("lastName", $customerSignIn->getCustomer()->getLastName());
在参数数量可变的情况下,也可以在谓词中使用数组值。
$builder ->productProjections() ->get() ->withWhere('masterVariant(sku in :skus)') ->withPredicateVar("skus", ["foo", "bar"]);
通过 ID/键获取
$builder ->productProjections() ->withId('test_id') ->get();
$builder ->productProjections() ->withKey('test_key') ->get();
排序
有关详细信息,请参阅 排序。
使用单个参数进行排序
$builder ->products() ->get() ->withSort("masterData.current.name.en asc");
使用多个参数进行排序
$builder ->products() ->get() ->withSort(["masterData.current.name.en asc", "id asc"]);
分页
限制返回文档的数量或页面大小
$builder ->products() ->get() ->withLimit(4) ->withOffset(4);
产品和产品类型
创建产品类型
ProductType 类似于定义产品属性结构的模式。
ProductType
包含一个 AttributeDefinition 列表,它对应于每个属性的名称和类型,以及一些其他信息。每个名称/类型对必须在项目范围内是唯一的,因此如果您创建了一个类型为 String 的属性 "foo",您不能创建另一个 ProductType,其中 "foo" 有另一种类型(例如 LocalizedString)。如果您这样做,您将收到类似以下错误消息
"具有名称 'foo' 的属性在产品类型 'exampleproducttype' 中的类型不同。"
在此场景中,我们提供了两个 ProductTypes
: book 和 t-shirt。
book 产品类型包含以下属性
t-shirt 产品类型包含以下属性
$color作为AttributeLocalizedEnumValue,颜色为绿色和红色,以及德语和英语翻译。$size作为AttributePlainEnumValue,尺寸为S、M和X。$laundrySymbols为一组AttributeLocalizedEnumValue,包含温度和烘干方式。$matchingProducts为一组ProductReference,可指向与当前产品相似的产品。$rrp为包含推荐零售价的Money。$availableSince为DateTime,表示产品自何时起在商店中对客户可用。所有可用的属性类型可以在“所有已知实现类”中的AttributeType中找到。
创建书籍产品类型的代码
$isbn = AttributeDefinitionBuilder::of() ->withType(AttributeTextTypeBuilder::of()->build()) ->withName(self::ISBN_ATTR_NAME) ->withLabel(LocalizedStringBuilder::of("ISBN")->build()) ->withIsRequired(false) ->build(); $productType = ProductTypeBuilder::of() ->withName(self::BOOK_PRODUCT_TYPE_NAME) ->withDescription("books") ->withAttributes(AttributeDefinitionCollection::of()->add($isbn)) ->build(); $builder = new ApiRequestBuilder('{projectKey}', $client); $request = $builder ->productTypes() ->withId($productType->getId()) ->get(); $productTypeQueryResponse = $request->execute();
请参阅测试代码
创建T恤产品类型的代码
$green = AttributeLocalizedEnumValueBuilder::of() ->withKey("green") ->withLabel(LocalizedStringBuilder::fromArray(["en" => "green", "de" => "grün"])->build()) ->build(); $red = AttributeLocalizedEnumValueBuilder::of() ->withKey("red") ->withLabel(LocalizedStringBuilder::fromArray(["en" => "red", "de" => "rot"])->build()) ->build(); $color = AttributeDefinitionDraftBuilder::of() ->withName(self::COLOR_ATTR_NAME) ->withLabel(LocalizedStringBuilder::fromArray(["en" => "color"])->build()) ->withType(AttributeLocalizedEnumTypeBuilder::of() ->withValues(AttributeLocalizedEnumValueCollection::fromArray([$green, $red])) ->build()) ->withIsRequired(true) ->build(); $small = AttributePlainEnumValueBuilder::of() ->withKey("S") ->withLabel("S") ->build(); $medium = AttributePlainEnumValueBuilder::of() ->withKey("M") ->withLabel("M") ->build(); $sizeX = AttributePlainEnumValueBuilder::of() ->withKey("X") ->withLabel("X") ->build(); $size = AttributeDefinitionDraftBuilder::of() ->withName(self::SIZE_ATTR_NAME) ->withLabel(LocalizedStringBuilder::fromArray(["en" => "Size"])->build()) ->withType(AttributeEnumTypeBuilder::of() ->withValues(AttributePlainEnumValueCollection::fromArray([$small, $medium, $sizeX])) ->build()) ->withIsRequired(true) ->build(); $cold = AttributeLocalizedEnumValueBuilder::of() ->withKey("cold") ->withLabel(LocalizedStringBuilder::fromArray(["en" => "Wash at or below 30°C ", "de" => "30°C"])->build()) ->build(); $hot = AttributeLocalizedEnumValueBuilder::of() ->withKey("hot") ->withLabel(LocalizedStringBuilder::fromArray(["en" => "Wash at or below 60°C", "de" => "60°C"])->build()) ->build(); $tumbleDrying = AttributeLocalizedEnumValueBuilder::of() ->withKey("tumbleDrying") ->withLabel(LocalizedStringBuilder::fromArray(["en" => "Tumble Drying", "de" => "Trommeltrocknen"])->build()) ->build(); $noTumbleDrying = AttributeLocalizedEnumValueBuilder::of() ->withKey("noTumbleDrying") ->withLabel(LocalizedStringBuilder::fromArray(["en" => "no tumble drying", "de" => "Nicht im Trommeltrockner trocknen"])->build()) ->build(); $laundryLabelType = AttributeSetTypeBuilder::of() ->withElementType(AttributeLocalizedEnumTypeBuilder::of() ->withValues(AttributeLocalizedEnumValueCollection::fromArray([$cold, $hot, $tumbleDrying, $noTumbleDrying])) ->build()) ->build(); $laundrySymbols = AttributeDefinitionDraftBuilder::of() ->withType($laundryLabelType) ->withName(self::LAUNDRY_SYMBOLS_ATTR_NAME) ->withLabel(LocalizedStringBuilder::fromArray(["en" => "washing labels"])->build()) ->withIsRequired(false) ->build(); $matchingProducts = AttributeDefinitionDraftBuilder::of() ->withName(self::MATCHING_PRODUCTS_ATTR_NAME) ->withLabel(LocalizedStringBuilder::fromArray(["en" => "matching products"])->build()) ->withType(AttributeSetTypeBuilder::of() ->withElementType(AttributeReferenceTypeBuilder::of() ->withReferenceTypeId("product") ->build()) ->build()) ->withIsRequired(false) ->build(); $rrp = AttributeDefinitionDraftBuilder::of() ->withName(self::RRP_ATTR_NAME) ->withLabel(LocalizedStringBuilder::fromArray(["en" => "recommended retail price"])->build()) ->withType(AttributeMoneyTypeBuilder::of()->build()) ->withIsRequired(false) ->build(); $availableSince = AttributeDefinitionDraftBuilder::of() ->withName(self::AVAILABLE_SINCE_ATTR_NAME) ->withLabel(LocalizedStringBuilder::fromArray(["en" => "available since"])->build()) ->withType(AttributeDateTimeTypeBuilder::of()->build()) ->withIsRequired(false) ->build(); $attributes = AttributeDefinitionDraftCollection::fromArray([$color, $size, $laundrySymbols, $matchingProducts, $rrp, $availableSince]); $productTypeDraft = ProductTypeDraftBuilder::of() ->withKey(ProductTypeFixture::uniqueProductTypeString()) ->withName(self::PRODUCT_TYPE_NAME) ->withDescription("a 'T' shaped cloth") ->withAttributes($attributes) ->build(); $productType = $builder ->with() ->productTypes() ->post($productTypeDraft) ->execute();
请参阅测试代码
产品类型有一个键(字符串),可以用作逻辑上识别产品类型的键。该键具有唯一约束。
创建产品
要创建产品,您需要引用产品类型。由于开发系统的产品类型ID不会是生产系统的ID,因此有必要按名称查找产品类型
$productType = $builder ->with() ->productTypes() ->get() ->withQueryParam('where', 'name="' . $name . '"') ->execute(); return $productType->getResults()->current() ?: null;
请参阅测试代码
将属性添加到产品变体的最简单方法是使用php ProductVariantDraftBuilder::of()->withAttributes($attributes)
,这允许您直接将属性值放入草案中。但它无法检查您是否放入了正确的对象和类型。
书籍示例
$attributes = AttributeCollection::of() ->add( AttributeBuilder::of() ->withName(self::ISBN_ATTR_NAME) ->withValue("978-3-86680-192-9") ->build()); $productVariantDraft = ProductVariantDraftBuilder::of() ->withAttributes($attributes) ->build(); $productTypeResourceIdentifier = ProductTypeResourceIdentifierBuilder::of() ->withId($productType->getId()) ->build(); $productDraft = ProductDraftBuilder::of() ->withProductType($productTypeResourceIdentifier) ->withName(LocalizedStringBuilder::of()->put("en", "a book")->build()) ->withSlug(LocalizedStringBuilder::of()->put("en", ProductTypeFixture::uniqueProductTypeString())->build()) ->withMasterVariant($productVariantDraft) ->build(); $product = $builder->products() ->post($productDraft) ->execute();
请参阅测试代码
T恤示例
$referenceableProduct = ProductFixture::referenceableProduct($builder); $productType = ProductTypeFixture::fetchProductTypeByName($builder, self::PRODUCT_TYPE_NAME); if (!$productType) { $productType = ProductTypeFixture::createProductType($builder, self::PRODUCT_TYPE_NAME); } $productReference = ProductReferenceBuilder::of()->withId($referenceableProduct->getId())->build(); $datetime = new \DateTime('2015-02-02'); $datetime = $datetime->format(\DateTime::ATOM); $attributes = AttributeCollection::of() ->add(AttributeBuilder::of()->withName(self::COLOR_ATTR_NAME)->withValue("green")->build()) ->add(AttributeBuilder::of()->withName(self::SIZE_ATTR_NAME)->withValue("S")->build()) ->add(AttributeBuilder::of()->withName(self::LAUNDRY_SYMBOLS_ATTR_NAME)->withValue(["cold", "tumbleDrying"])->build()) ->add(AttributeBuilder::of()->withName(self::RRP_ATTR_NAME)->withValue(MoneyBuilder::of()->withCentAmount(300)->withCurrencyCode("EUR")->build())->build()) ->add(AttributeBuilder::of()->withName(self::AVAILABLE_SINCE_ATTR_NAME)->withValue($datetime)->build()) ->add(AttributeBuilder::of()->withName(self::MATCHING_PRODUCTS_ATTR_NAME)->withValue([$productReference])->build()); $productVariantDraft = ProductVariantDraftBuilder::of() ->withAttributes($attributes) ->build(); $productTypeResourceIdentifier = ProductTypeResourceIdentifierBuilder::of() ->withId($productType->getId()) ->build(); $productDraft = ProductDraftBuilder::of() ->withProductType($productTypeResourceIdentifier) ->withKey(ProductFixture::uniqueProductString()) ->withName(LocalizedStringBuilder::of()->put('en', 'basic shirt')->build()) ->withSlug(LocalizedStringBuilder::of()->put('en', ProductFixture::uniqueProductString())->build()) ->withMasterVariant($productVariantDraft) ->build(); $product = $builder->products() ->post($productDraft) ->execute();
请参阅测试代码
字段值错误或不正确的类型将导致带有“InvalidField”错误代码的BadRequestException。
$productType = $builder->productTypes() ->post($productTypeDraft) ->execute(); $productVariantDraft = ProductVariantDraftBuilder::of() ->withAttributes(AttributeCollection::of() ->add(AttributeBuilder::of() ->withName(self::COLOR_ATTR_NAME) ->withValue(1) //1 is of illegal type and of illegal key ->build())) ->build(); $productTypeResourceIdentifier = ProductTypeResourceIdentifierBuilder::of() ->withId($productType->getId()) ->build(); $productDraft = ProductDraftBuilder::of() ->withProductType($productTypeResourceIdentifier) ->withName(LocalizedStringBuilder::of()->put("en", "basic shirt")->build()) ->withSlug(LocalizedStringBuilder::of()->put("en", ProductTypeFixture::uniqueProductTypeString())->build()) ->withMasterVariant($productVariantDraft)
请参阅测试代码
作为替代,您可以在同一位置声明您的属性,并使用这些属性读取和写入属性值
$green = AttributeLocalizedEnumValueBuilder::of() ->withKey("green") ->withLabel(LocalizedStringBuilder::of()->put("en", "green ")->put("de", "grün")->build()) ->build(); $cold = AttributeLocalizedEnumValueBuilder::of() ->withKey("cold") ->withLabel(LocalizedStringBuilder::of()->put("en", "Wash at or below 30°C ")->put("de", "30°C")->build()) ->build(); $tumbleDrying = AttributeLocalizedEnumValueBuilder::of() ->withKey("tumbleDrying") ->withLabel(LocalizedStringBuilder::of()->put("en", "tumble drying")->put("de", "Trommeltrocknen")->build()) ->build(); $productReference = ProductReferenceBuilder::of()->withId($referenceableProduct->getId())->build(); $attributes = AttributeCollection::of() ->add(AttributeBuilder::of()->withName(self::COLOR_ATTR_NAME)->withValue("green")->build()) ->add(AttributeBuilder::of()->withName(self::SIZE_ATTR_NAME)->withValue("S")->build()) ->add(AttributeBuilder::of()->withName(self::LAUNDRY_SYMBOLS_ATTR_NAME)->withValue(["cold", "tumbleDrying"])->build()) ->add(AttributeBuilder::of()->withName(self::RRP_ATTR_NAME)->withValue(MoneyBuilder::of()->withCentAmount(300)->withCurrencyCode("EUR")->build())->build()) ->add(AttributeBuilder::of()->withName(self::AVAILABLE_SINCE_ATTR_NAME)->withValue($datetime)->build()) ->add(AttributeBuilder::of()->withName(self::MATCHING_PRODUCTS_ATTR_NAME)->withValue([$productReference])->build()); $productVariantDraft = ProductVariantDraftBuilder::of() ->withAttributes($attributes) ->build(); $productTypeResourceIdentifier = ProductTypeResourceIdentifierBuilder::of() ->withId($productType->getId()) ->build(); $productDraft = ProductDraftBuilder::of() ->withProductType($productTypeResourceIdentifier) ->withKey(ProductFixture::uniqueProductString()) ->withName(LocalizedStringBuilder::of()->put('en', 'basic shirt')->build()) ->withSlug(LocalizedStringBuilder::of()->put('en', ProductFixture::uniqueProductString())->build()) ->withMasterVariant($productVariantDraft) ->build(); $product = $builder->products() ->post($productDraft) ->execute(); $masterVariant = $product->getMasterData()->getStaged()->getMasterVariant(); foreach ($masterVariant->getAttributes() as $attribute) { if ($attribute->getName() === self::COLOR_ATTR_NAME) { assertEquals($attribute->getValue()->key, "green"); } if ($attribute->getName() === self::SIZE_ATTR_NAME) { assertEquals($attribute->getValue()->key, "S"); }
请参阅测试代码
读取属性
获取属性值的简单方法是通过使用Attribute的getValue()方法,如php $attribute->getValue()
$product = $this->createProduct(); $masterVariant = $product->getMasterData()->getStaged()->getMasterVariant(); foreach ($masterVariant->getAttributes() as $attribute) { if ($attribute->getName() === self::SIZE_ATTR_NAME) { assertEquals($attribute->getValue()->key, "S"); } }
请参阅测试代码
您还可以使用php getValueAs()
方法作为属性的转换,例如,如果您有一个EnumValue,但将其提取为布尔值,因为这些方法将传递的值转换为类型
$product = $builder->products()->post($productDraft)->execute(); $masterVariant = $product->getMasterData()->getStaged()->getMasterVariant(); $result = null; foreach ($masterVariant->getAttributes() as $attribute) { if ($attribute->getName() === self::SIZE_ATTR_NAME) { /** @var AttributeAccessor $attrAccessor */ $attrAccessor = $attribute->with(AttributeAccessor::of()); $result = $attrAccessor->getValueAsBool(); } } $this->assertIsBool($result);
请参阅测试代码
更新产品的属性值
以下是一些关于设置属性值的示例,类似于产品创建
书籍示例
$product = $this->createBookProduct(); $masterVariantId = 1; $productUpdate = ProductUpdateBuilder::of() ->withVersion($product->getVersion()) ->withActions( ProductUpdateActionCollection::fromArray([ ProductSetAttributeActionBuilder::of() ->withVariantId($masterVariantId) ->withName(self::ISBN_ATTR_NAME) ->withValue("978-3-86680-192-8") ->build() ]) )->build(); $productUpdated = $builder ->products() ->withId($product->getId()) ->post($productUpdate) ->execute(); $masterVariant = $productUpdated->getMasterData()->getStaged()->getMasterVariant(); $attribute = ProductTypeFixture::findAttributes($masterVariant->getAttributes(), self::ISBN_ATTR_NAME); assertEquals($attribute->getValue(), "978-3-86680-192-8");
请参阅测试代码
T恤示例
$masterVariantId = 1; $productUpdatedAction = ProductUpdateBuilder::of() ->withVersion($product->getVersion()) ->withActions( ProductUpdateActionCollection::fromArray([ ProductSetAttributeActionBuilder::of() ->withVariantId($masterVariantId) ->withName(self::COLOR_ATTR_NAME) ->withValue("red") ->build(), ProductSetAttributeActionBuilder::of() ->withVariantId($masterVariantId) ->withName(self::SIZE_ATTR_NAME) ->withValue("M") ->build(), ProductSetAttributeActionBuilder::of() ->withVariantId($masterVariantId) ->withName(self::LAUNDRY_SYMBOLS_ATTR_NAME) ->withValue(["cold"]) ->build(), ProductSetAttributeActionBuilder::of() ->withVariantId($masterVariantId) ->withName(self::RRP_ATTR_NAME) ->withValue(MoneyBuilder::of()->withCurrencyCode("EUR")->withCentAmount(2000)->build()) ->build(), ]) )->build(); $productUpdated = $builder ->with() ->products() ->withId($product->getId()) ->post($productUpdatedAction) ->execute(); $attributesUpdatedProduct = $productUpdated->getMasterData()->getStaged()->getMasterVariant()->getAttributes(); self::assertEquals(ProductTypeFixture::findAttribute($attributesUpdatedProduct, self::SIZE_ATTR_NAME)->getValue()->key, "M"); self::assertEquals(ProductTypeFixture::findAttribute($attributesUpdatedProduct, self::COLOR_ATTR_NAME)->getValue()->key, "red"); self::assertEquals(ProductTypeFixture::findAttribute($attributesUpdatedProduct, self::LAUNDRY_SYMBOLS_ATTR_NAME)->getValue()[0]->key, "cold"); self::assertEquals(ProductTypeFixture::findAttribute($attributesUpdatedProduct, self::RRP_ATTR_NAME)->getValue()->centAmount, 2000);
请参阅测试代码
为导入订单创建属性
导入订单属性值的工作方式与更新产品不同。在订单中,您为枚举类型提供完整值,而不是像其他所有类型那样仅提供键。这使得可以在现场创建新的枚举值。其他属性的行为如预期。
示例
$product = $this->createProduct($builder); $attributes = AttributeCollection::of() ->add(AttributeBuilder::of()->withName(self::COLOR_ATTR_NAME)->withValue("yellow")->build()) ->add(AttributeBuilder::of()->withName(self::RRP_ATTR_NAME)->withValue(MoneyBuilder::of()->withCurrencyCode("EUR")->withCentAmount(30)->build())->build()); $productVariantImportDraft = ProductVariantImportDraftBuilder::of() ->withId(1) ->withAttributes($attributes) ->build(); $lineItemImportDraft = LineItemImportDraftBuilder::of() ->withProductId($product->getId()) ->withVariant($productVariantImportDraft) ->withQuantity(1) ->withPrice(ProductFixture::priceDraft()) ->withName(LocalizedStringBuilder::of()->put("en", "product name")->build()) ->build(); $orderImportDraft = OrderImportDraftBuilder::of() ->withLineItems(LineItemImportDraftCollection::of()->add($lineItemImportDraft)) ->withTotalPrice(MoneyBuilder::of()->withCentAmount(20)->withCurrencyCode("EUR")->build()) ->withOrderState(OrderState::COMPLETE) ->build(); $order = $builder->orders() ->importOrder() ->post($orderImportDraft) ->execute(); $productVariant = $order->getLineItems()->current()->getVariant(); $colorAttribute = ProductTypeFixture::findAttribute($productVariant->getAttributes(), self::COLOR_ATTR_NAME); assertEquals("yellow", $colorAttribute->getValue()); $rrpAttribute = ProductTypeFixture::findAttribute($productVariant->getAttributes(), self::RRP_ATTR_NAME); assertEquals(30, $rrpAttribute->getValue()->centAmount);
请参阅测试代码
序列化
在PHP SDK中,一些类实现了JsonSerializable接口,并且它们有一个自定义的jsonSerialize()
方法,以便轻松地将类的实例转换为JSON字符串。这意味着当调用json_encode()
方法时,对象将被正确转换并格式化为JSON字符串。
请参阅以下示例
$messagePayload = new MessageDeliveryPayloadModel( "{projectKey}", null, // Replace with an actual Reference object if needed null, // Replace with an actual UserProvidedIdentifiers object if needed "uniqueId456", // ID 1, // The version new DateTimeImmutable("2024-08-06T12:34:56+00:00"), // CreatedAt new DateTimeImmutable("2024-08-06T12:34:56+00:00"), // LastModifiedAt 42, // SequenceNumber 1, // Resource version null, // Replace with an actual PayloadNotIncluded object if needed "Message" // notification type ); $messagePayloadJSON = json_encode($messagePayload);
从SDK v1迁移指南
要从1.x迁移到2.x,以下有指南
可观察性
要监控和观察SDK,请参阅官方文档可观测性,其中有一个示例应用程序,展示了如何使用New Relic和Datadog监控PHP SDK。
文档
许可
MIT