accelasearch/sdk-php

允许轻松集成AccelaSearch的产品管理。

0.5 2023-10-19 12:58 UTC

This package is auto-updated.

Last update: 2024-09-19 14:59:04 UTC


README

PHP SDK,用于轻松集成AccelaSearch。

概述

AccelaSearch部署了一个中间的类似SQL的数据库,称为collector,用于存储产品信息,然后用于配置和填充搜索引擎和结果。项目的数据必须以正确的格式存储(有关详细信息,请参阅关于自定义集成的文档)。此SDK公开了一个抽象数据类型(ADT),用于表示AccelaSearch支持的所有不同类型的产品,以及一组方便的数据映射器,可以将数据从/到不同的格式转换,包括JSON、PHP字典和中间SQL格式。

此SDK允许以抽象、语法友好的方式定义产品数据,并从/到collector数据库发送/检索信息,以简化与第三方系统或CMS的集成,而无需了解底层collector数据库模式。请注意,但是,产品映射器将作为整体、原子的实体操作产品,并且将不知道CMS指定的行为,这可能有助于加快同步过程(请参阅限制部分以获取示例)。

要求

此SDK是自包含的,它需要一个最新的PHP版本来运行。

提供的单元测试可以使用PHPUnit 运行,代码文档可以使用PHPDcoumentor 生成。

安装

推荐通过 Composer 安装

composer require accelasearch/sdk-php

可以通过克隆或下载此存储库进行手动安装

git clone https://github.com/accelasearch/sdk-php.git
wget https://github.com/accelasearch/sdk-php/archive/master.zip

概述

在注册AccelaSearch后,系统将发布一个API密钥,例如my-api-key,应将其保密并安全存储。API密钥可用于实例化一个DataMapper\Api\Client对象,该对象允许检索有关支持的CMS和collector的信息。前者应用于创建一个Shop实例,而后者应用于建立到collector的SQL连接,该连接可以用于存储有关商店和产品的信息。为了便于这些操作,AccelaSearch - Product Mapper提供了一些实用工具和外观,它们代表与collector交互的首选方式。

检索信息

可以通过使用DataMapper\Api\Client以及相关的数据映射器,通过AccelaSearch的API系统访问基本信息,例如支持的CMS列表和collector凭据。

use \AccelaSearch\ProductMapper\DataMapper\Api\Client;
use \AccelaSearch\ProductMapper\DataMapper\Api\Cms as CmsMapper;
use \AccelaSearch\ProductMapper\DataMapper\Api\Collector as CollectorMapper;

$client = Client::fromApiKey("my-api-key");
$cms_mapper = new CmsMapper($client);
$collector_mapper = new CollectorMapper($client);

$cms_list = $cms_mapper->search();
$collector = $collector_mapper->read();

连接到Collector

一旦获得一个collector对象(这很可能是通过DataMapper\Api\Collector完成的),就可以用它来建立到collector数据库的连接

use \PDO;

$dbh = new PDO(
    'mysql:host=' . $collector->getHostName() . ';dbname=' . $collector->getDatabaseName(),
    $collector->getUsername(),
    $collector->getPassword(),
    [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
    ]
);

管理商店

可以使用SQL连接实例化一个商店数据映射器,该映射器可以进一步用于将Shop实例插入到collector

use \AccelaSearch\ProductMapper\Shop;
use \AccelaSearch\ProductMapper\DataMapper\Sql\Shop as ShopMapper;

// $cms_list = ...
// $dbh = ...
$shop_mapper = ShopMapper::fromConnection($dbh);
$shop = new Shop("http://www.shop.com", "en", $cms_list[0]);
$shop_mapper->create($shop);

插入时将创建一个唯一的商店标识符,并将其分配给$shop。可以使用该标识符从数据库中检索商店并更新其信息或软删除它

// Shop has identifier 2
$shop = $shop_mapper->read(2);
$shop->setUrl("http://www.new-url.com");
$shop_mapper->update($shop);

// Soft-deletion
$shop->setIsActive(false);
$shop_mapper->update($shop);

注意:不应手动硬删除商店,AccelaSearch 将定期扫描收集器并采取适当措施,最终删除软删除的商店。

管理商品

处理商品数据的首选方式是通过 CollectorFacade,它自动处理 SQL 事务和回滚,插入关系型特征,隐式处理插入与更新。CollectorFacade 需要一个 DataMapper\API\Client 实例以及操作的商店标识符,它将自动检索所有必要的连接信息。

use \AccelaSearch\ProductMapper\DataMapper\Api\Client;
use \AccelaSearch\ProductMapper\CollectorFacade;

$client = Client::fromApiKey("my-api-key");
$collector = new CollectorFacade($client, 2);

CollectorFacade 提供四种与产品交互的方法:loadsearchByExternalIdentifiersavedelete。后者将执行软删除,而 save 将根据商品在收集器中的存在与否执行插入或更新。

// Retrieves item with identifier 42
$item = $collector->load(42);

// Retrieves item having external identifier "ITM0001"
$item = $collector->searchByExternalIdentifier("ITM0001");

// Updates item information
$item->setUrl("http://new-shop-url.com/ITM0001");
$collector->save($item);

// Soft deletion
$collector->delete($item);

商品层级

AccelaSearch 支持九种不同类型的商品

  • 横幅:带有 URL 和图片的横幅(桌面和移动端不同)
  • 页面:通用网页
  • 分类页面:分类或收集器的网页
  • 标准:标准产品
  • 虚拟:Simple 的子类型,通常表示无需运输
  • 可下载:Virtual 的子类型,可下载的项目
  • 可配置:存在一组变体的商品,例如不同颜色或尺寸的衬衫;变体通常表示为 Simple 项目,尽管可以使用任何类型的商品
  • 捆绑:一起销售的项目捆绑
  • 分组:类似于捆绑,由区分捆绑的 CMS(如 Magento)使用

每种类型的商品在主 \AccelaSearch\ProductMapper 下都有一个同名的类。每个类都实现了 ItemInterface,而 SimpleVirtualDownloadableConfigurableBundleGrouped 还实现了 ProductInterface,该接口增加了关于外部标识符、属于零个或多个分类、图片信息、自定义属性以及关于可用性和定价(通过扩展 StockableInterfaceSellableInterface)的信息。

尽管可以通过构造函数创建商品,但实现 ProductInterface 的商品可以通过 ProductFactory 实例化。

use \AccelaSearch\ProductMapper\ProductFactory;

$factory = new ProductFactory();
$simple = $factory->createSimple("http://myshop.com/SIMPLE0001", "SIMPLE0001");
$virtual = $factory->createVirtual("http://myshop.com/VIRTUAL0001", "VIRTUAL0001");
$downloadable = $factory->createDownloadable("http://myshop.com/DOWNLOADABLE0001", "DOWNLOADABLE0001");
$configurable = $factory->createConfigurable("http://myshop.com/CONF0001", "CONF0001");
$bundle = $factory->createBundle("http://myshop.com/BUNDLE0001", "BUNDLE0001");
$grouped = $factory->createVirtual("http://myshop.com/GROUP0001", "GROUP0001");

每个方法都是以它创建的商品类型命名的,并接受商品的 URL 及其外部标识符。每个商品都创建为具有空的可用性、定价和图片信息,并且没有任何分类。

添加标准属性

每个商品都允许通过访问器设置 SKU 和 URL,而产品还允许设置外部标识符、分类、图片信息、库存可用性、定价和自定义属性。前者可以按以下方式访问

// $item = ...
$item->setSku("ITM-003");
$item->setUrl("http://www.myshop.com/catalogue/itm-003");
echo $item->getSku() . " " . $item->getUrl();

// $product = ...
$product->setExternalIdentifier("56");
echo $product->getExternalIdentifier();

以下部分展示了如何处理更复杂的标准信息。

添加分类

在分配给产品之前必须创建(或从收集器读取)分类

use \AccelaSearch\ProductMapper\Category;

$parent_category = new Category("cat-0001", "Fashion", null);
$category = new Category("cat-00075", "Woman", $parent_category);
$category->setUrl("http://www.myshop/categories/75");
$item->addCategory($category);
$item->removeCategory($category);

分类不是由 CollectorFacade 明确处理的,它在需要时将透明地插入或读取数据。相反,可以通过使用 Repository\Sql\Category 存储库或更低级别的数据映射器 DataMapper\Sql\Category 来持久化分类,进行原始操作。

添加图片信息

关于产品图片的信息由 Image 类处理,该类允许为每个图片指定标签、URL 和位置

use \AccelaSearch\ProductMapper\Image;

$image_1 = new Image("main", "http://www.myshop.com/storage/images/001.jpeg", 1);
$image_2 = new Image("over", "http://www.myshop.com/storage/images/002.jpeg", 3);

可以通过 addImage 方法将图片添加到商品中

use \AccelaSearch\ProductMapper\ProductFactory;

$factory = new ProductFactory();
$item = $factory->createSimple("http://myshop.com/SIMPLE0001", "SIMPLE0001");
$item->addImage($image_1)->addImage($image_2);

添加可用性

可用性始终与仓库相关,可能是有限的或无限的。在使用之前,必须创建(或从收集器读取)仓库,可以是虚拟的或物理的(其中纬度和经度是已知的)。通过 ProductFactory 创建产品时,会自动实例化一个空的 Stock\Availability,可以通过其访问器方法进行访问

use \AccelaSearch\ProductMapper\Stock\Warehouse\Virtual as VirtualWarehouse;
use \AccelaSearch\ProductMapper\Stock\Warehouse\Physical as PhysicalWarehouse;
use \AccelaSearch\ProductMapper\Stock\Quantity\Limited as LimitedQuantity;
use \AccelaSearch\ProductMapper\Stock\Quantity\Unlimited as UnlimitedQuantity;

$generic_warehouse = new VirtualWarehouse("warehouse-001");
$brick_warehouse = new PhysicalWarehouse("warehouse-002", 45.0, 13.5);
$five_in_stock = new LimitedQuantity(5);
$unlimited = new UnlimitedQuantity();

// $item = ...
$item->getAvailability()->add(new Stock($generic_warehouse, $five_in_stock))
    ->add(new Stock($brick_warehouse, $unlimited));

允许仓库和数量的任何组合,每个组合都由 Stock\Stock 类进行中介。

添加定价

价格信息始终与客户群体相关,以便为不同用户群体提供不同的价格系统。此外,价格可能因购买数量而异(即多级定价),支持多种货币,并允许指定与列表价格不同的销售价格。在使用之前,必须创建(或从收集器读取)客户群体,而层、货币和销售价格及列表价格是 Price\Price 类的标准属性。通过 ProductFactory 创建产品时,会自动实例化一个空的 Price\Pricing,应通过其访问器方法进行访问

use \AccelaSearch\ProductMapper\Price\CustomerGroup;
use \AccelaSearch\ProductMapper\Price\Price;

$group_1 = new CustomerGroup("standard-group");
$group_2 = new CustomerGroup("webpos-group");

// $item = ...
// Item normally sold for 19.99 USD, now selling for 15.99, no tiers, only for standard-group
$item->getPricing()->add(new Price(19.99, 15.99, "USD", 0, $group_1));
// Same item normally sold for 16.43 EUR, now selling at 13.14 EUR
$item->getPricing()->add(new Price(19.99, 15.99, "USD", 0, $group_1));

// Item selling at 19.99 USD for quantities between 0 and 9, selling at 9.99 if 100 or more units are bought
$item->getPricing()->add(new Price(19.99, 19.99, "USD", 0, $group_1))
    ->add(new Price(9.99, 9.99, "USD", 100, $group_1));

// Same item, but different prices for different customer group, second group gets a discount
$item->getPricing()->add(new Price(19.99, 19.99, "USD", 0, $group_1))
    ->add(new Price(25.99, 21.50, "USD", 0, $group_1));

同一组合的货币、最小数量和组不得插入多次,否则将发生未定义的行为。

添加自定义属性

除了显式处理的属性(URL、sku、价格、可用性等)外,还可以插入自定义属性。每个自定义属性都有一个名称和一系列值,即每个属性都被视为多值。单值必须作为具有单个值的单值属性插入。应在将属性分配给产品之前创建属性

use \AccelaSearch\ProductMapper\Attribute;

$name = new Attribute("name");
$name->addValue("T-Shirt");

$tags = new Attribute("tag");
$tags->addValue("fashion")->addValue("summer")->addValue("light");

// $item = ...
$item->addAttribute($name)
    ->addAttribute($tags);

一旦为产品定义了属性,就可以通过其名称(和可能修改其值列表)检索它

$item->getAttribute("tag")->removeValue("light")->addValue("men");

属性名称应为英文单词,全部小写,单数形式(当适用时),并且不得包含空格。我们建议使用连字符或下划线代替空格。

对于单值属性,有一个简写形式为工厂方法

$item->addAttribute(Attribute::fromNameAndValue("name", "T-Shirt"));

对于属于配置的产品,影响配置的属性必须通过将 isConfigurable 设置为 true 来标记为配置的

$color = new Attribute("color");
$color->addValue("red");
$color->setIsConfigurable(true);

// $configurable_item = ...
// $actual_item = ...
$actual_item->addAttribute($color);

这也可以使用简写形式表示

$actual_item->addAttribute(Attribute::fromNameAndValue("color", "red")->setIsConfigurable(true));

可配置产品

可配置产品是元产品,逻辑上将一组实际(通常是 Simple)产品分组在一起,这些产品之间通过细微的差异(如颜色或大小)而不同。在处理可配置产品时,必须创建并分配一组子产品给父可配置产品。一些子产品的属性应标记为可配置,以便告诉 AccelaSearch 哪些属性使配置,哪些属性不(如前所述)

use \AccelaSearch\ProductMapper\ProductFactory;
use \AccelaSearch\ProductMapper\Attribute;

$factory = new ProductFactory();
$shirt = $factory->createConfigurable("http://www.myshop.com/shirt", "ID:42");
$shirt->setSku("CONF-001");

$blue_shirt = $factory->createSimple("http://www.myshop.com/shirt/blue", "ID:44");
$blue_shirt->setSku("CONF-001-b");
$blue_shirt->addAttribute(Attribute::fromNameAndValue("color", "blue")->setIsConfigurable(true));
$blue_shirt->addAttribute(Attribute::fromNameAndValue("name", "blue shirt"));

$red_shirt = $factory->createSimple("http://www.myshop.com/shirt/red", "ID:45");
$red_shirt->setSku("CONF-001-r");
$red_shirt->addAttribute(Attribute::fromNameAndValue("color", "red")->setIsConfigurable(true));
$red_shirt->addAttribute(Attribute::fromNameAndValue("name", "red shirt"));

$shirt->addVariant($red_shirt)->addVariant($blue_shirt);

尽管示例中没有显示,但建议为父产品和子产品设置定价、可用性和分类信息,因为前者不会从后者继承它们,反之亦然。

捆绑和组合产品

捆绑和组合是元产品,将一组实际(通常是 Simple)产品捆绑在一起销售。在处理捆绑或组合产品时,必须创建并分配一组子产品给父产品。一个产品可以作为同一父产品的子产品出现多次,例如,当一组两个相同的产品一起销售时

use \AccelaSearch\ProductMapper\ProductFactory;
use \AccelaSearch\ProductMapper\Attribute;

$factory = new ProductFactory();
$group = $factory->createGrouped("http://www.myshop.com/group", "ID:48");
$group->setSku("GRP-009");

$bottle = $factory->createSimple("http://www.myshop.com/bottle", "ID:94");
$bottle->setSku("BTL-001");

$paper = $factory->createSimple("http://www.myshop.com/paper", "ID:105");
$bottle->setSku("PPR-001");

// Two bottles and one piece of paper
$group->addProduct($bottle)->addProduct($bottle)->addProduct($paper);

尽管示例中没有显示,但建议为父产品和子产品设置定价、可用性和分类信息,因为前者不会从后者继承它们,反之亦然。