accelasearch / sdk-php
允许轻松集成AccelaSearch的产品管理。
Requires
- php: >=7.1.0
Requires (Dev)
- phpunit/phpunit: >=7
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
提供四种与产品交互的方法:load
、searchByExternalIdentifier
、save
和 delete
。后者将执行软删除,而 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
,而 Simple
、Virtual
、Downloadable
、Configurable
、Bundle
和 Grouped
还实现了 ProductInterface
,该接口增加了关于外部标识符、属于零个或多个分类、图片信息、自定义属性以及关于可用性和定价(通过扩展 StockableInterface
和 SellableInterface
)的信息。
尽管可以通过构造函数创建商品,但实现 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);
尽管示例中没有显示,但建议为父产品和子产品设置定价、可用性和分类信息,因为前者不会从后者继承它们,反之亦然。