-
Notifications
You must be signed in to change notification settings - Fork 9.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature: EAV attribute setup configuration builder #4279
Feature: EAV attribute setup configuration builder #4279
Conversation
Is this PR correct - #4239? |
@nevvermind, thank you for contribution. Having OO way to declare attributes in setup scripts is a good improvement. However there are some details in implementation that should be avoided in Magento 2.
|
Thanks for the feedback, @vkublytskyi. I'm ok with 1. and 3., but I'm not sure about 2. How would you create those builders with no state? Isn't that what factory generation is for? So you're saying to public function visible($flag = true)
{
$newConfig = clone $this;
$newConfig->attributeConfig->setData('visible', (bool) $flag);
return $newConfig;
} I agree that, because the Obj Manager gets you a singleton by default, it's better to avoid state-fulness, but I find this to be a slight-overkill. But I like it. So how about a main Attribute Configuration object with interface AdditionalAttributeConfiguration
{
public function toArray();
}
CatalogAdditionalConfiguration implements AdditionalAttributeConfiguration
{
// all the methods here
}
CustomerAdditionalConfiguration implements AdditionalAttributeConfiguration
{
// all the methods here
} |
Great stuff! |
Yeah, I thought you wouldn't like it. But:
This is not a case of coupling, but injection. Be it a string I think I'll fallback to |
@nevvermind, I agree that solution with cloning of configuration may looks over-complicated but I believe that more stable code worth it. Another one point that we should be careful about with such approach is memory usage. While Probably most flexible way to implement extensible input types list will be add new dependency like |
Wow! We've gone from a simple array to a full module! 😜 Do you mean
a la With calls like:
Does my code have to do that, or yours, when using the Attribute? |
I don't see a reason to have special factory. So we may have
And than we will have code in
Which can be used like |
a) I didn't mean it to be a special factory, but an auto-generated one, as I don't want to inject an instance of something which may not be used (maybe some won't call b) Must I create c) For the Thanks very much for those snippets. They helped a lot. You actually wrote half of this PR. 😄 |
Good point. And yes, proxy could be used for this. But usage of proxy should be declared in DI config. Class should not expects proxy as a parameter type.
No. We just need have an extension point and remove knowledge about ui component from attribute configuration. Single implementation would be enough. |
Pushed new version. How about now? $productAdditional = $objectManager->get(\Magento\Catalog\Setup\AttributeConfiguration\CatalogConfiguration::class)
->searchable()
->usedForSortBy();
$attrConfiguration = $objectManager->get(\Magento\Eav\Setup\AttributeConfiguration\MainConfiguration::class)
->withAdditionalConfiguration($productAdditional)
->required()
->withFrontendLabel('Label')
->withFrontendInput('text');
$objectManager->get(\Magento\Eav\Setup\EavSetup::class)
->addAttribute(
\Magento\Catalog\Model\Product::ENTITY,
'shiny_new_attribute',
$attrConfiguration->toArray()
); |
Maybe we can use this to hide the differences between Besides, having those two new methods above will make future refactoring easier. I understand why you wouldn't want APIs to change, but concrete implementations, too? Why? |
hey @nevvermind the Travis seems to be failing on something weird. Can you update to latest dev branch and resubmit? |
Internal issue MAGETWO-53266 |
@piotrekkaminski - it already was rebased on the latest. The reason CI's failing is not weird, but it has exactly the same type of error as the previous. Somebody's already starting to code against 5.6. |
Sorry @adragus-inviqa you are right, we had different failures before. We will update Travis to use PHP 5.6 |
@vkublytskyi - the more I look back at this code, the more it seems wrong to use composition. a) A customer attribute configuration ( b) Classes are additive, they're not some other kind of behaviour. c) I don't think M2 will work if you don't provide an additional configuration, so having a setter is counter-intuitive. A constructor arg would be better - in the case of composition, anyway - but I still think composition is wrong in this case. Is there a reason why we shouldn't switch back to inheritance? |
@nevvermind, Agree that there should not be possible to create object that is inconsistent at some point. Also for me For now inheritance looks more native. But it may restrict us in future. E.g. we may have some overlapped sets of attributes that are suitable for different entities. Even now we have duplicated |
I didn't quite get the |
Refactored. Additional configuration objects now need a MainConfiguration instance. |
public function __clone() | ||
{ | ||
$this->attributeConfig = new DataObject($this->attributeConfig->toArray()); | ||
$this->mainConfiguration = clone $this->mainConfiguration; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No reason to clone main configuration here as it's immutable so safely may be shared by several instances
Thanks for reviewing. Amended. |
Such builder should be used when creating new EAV attributes. Currently, creating configuration for only these EAV types is supported: product, category, customer and customer address. Each entity type has its own configuration builder. Tutorial: $productAdditional = $objectManager->get(\Magento\Catalog\Setup\AttributeConfiguration\CatalogConfiguration::class) ->searchable() ->usedForSortBy(); $attrConfiguration = $objectManager->get(\Magento\Eav\Setup\AttributeConfiguration\MainConfiguration::class) ->withAdditionalConfiguration($productAdditional) ->required() ->withFrontendLabel('Label') ->withFrontendInput('text'); $objectManager->get(\Magento\Eav\Setup\EavSetup::class) ->addAttribute( \Magento\Catalog\Model\Product::ENTITY, 'shiny_new_attribute', $attrConfiguration->toArray() );
Can I bother someone to review this again? |
@nevvermind, one more thank you for your PR request and your hard work. And sorry for the delay in response. Now we are working on the design for EAV API and will update you here when it ready. Please share any thoughts on this. One more time thank you for your impact. It raises important issue that should be solved in Magento. |
No worries. At least I got you to update things, maybe to a more declarative approach, far from array keys. :) I don't mind this PR being closed, btw. I'll hopefully see the changes in the CHANGELOG when they arrive; no need to update this thread. |
Opened internal task item MAGETWO-56718 |
Thank you @nevvermind for your contribution and patience. This Pull Request is a long and very interesting story :) |
[arcticfoxes] 2.2-develop PR
/cc #4266
This PR introduces an OOP way of adding EAV attributes, by using attribute configuration builders.
My main concerns with this were:
Only
product
,category
,customer
andcustomer_address
types are supported.Class design looks like this:
All classes introduced here are builders, which get converted into the EAV setup array you all love, nothing more.
Here's how you should use these to add a Product attribute:
You should instantiate the builder of the EAV type you're interested in:
CategoryAttributeConfiguration
for categoryProductAttributeConfiguration
for productCustomerAddressAttributeConfiguration
for customer address, andCustomerAttributeConfiguration
for customerDilemma 1: You might not like that you need a full-blown instance of an UI Element when declaring a frontend input type, just so the code can extract whether it's
text
ormultiselect
etc.:My argument is explicitness. You're assured your input type is there. As all explicit things go, it's more to type. If everybody hates it, I can add another method which accepts a string, but this is my alternative to having just a string param or having many similar methods (@Vinai's suggestion).
Dilemma 2: I'm not sure whether I've covered up all the cases with the attribute configs. I've been mostly looking at
\Magento\Eav\Model\Entity\Setup\PropertyMapperInterface
and\Magento\Eav\Setup\EavSetup::addAttribute()
for keys to pick up.Needless to say - but I'll say it anyway -, suggestions are welcomed.