我最终使用Ryan H建议的ObjectFactory方法重写了整个答案。
最终它是一个Helper类,它利用了我在客户对象上创建的一些属性,但是想法是关于如何利用EAV + ObjectFactories来操纵属性选项的
<?php
namespace Stti\Healthday\Helper {
use Magento\Eav\Model\Entity\AttributeFactory;
use Magento\Eav\Model\Entity\Attribute\OptionFactory;
use Magento\Eav\Model\Entity\Attribute\OptionManagementFactory;
use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Framework\App\Helper\Context;
use Magento\Eav\Model\Entity\Attribute;
use Stti\Healthday\Model\RelationFactory;
/**
* Eav data helper
*/
class Data extends AbstractHelper {
protected $optionFactory;
protected $attributeFactory;
protected $relationFactory;
protected $optionManagementFactory;
public function __construct(Context $context, AttributeFactory $attributeFactory, OptionFactory $optionFactory,
RelationFactory $relationFactory,
OptionManagementFactory $optionManagementFactory) {
$this->optionFactory = $optionFactory;
$this->attributeFactory = $attributeFactory;
$this->optionFactory = $optionFactory;
$this->relationFactory = $relationFactory;
$this->optionManagementFactory = $optionManagementFactory;
parent::__construct($context);
}
public function addRelationsHelper($answerJson, $attributeCode) {
// IMPORTANT: READ THIS OR THE CODE BELOW WONT MAKE SENSE!!!!
// Since magento's attribute option model was never meant to
// hold guids, we'll be saving the guid as the label. An option_id will
// get created, which can then be saved to the relationship table. Then
// the label in the attribute_option table can be changed to the actual 'word'
// by looking up all of the options, matching on the guid, and doing a replace.
// At that point, there will be a 1:1 relation between guid, option_id, and the 'word'
// Get the attribute requested
$attribute = $this->attributeFactory->create();
$attribute = $attribute->loadByCode("customer", $attributeCode);
$answers = json_decode($answerJson, true);
// Prepare vars
//$setup = new Mage_Eav_Model_Entity_Setup('core_setup');
$prekeys = array();
$prevalues = array();
foreach ($answers as $answer) {
$prekeys[] = $answer['Key'];
$prevalues[] = $answer['Value'];
}
// load up all relations
// generate an array of matching indexes so we can remove
// them from the array to process
$collection = $this->relationFactory->create()->getCollection();
$removalIds = array();
foreach ($collection as $relation) {
// if the item is already in the magento relations,
// don't attempt to add it to the attribute options
for($cnt = 0; $cnt < sizeof($answers); $cnt++) {
if ($relation['stti_guid'] == $prekeys[$cnt]) {
$removalIds[] = $cnt;
}
}
}
// Remove the values from the arrays we are going to process
foreach($removalIds as $removalId) {
unset($prekeys[$removalId]);
unset($prevalues[$removalId]);
}
// "reindex" the arrays
$keys = array_values($prekeys);
$values = array_values($prevalues);
// prepare the array that will be sent into the attribute model to
// update its option values
$updates = array();
$updates['attribute_id'] = $attribute->getId();
// This section utilizes the DI generated OptionFactory and OptionManagementFactory
// to add the options to the customer attribute specified in the parameters.
for($cnt = 0; $cnt < sizeof($keys); $cnt++) {
$option = $this->optionFactory->create();
$option->setLabel($keys[$cnt]);
$this->optionManagementFactory->create()->add("customer", $attributeCode, $option);
}
// After save, pull all attribute options, compare to the 'keys' array
// and create healthday/relation models if needed
$relationIds = $attribute->getOptions();
$updatedAttributeCount = 0;
$options = array();
$options['value'] = array();
for($cnt = 0; $cnt < sizeof($keys); $cnt++) {
$option_id = 0;
foreach($relationIds as $relationId) {
if ($relationId->getLabel() == $keys[$cnt]) {
$option_id = $relationId['value'];
break;
}
}
if ($option_id > 0) {
// Create the healthday relation utilizing our custom models DI generated ObjectFactories
$relation = $this->relationFactory->create();
$relation->setAttributeId($attribute->getId());
$relation->setOptionId($option_id);
$relation->setSttiGuid($keys[$cnt]);
$relation->save();
// Rename the attribute option value to the 'word'
$options['value'][$option_id][] = $values[$cnt];
$updatedAttributeCount++;
}
}
if ($updatedAttributeCount > 0) {
$attribute->setData('option', $options);
$attribute->save();
}
// Save the relationship to the guid
return $updatedAttributeCount;
}
}
}