I have created custom attribute programmatically. it is not showing in product section in admin panel.I used following commands after create InstallData.php & Options.php files :
php bin/magento setup:upgrade
php bin/magento cache:clean
After it i am not able to find custom attribute on product section in admin.
Code is
1 Create InstallData.php
namespace Matrixsoftware\Matrix\Setup;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory /* For Attribute create */;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
class InstallData implements InstallDataInterface
{
private $eavSetupFactory;
public function __construct(EavSetupFactory $eavSetupFactory)
{
$this->eavSetupFactory = $eavSetupFactory;
}
public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
$setup->startSetup();
/** #var EavSetup $eavSetup */
$eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
$eavSetup->addAttribute(
\Magento\Catalog\Model\Product::ENTITY,
'thickness',/* Custom Attribute Code */
[
'group' => 'Product Details',/* Group name in which you want
to display your custom attribute */
'type' => 'int',/* Data type in which formate your value save in database*/
'backend' => '',
'frontend' => '',
'label' => 'Choose Thickness', /* lablel of your attribute*/
'input' => 'select',
'class' => '',
'source' => 'Matrixsoftware\Matrix\Model\Config\Source\Options',
/* Source of your select type custom attribute options*/
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
/*Scope of your attribute */
'visible' => true,
'required' => true,
'user_defined' => false,
'default' => '',
'searchable' => false,
'filterable' => true,
'comparable' => false,
'visible_on_front' => true,
'used_in_product_listing' => true,
'unique' => false
]
);
$setup->endSetup();
}
}
2.Create Options.php
namespace Matrixsoftware\Matrix\Model\Config\Source;
use Magento\Eav\Model\ResourceModel\Entity\Attribute\OptionFactory;
use Magento\Framework\DB\Ddl\Table;
class Options extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
{
protected $optionFactory;
/*public function __construct(OptionFactory $optionFactory)
{
$this->optionFactory = $optionFactory;
//you can use this if you want to prepare options dynamically
}*/
public function getAllOptions()
{
/* your Attribute options list*/
$this->_options=[ ['label'=>'Select Options', 'value'=>''],
['label'=>'Option1', 'value'=>'1']
['label'=>'Option2', 'value'=>'2']
['label'=>'Option3', 'value'=>'3']
];
return $this->_options;
}
public function getOptionText($value)
{
foreach ($this->getAllOptions() as $option) {
if ($option['value'] == $value) {
return $option['label'];
}
}
return false;
}
public function getFlatColumns()
{
$attributeCode = $this->getAttribute()->getAttributeCode();
return [
$attributeCode => [
'unsigned' => false,
'default' => null,
'extra' => null,
'type' => Table::TYPE_INTEGER,
'nullable' => true,
'comment' => 'Custom Attribute Options ' . $attributeCode . ' column',
],
];
}
}
You use this as well, as I used to create custom product attributes programatically.
app/code/[Vendor]/[Module]/Setup/InstallData.php
namespace [Vendor]\[Module]\Setup;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\DB\Ddl\Table;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Sales\Setup\SalesSetupFactory;
use Magento\Quote\Setup\QuoteSetupFactory;
class InstallData implements InstallDataInterface
{
private $eavSetupFactory;
private $quoteSetupFactory;
private $salesSetupFactory;
/**
* InstallData constructor.
* #param EavSetupFactory $eavSetupFactory
* #param QuoteSetupFactory $quoteSetupFactory
*/
public function __construct(
EavSetupFactory $eavSetupFactory,
QuoteSetupFactory $quoteSetupFactory,
SalesSetupFactory $salesSetupFactory
)
{
$this->eavSetupFactory = $eavSetupFactory;
$this->quoteSetupFactory = $quoteSetupFactory;
$this->salesSetupFactory = $salesSetupFactory;
}
public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
$eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
$quoteSetup = $this->quoteSetupFactory->create(['setup' => $setup]);
$salesSetup = $this->salesSetupFactory->create(['setup' => $setup]);
/**
* Add attributes to the eav/attribute
*/
$eavSetup->addAttribute(
\Magento\Catalog\Model\Product::ENTITY,
'dropdown_attribute',
[
'type' => 'int',
'label' => 'Dropdown Attribute',
'input' => 'select',
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
'visible' => true,
'required' => false,
'user_defined' => true,
'default' => '',
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'used_in_product_listing' => false,
'unique' => false,
'option' => [
'values' => [
'Option 1',
'Option 2',
'Option 3'
],
]
]
);
$attributeSetId = $eavSetup->getDefaultAttributeSetId('catalog_product');
$eavSetup->addAttributeToSet(
'catalog_product',
$attributeSetId,
'General',
'dropdown_attribute'
);
$attributeOptions = [
'type' => Table::TYPE_TEXT,
'visible' => true,
'required' => false
];
}
}
Related
I created a custom module. My module adds the custom attribute to product. Now when I try to add New Product in Magento 2.4.4 , I am getting The "componentType" configuration parameter is required for the "" component. error
Here is My code for InstallData.php
<?php
namespace Vendor\Module\Setup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
class InstallData implements InstallDataInterface
{
private $eavSetupFactory;
public function __construct(EavSetupFactory $eavSetupFactory)
{
$this->eavSetupFactory = $eavSetupFactory;
}
/**
* {#inheritdoc}
*/
public function install(
ModuleDataSetupInterface $setup,
ModuleContextInterface $context
) {
$eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
$eavSetup->addAttribute(
\Magento\Catalog\Model\Product::ENTITY,
'mcwarehouse',
[
'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
'label' => 'Warehouse',
'input' => 'select',
'source' => \Vendor\Module\Model\Product\Attribute\Source\Warehouse::class,
'backend_model' =>\Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend::class,
'required' => false,
'sort_order' => 50,
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
'group' => 'Product Details',
'is_used_in_grid' => true,
'is_visible_in_grid' => false,
'is_filterable_in_grid' => false
]
);
}
}
The error I got is
1 exception(s):
Exception #0 (Magento\Framework\Exception\LocalizedException): The "componentType" configuration parameter is required for the "" component.
I want to add a custom attribute to product in Magento 2.3.3 programmatically.
This is my UpgradeData.php
<?php
namespace Mageplaza\HelloWorld\Setup;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\UpgradeDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
class UpgradeData implements UpgradeDataInterface
{
private $eavSetupFactory;
public function __construct(EavSetupFactory $eavSetupFactory)
{
$this->eavSetupFactory = $eavSetupFactory;
}
public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
$eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
$eavSetup->addAttribute(
\Magento\Catalog\Model\Product::ENTITY,
'sample_attribute',
[
'type' => 'text',
'backend' => '',
'frontend' => '',
'label' => 'Sample Atrribute',
'input' => 'text',
'class' => '',
'source' => '',
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
'visible' => true,
'required' => true,
'user_defined' => false,
'default' => '',
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'used_in_product_listing' => true,
'unique' => false,
'apply_to' => ''
]
);
}
}
When I execute php magento setup:upgrade, nothing happens. I tried InstallData.php but it didn't work either. What am I doing wrong?
Step 1: Create file UpgradeData.php
We will start with the InstallData class which located in app/code/Mageplaza/Setup/UpgradeData.php. The content for this file:
<?php
namespace Mageplaza\HelloWorld\Setup;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
class UpgradeData implements UpgradeDataInterface
{
private $eavSetupFactory;
public function __construct(EavSetupFactory $eavSetupFactory)
{
$this->eavSetupFactory = $eavSetupFactory;
}
}
Step 2: Define the upgrade() method
<?php
public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
}
Step 3: Create custom attribute
<?php
namespace Mageplaza\HelloWorld\Setup;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\UpgradeDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
class UpgradeData implements UpgradeDataInterface
{
private $eavSetupFactory;
public function __construct(EavSetupFactory $eavSetupFactory)
{
$this->eavSetupFactory = $eavSetupFactory;
}
public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
$eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
$eavSetup->addAttribute(
\Magento\Catalog\Model\Product::ENTITY,
'sample_attribute',
[
'type' => 'text',
'backend' => '',
'frontend' => '',
'label' => 'Sample Atrribute',
'input' => 'text',
'class' => '',
'source' => '',
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
'visible' => true,
'required' => true,
'user_defined' => false,
'default' => '',
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'used_in_product_listing' => true,
'unique' => false,
'apply_to' => ''
]
);
}
}
All done, please run the upgrade script php bin/magento setup:upgrade to install the module and the product attribute sample_attribute will be created. After run upgrade complete, please run php bin/magento setup:static-content:deploy and go to product from admin to check the result. it will show like this:
NOTE:- Please clear Cache too before checking.
I am importing some customers with :
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$customerFactory = $objectManager->create('\Magento\Customer\Model\CustomerFactory');
$customer = $objectManager->create('Magento\Customer\Model\Customer')->setWebsiteId(1)->loadByEmail('customrr#custom.com');
try {
if(!empty($customer->getData('email')))
{
$customer->setAttr1(1); // Attr1 = Name of the custom Attribute
$customer->setAttr2(2); // Attr2 = Name of the custom Attribute
}
else
{
$customer = $customerFactory->create()->setWebsiteId(1);
}
$customer->setLastname("Lastname");
$customer->setFirstname("Firsty");
.....
$customer->save();
The customer is saved with all his standard attributes correctly but my new attributes won't be saved anyway. I've also tried :
$customer->setCustomAttribute('Attr1','value');
but this didn't work too.
The custom Attribute are shown correclty in Magentos 2 backoffice and the values are saved correctly too if creating a customer manually.
Have you tried:
$customer-> setData('Attr1','value');
and don't forget to save and log the information:
try {
$customer->save();
} catch (\Exception $e) {
// log exception so you can debug the issue if there is one
}
<?php
namespace Custom\Module\Setup;
use Magento\Eav\Model\Config;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
class InstallData implements InstallDataInterface
{
private $eavSetupFactory;
public function __construct(
EavSetupFactory $eavSetupFactory,
Config $eavConfig
) {
$this->eavSetupFactory = $eavSetupFactory;
$this->eavConfig = $eavConfig;
}
public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
$eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
$eavSetup->addAttribute(\Magento\Customer\Model\Customer::ENTITY, 'custom_attribute', [
'label' => 'Label',
'system' => 0,
'position' => 720,
'sort_order' => 720,
'visible' => true,
'note' => '',
'type' => 'int',
'input' => 'boolean',
'source' => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean',
'backend' => \Custom\Module\Model\Customer\Attribute\Backend\DoWHatEver::class,
]
);
$attribute = $this->getEavConfig()->getAttribute(\Magento\Customer\Model\Customer::ENTITY, 'custom_attribute');
$attribute->addData([
'is_user_defined' => 1,
'is_required' => 0,
'default_value' => 0,
'used_in_forms', ['adminhtml_customer']
])->save();
}
public function getEavConfig()
{
return $this->eavConfig;
}
}
I found similar topics, but they are not up to date.
I have to generate around 1000 orders with random products. I found good article about creating orders http://inchoo.net/magento/programmatically-create-order-in-magento/ but it's kinda old and it's not working on version 1.9.
I get following errors:
array (size=5)
0 => string 'Please specify the product's option(s).' (length=39)
1 => string 'Please specify the product's option(s).' (length=39)
2 => string 'Please specify the product's option(s).' (length=39)
3 => string 'Please specify the product's option(s).' (length=39)
4 => string 'Please specify the product's option(s).' (length=39)
#0 E:\xampp\htdocs\magento\app\code\core\Mage\Adminhtml\Model\Sales\Order\Create.php(1631): Mage::throwException('')
#1 E:\xampp\htdocs\magento\app\code\core\Mage\Adminhtml\Model\Sales\Order\Create.php(1523): Mage_Adminhtml_Model_Sales_Order_Create->_validate()
As you can see in my create method I add options to product, so why do I get this errors?
Here is my class
class MyNamespace_MyModule_Model_Generate_Sample {
protected $orderData;
protected $product;
public function run()
{
//$customer is a random customer object
$product = Mage::getModel('catalog/product')->load(342);
$this->product = $product;
$this->orderData = array(
'session' => array(
'customer_id' => $customer->getId(),
'store_id' => Mage::app()->getStore('default')->getId(),
),
'payment' => array(
'method' => 'checkmo',
),
'add_products' =>array(
$product->getId() => array('qty' => 1),
),
'order' => array(
'currency' => 'USD',
'account' => array(
'group_id' => $customer->getGroupId(),
'email' => $customer->getEmail()
),
'billing_address' => array(
'customer_address_id' => $customer->getCustomerAddressId(),
'prefix' => '',
'firstname' => $customer->getFirstname(),
'middlename' => '',
'lastname' => $customer->getLastname(),
'suffix' => '',
'company' => '',
'street' => array($customer->getStreet(),''),
'city' => $customer->getCity(),
'country_id' => $customer->getCountryId(),
'region' => '',
'region_id' => $customer->getRegionId(),
'postcode' => $customer->getPostcode(),
'telephone' => $customer->getTelephone(),
'fax' => '',
),
'shipping_address' => array(
'customer_address_id' => $customer->getCustomerAddressId(),
'prefix' => '',
'firstname' => $customer->getFirstname(),
'middlename' => '',
'lastname' => $customer->getLastname(),
'suffix' => '',
'company' => '',
'street' => array($customer->getStreet(),''),
'city' => $customer->getCity(),
'country_id' => $customer->getCountryId(),
'region' => '',
'region_id' => $customer->getRegionId(),
'postcode' => $customer->getPostcode(),
'telephone' => $customer->getTelephone(),
'fax' => '',
),
'shipping_method' => 'flatrate_flatrate',
'comment' => array(
'customer_note' => 'This order has been programmatically created via import script.',
),
'send_confirmation' => 0
),
);
$this->create();
}
/**
* Creates order
*/
public function create()
{
$orderData = $this->orderData;
if (!empty($orderData)) {
$this->_initSession($orderData['session']);
$this->_processQuote($orderData);
if (!empty($orderData['payment'])) {
$this->_getOrderCreateModel()->setPaymentData($orderData['payment']);
$this->_getOrderCreateModel()->getQuote()->getPayment()->addData($orderData['payment']);
}
$item = $this->_getOrderCreateModel()->getQuote()->getItemByProduct($this->product);
foreach($this->product->getAttributes() as $option)
{
if ($option->getIsVisibleOnFront()) {
$item->addOption(new Varien_Object(
array(
'product' => $this->product,
'code' => $option->getAttributeCode(),
'value' => $option->getFrontend()->getValue($this->product)
)
));;
}
}
Mage::app()->getStore()->setConfig(Mage_Sales_Model_Order::XML_PATH_EMAIL_ENABLED, "0");
$_order = $this->_getOrderCreateModel()
->importPostData($orderData['order'])
->createOrder();
$this->_getSession()->clear();
Mage::unregister('rule_data');
return $_order;
}
return null;
}
protected function _processQuote($data = array())
{
/* Saving order data */
if (!empty($data['order'])) {
$this->_getOrderCreateModel()->importPostData($data['order']);
}
$this->_getOrderCreateModel()->getBillingAddress();
$this->_getOrderCreateModel()->setShippingAsBilling(true);
/* Just like adding products from Magento admin grid */
if (!empty($data['add_products'])) {
$this->_getOrderCreateModel()->addProducts($data['add_products']);
}
/* Collect shipping rates */
$this->_getOrderCreateModel()->collectShippingRates();
/* Add payment data */
if (!empty($data['payment'])) {
$this->_getOrderCreateModel()->getQuote()->getPayment()->addData($data['payment']);
}
$this->_getOrderCreateModel()
->initRuleData()
->saveQuote();
if (!empty($data['payment'])) {
$this->_getOrderCreateModel()->getQuote()->getPayment()->addData($data['payment']);
}
return $this;
}
/**
* Retrieve order create model
*
* #return Mage_Adminhtml_Model_Sales_Order_Create
*/
protected function _getOrderCreateModel()
{
return Mage::getSingleton('adminhtml/sales_order_create');
}
/**
* Retrieve session object
*
* #return Mage_Adminhtml_Model_Session_Quote
*/
protected function _getSession()
{
return Mage::getSingleton('adminhtml/session_quote');
}
/**
* Initialize order creation session data
*
* #param array $data
* #return Mage_Adminhtml_Sales_Order_CreateController
*/
protected function _initSession($data)
{
/* Get/identify customer */
if (!empty($data['customer_id'])) {
$this->_getSession()->setCustomerId((int) $data['customer_id']);
}
/* Get/identify store */
if (!empty($data['store_id'])) {
$this->_getSession()->setStoreId((int) $data['store_id']);
}
return $this;
}
}
Thanks for any help
I have defined a fieldset for phone numbers. This contains fields "type" (private, Office mobile ...) and "number". The Input filter for number is "required => true":
``
class PhoneFieldset extends BaseFieldset implements InputFilterProviderInterface
{
public function __construct()
{
parent::__construct('phones');
$this->setHydrator(new DoctrineHydrator($this->getEntityManager(), 'HtsBase\Entity\Phone'))
->setObject(new Phone());
$this->add(array(
'type' => 'DoctrineORMModule\Form\Element\EntitySelect',
'name' => 'type',
'options' => array(
'label' => 'Type',
'empty_option' => '',
'object_manager' => $this->getEntityManager(),
'target_class' => 'HtsBase\Entity\OptionlistPhoneType',
'property' => 'name',
),
'attributes' => array(
#'id' => 'type',
'class' => 'input-medium',
),
));
$this->add(array(
'name' => 'number',
'options' => array(
'label' => 'Number',
),
'attributes' => array(
'type' => 'text',
#'id' => 'number',
'class' => 'input-medium',
'maxlength' => '25',
'autocomplete' => 'off',
),
));
}
public function getInputFilterSpecification()
{
return array(
'type' => array(
'required' => false,
),
'number' => array(
'required' => true,
'filters' => array(
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'max' => 25,
),
),
),
),
);
}
``
Can i attach a validator/filter to the entire fieldset? So that if "type" AND "number" are empty the fieldset is valid, but validate if least one is filled out?
I found an easy to use solution, although I don't use the form any more I now heavily use the InputFilter and still needed the same stuff. But found an easy solution
The AbstractFilterValidator, my own implementation
abstract class AbstractFilterValidator extends AbstractValidator
{
/**
* Returns true if and only if $value meets the validation requirements
*
* If $value fails validation, then this method returns false, and
* getMessages() will return an array of messages that explain why the
* validation failed.
*
* #param mixed $value
* #return bool
* #throws Exception\RuntimeException If validation of $value is impossible
*/
public function isValid($value)
{
$this->setValue($value);
$filter = $this->buildFilter();
$filter->setData($value);
if (!$filter->isValid()) {
$this->abstractOptions['messages'] = $filter->getMessages();
return false;
}
return true;
}
/**
* #return array
*/
public function getMessages()
{
return $this->abstractOptions['messages'];
}
/**
* #return InputFilter\InputFilter
*/
abstract protected function buildFilter();
}
Old answer
Although you were using the InputFilterProviderInterface, I used Zend\InputFilter\InputFilter and wanted the same as you. If the fieldset was not filled in, validate true.
To do this I replace isValid with the following;
public function isValid()
{
$values = array_filter($this->getRawValues());
if (empty($values)) {
return true;
}
return parent::isValid();
}
It simply filters the array from all empty array keys, see docs for info about that. Then a check if the $values is empty, and if so return true. Else the validators are called.
Well I needed something again but needed a decent solution. Still no luck finding a good one, so I wrote the following code.
<?php
namespace Application\InputFilter;
use Zend\InputFilter as ZFI;
class InputFilter extends ZFI\InputFilter
{
private $required = true;
/**
* #return boolean
*/
public function isRequired()
{
return $this->required;
}
/**
* #param boolean $required
*
* #return $this
*/
public function setRequired($required)
{
$this->required = (bool) $required;
return $this;
}
/**
* #return bool
*/
public function isValid()
{
if (!$this->isRequired() && empty(array_filter($this->getRawValues()))) {
return true;
}
return parent::isValid();
}
}
github gist
You can now simply call setRequired(false) on a InputFilter