We should use Service Contracts Layer.
/**
* @var \Magento\Framework\Api\SearchCriteriaBuilder
*/
protected $searchCriteriaBuilder;
/**
* @var \Magento\Eav\Api\AttributeRepositoryInterface
*/
protected $attributeRepository;
public function __construct(
\Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder,
\Magento\Eav\Api\AttributeRepositoryInterface $attributeRepository,
......
)
{
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
$this->attributeRepository = $attributeRepository;
......
}
In your custom method:
$searchCriteria = $this->searchCriteriaBuilder->addFilter('is_user_defined', 1)->create();
$attributeRepository = $this->attributeRepository->getList(
\Magento\Catalog\Api\Data\CategoryAttributeInterface::ENTITY_TYPE_CODE,
$searchCriteria
);
foreach ($attributeRepository->getItems() as $items) {
$items->getAttributeCode();
$items->getFrontendLabel();
}
NOTE: For the entity type code in getList
method, we can find in the eav_entity_type
table.