Magento 2: Creating New Eav Entity and Model (Updated for Data Installation)

This tutorial will show you how to install new EAV Entity and Model Step by Step

Posted on August 2, 2017 in Magento2

Create a new Module

File: module.xml


#app/code/Jeff/DataTutorial/etc/Module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Jeff_DataTutorial" setup_version="0.0.3">
        <sequence>
            <module name="Mage_Eav" />
        </sequence>
    </module>
</config>

File: registration.php


<?php
    \Magento\Framework\Component\ComponentRegistrar::register(
        \Magento\Framework\Component\ComponentRegistrar::MODULE,
        'Jeff_DataTutorial',
        __DIR__
    );

Create Simple Model - Department and Eav Model - Employee

File: Department.php


<?php
#app/code/Jeff/DataTutorial/Model/Department

namespace Jeff\DataTutorial\Model;

use Magento\Framework\Model\AbstractModel;

class Department extends AbstractModel {
    protected function _construct() {
        /* full resource classname */
        $this->_init('Jeff\DataTutorial\Model\ResourceModel\Department');
    }
}

File Employee.php


#app/code/Jeff/DataTutorial/Model/Employee.php

<?php
namespace Jeff\DataTutorial\Model;

use Magento\Framework\Model\AbstractModel;

class Employee extends AbstractModel {
    const ENTITY = 'jeff_employee';

    protected function _construct() {
        /* full resource classname */
        $this->_init('Jeff\DataTutorial\Model\ResourceModel\Employee');
    }
}

Create ResourceModel and Collection for both Simple and Eav Model

file: Department.php


#app/code/Jeff/DataTutorial/Model/ResourceModel/Department.php

<?php
namespace Jeff\DataTutorial\Model\ResourceModel;

use Magento\Framework\Model\ResourceModel\Db\AbstractDb;

class Department extends AbstractDb {
    protected function _construct() {
        /* tablename, primarykey*/
        $this->_init('jeff_department', 'id');
    }
}

file: collection.php


#app/code/Jeff/DataTutorial/Model/ResourceModel/Department/Collection.php
<?php

namespace Jeff\DataTutorial\Model\ResourceModel\Department;

use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;

class Collection extends AbstractCollection {
    protected function _construct() {
        $this->_init('Jeff\DataTutorial\Model\Department', 'Jeff\DataTutorial\Model\ResourceModel\Department');
    }
}

File: Employee.php - ResourceModel


#app/code/Jeff/DataTutorial/Model/Resource/Employee.php
<?php
namespace Jeff\DataTutorial\Model\ResourceModel;

use Magento\Eav\Model\Entity\AbstractEntity;

/*
Our resource class extends from \Magento\Eav\Model\Entity\AbstractEntity, 
and set $this->_read, $this->_write class properties  in _construct() method 
*/
class Employee extends AbstractEntity {
    protected function _construct() {
        $this->_read = 'jeff_employee_read';
        $this->_write = 'jeff+employee_write';
    }

    public function getEntityType() {
        if(empty($this->_type)) {
            $this->setType(\Jeff\DataTutorial\Model\Employee::ENTITY);
        }

        return parent::getEntityType();
    }
}

File: Collection.php - for Employee


#app/code/Jeff/DataTutorial/Model/ResourceModel/Employee/Collection.php
<?php
namespace Jeff\DataTutorial\Model\ResourceModel\Employee;

use Magento\Eav\Model\Entity\Collection\AbstractCollection;

class Collection extends AbstractCollection {
    protected function _construct() {
        /* Full model classname, full resource classname */
        $this->_init(
            'Jeff\DataTutorial\Model\Employee',
            'Jeff\Office\Model\ResourceModel\Employee');
        );
    }
}

Schema Installation script and upgrade script

File: InstallSchema.php


#app/code/Jeff/DataTutorial/Setup/InstallSchema.php
<?php

namespace Jeff\DataTutorial\Setup;

use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;

class InstallSchema implements InstallSchemaInterface {
    /*
     * @param SchemaSetupInterface $setup
     * @param ModuleContextInterface $context
     * @return null
    */
    public function install(SchemaSetupInterface $setup, ModuleContextInterface $context) {
        $setup->startSetup();
        
        $table = $setup->getConnection()
            ->newTable($setup->getTable('jeff_department'))
            ->addColumn(
                'id', 
                \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                null,
                ['identity'=>true, 'unsigned'=>true, 'nullable'=>false, 'primary' => true],
                'Entity ID'
            )
            ->addColumn(
                'name',
                \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                64,
                [],
                'Name'
            )
            ->setComment('Jeff Department Table');

        $setup->getConnection()->createTable($table);

        $employeeEntity = \Jeff\DataTutorial\Model\Employee::ENTITY;

        $table = $setup->getConnection()
            ->newTable($setup->getTable($employeeEntity . '_entity'))
            ->addColumn(
                'entity_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                null,
                ['identity' => true, 'unsigned'=>true, 'nullable'=>false, 'primary' => true],
                'Entity Id'
            )
            ->addColumn(
                'department_id', 
                \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                null,
                ['unsigned'=>true, 'nullable'=>false],
                'Department Id'
            )
            ->addColumn(
                'email',
                \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                64,
                [],
                'EMail'
            )
            ->addColumn(
                'first_name',
                \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                64,
                [],
                'First Name'
            )
            ->addColumn(
                'last_name',
                \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                64,
                [],
                'Last Name'
            )
            ->setComment('Jeff_DataTutorial Employee Table');
        $setup->getConnection()->createTable($table);

        $table = $setup->getConnection()
            ->newTable($setup->getTable($employeeEntity . '_entity_decimal'))
            ->addColumn(
                'value_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                null,
                ['identity'=>true, 'nullable'=>false, 'primary'=>true],
                'Value ID'
            )
            ->addColumn(
                'attribute_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
                null,
                ['unsigned'=>true, 'nullable'=>false, 'default'=>'0'],
                'Attribute Id'
            )
            ->addColumn(
                'store_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
                null,
                ['unsigned'=>true, 'nullable'=>false, 'default'=>'0'],
                'Store ID'
            )
            ->addColumn(
                'entity_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                null,
                ['unsigned' => true, 'nullable'=>false, 'default'=>'0'],
                'Entity Id'
            )
            ->addColumn(
                'value',
                \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL,
                '12,4',
                [],
                'value'
            )
            ->addIndex(
                $setup->getIdxName($employeeEntity . '_entity_decimal',
                ['entity_id', 'attribute_id', 'store_id'],
                \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE),
                ['entity_id', 'attribute_id', 'store_id'],
                ['type'=>\Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE]
            )
            ->addIndex(
                $setup->getIdxName($employeeEntity . '_entity_decimal',
                ['store_id']),
                ['store_id']
            )
            ->addIndex(
                $setup->getIdxName($employeeEntity . '_entity_decimal',
                ['attribute_id']),
                ['attribute_id']
            )
            ->addForeignKey(
                $setup->getFkName(
                    $employeeEntity . '_entity_decimal',
                    'attribute_id',
                    'eav_attribute',
                    'attribute_id'
                ),
                'attribute_id',
                $setup->getTable('eav_attribute'),
                'attribute_id',
                \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
            )
            ->addForeignKey(
                $setup->getFkName(
                    $employeeEntity . '_entity_decimal',
                    'entity_id',
                    $employeeEntity . '_entity',
                    'entity_id'
                ),
                'entity_id',
                $setup->getTable($employeeEntity . '_entity'),
                'entity_id',
                \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
            )
            ->addForeignKey(
                $setup->getFkName(
                    $employeeEntity . '_entity_decimal', 'store_id', 'store', 'store_id'
                ),
                'store_id',
                $setup->getTable('store'),
                'store_id',
                \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
            )
            ->setComment('Employee Decimal Attribute Backend Table');
        $setup->getConnection()->createTable($table);

        $setup->endSetup();
    }
}

File: UpgradeSchema.php


<?php
namespace Jeff\DataTutorial\Setup;

use Magento\Framework\Setup\UpgradeSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;

class UpgradeSchema implements UpgradeSchemaInterface {
    public function upgrade(\Magento\Framework\Setup\SchemaSetupInterface $setup, \Magento\Framework\Setup\ModuleContextInterface $context) {
        $setup->startSetup();
        
        $employeeEntity = \Jeff\DataTutorial\Model\Employee::ENTITY;
        $departmentEntityTable = 'jeff_department';
        $employeeEntityTable = $employeeEntity . '_entity';

        //Adding a foreign key to department_id 
        $setup->getConnection()
            ->addForeignKey(
                $setup->getFkName($employeeEntityTable, 'department_id', $departmentEntityTable, 'entity_id'),
                $setup->getTable($employeeEntityTable),
                'department_id',
                $setup->getTable($departmentEntityTable),
                'entity_id',
                \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
            );

        $table = $setup->getConnection()
            ->newTable($setup->getTable($employeeEntity . '_entity_datetime'))
            ->addColumn(
                'value_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                null,
                ['identity'=>true, 'nullable'=>false, 'primary'=>true],
                'Value ID'
            )
            ->addColumn(
                'attribute_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
                null,
                ['unsigned'=>true, 'nullable'=>false, 'default'=>'0'],
                'Attribute Id'
            )
            ->addColumn(
                'store_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
                null,
                ['unsigned'=>true, 'nullable'=>false, 'default'=>'0'],
                'Store ID'
            )
            ->addColumn(
                'entity_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                null,
                ['unsigned' => true, 'nullable'=>false, 'default'=>'0'],
                'Entity Id'
            )
            ->addColumn(
                'value',
                \Magento\Framework\DB\Ddl\Table::TYPE_DATETIME,
                null,
                [],
                'value'
            )
            ->addIndex(
                $setup->getIdxName($employeeEntity . '_entity_decimal',
                ['entity_id', 'attribute_id', 'store_id'],
                \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE),
                ['entity_id', 'attribute_id', 'store_id'],
                ['type'=>\Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE]
            )
            ->addIndex(
                $setup->getIdxName($employeeEntity . '_entity_datetime',
                ['store_id']),
                ['store_id']
            )
            ->addIndex(
                $setup->getIdxName($employeeEntity . '_entity_datetime',
                ['attribute_id']),
                ['attribute_id']
            )
            ->addForeignKey(
                $setup->getFkName(
                    $employeeEntity . '_entity_datetime',
                    'attribute_id',
                    'eav_attribute',
                    'attribute_id'
                ),
                'attribute_id',
                $setup->getTable('eav_attribute'),
                'attribute_id',
                \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
            )
            ->addForeignKey(
                $setup->getFkName(
                    $employeeEntity . '_entity_datetime',
                    'entity_id',
                    $employeeEntity . '_entity',
                    'entity_id'
                ),
                'entity_id',
                $setup->getTable($employeeEntity . '_entity'),
                'entity_id',
                \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
            )
            ->addForeignKey(
                $setup->getFkName(
                    $employeeEntity . '_entity_datetime', 'store_id', 'store', 'store_id'
                ),
                'store_id',
                $setup->getTable('store'),
                'store_id',
                \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
            )
            ->setComment('Employee Datetime Attribute Backend Table');
        $setup->getConnection()->createTable($table);

        $table = $setup->getConnection()
            ->newTable($setup->getTable($employeeEntity . '_entity_text'))
            ->addColumn(
                'value_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                null,
                ['identity'=>true, 'nullable'=>false, 'primary'=>true],
                'Value ID'
            )
            ->addColumn(
                'attribute_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
                null,
                ['unsigned'=>true, 'nullable'=>false, 'default'=>'0'],
                'Attribute Id'
            )
            ->addColumn(
                'store_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
                null,
                ['unsigned'=>true, 'nullable'=>false, 'default'=>'0'],
                'Store ID'
            )
            ->addColumn(
                'entity_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                null,
                ['unsigned' => true, 'nullable'=>false, 'default'=>'0'],
                'Entity Id'
            )
            ->addColumn(
                'value',
                \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                255,
                [],
                'value'
            )
            ->addIndex(
                $setup->getIdxName($employeeEntity . '_entity_text',
                ['entity_id', 'attribute_id', 'store_id'],
                \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE),
                ['entity_id', 'attribute_id', 'store_id'],
                ['type'=>\Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE]
            )
            ->addIndex(
                $setup->getIdxName($employeeEntity . '_entity_text',
                ['store_id']),
                ['store_id']
            )
            ->addIndex(
                $setup->getIdxName($employeeEntity . '_entity_text',
                ['attribute_id']),
                ['attribute_id']
            )
            ->addForeignKey(
                $setup->getFkName(
                    $employeeEntity . '_entity_text',
                    'attribute_id',
                    'eav_attribute',
                    'attribute_id'
                ),
                'attribute_id',
                $setup->getTable('eav_attribute'),
                'attribute_id',
                \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
            )
            ->addForeignKey(
                $setup->getFkName(
                    $employeeEntity . '_entity_text',
                    'entity_id',
                    $employeeEntity . '_entity',
                    'entity_id'
                ),
                'entity_id',
                $setup->getTable($employeeEntity . '_entity'),
                'entity_id',
                \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
            )
            ->addForeignKey(
                $setup->getFkName(
                    $employeeEntity . '_entity_text', 'store_id', 'store', 'store_id'
                ),
                'store_id',
                $setup->getTable('store'),
                'store_id',
                \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
            )
            ->setComment('Employee text Attribute Backend Table');
        $setup->getConnection()->createTable($table);

        $table = $setup->getConnection()
            ->newTable($setup->getTable($employeeEntity . '_entity_int'))
            ->addColumn(
                'value_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                null,
                ['identity'=>true, 'nullable'=>false, 'primary'=>true],
                'Value ID'
            )
            ->addColumn(
                'attribute_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
                null,
                ['unsigned'=>true, 'nullable'=>false, 'default'=>'0'],
                'Attribute Id'
            )
            ->addColumn(
                'store_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
                null,
                ['unsigned'=>true, 'nullable'=>false, 'default'=>'0'],
                'Store ID'
            )
            ->addColumn(
                'entity_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                null,
                ['unsigned' => true, 'nullable'=>false, 'default'=>'0'],
                'Entity Id'
            )
            ->addColumn(
                'value',
                \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                null, 
                [],
                'value'
            )
            ->addIndex(
                $setup->getIdxName($employeeEntity . '_entity_int',
                ['entity_id', 'attribute_id', 'store_id'],
                \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE),
                ['entity_id', 'attribute_id', 'store_id'],
                ['type'=>\Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE]
            )
            ->addIndex(
                $setup->getIdxName($employeeEntity . '_entity_int',
                ['store_id']),
                ['store_id']
            )
            ->addIndex(
                $setup->getIdxName($employeeEntity . '_entity_int',
                ['attribute_id']),
                ['attribute_id']
            )
            ->addForeignKey(
                $setup->getFkName(
                    $employeeEntity . '_entity_int',
                    'attribute_id',
                    'eav_attribute',
                    'attribute_id'
                ),
                'attribute_id',
                $setup->getTable('eav_attribute'),
                'attribute_id',
                \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
            )
            ->addForeignKey(
                $setup->getFkName(
                    $employeeEntity . '_entity_int',
                    'entity_id',
                    $employeeEntity . '_entity',
                    'entity_id'
                ),
                'entity_id',
                $setup->getTable($employeeEntity . '_entity'),
                'entity_id',
                \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
            )
            ->addForeignKey(
                $setup->getFkName(
                    $employeeEntity . '_entity_int', 'store_id', 'store', 'store_id'
                ),
                'store_id',
                $setup->getTable('store'),
                'store_id',
                \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
            )
            ->setComment('Employee Int Attribute Backend Table');
        $setup->getConnection()->createTable($table);

        $table = $setup->getConnection()
            ->newTable($setup->getTable($employeeEntity . '_entity_varchar'))
            ->addColumn(
                'value_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                null,
                ['identity'=>true, 'nullable'=>false, 'primary'=>true],
                'Value ID'
            )
            ->addColumn(
                'attribute_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
                null,
                ['unsigned'=>true, 'nullable'=>false, 'default'=>'0'],
                'Attribute Id'
            )
            ->addColumn(
                'store_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
                null,
                ['unsigned'=>true, 'nullable'=>false, 'default'=>'0'],
                'Store ID'
            )
            ->addColumn(
                'entity_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                null,
                ['unsigned' => true, 'nullable'=>false, 'default'=>'0'],
                'Entity Id'
            )
            ->addColumn(
                'value',
                \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                256,
                [],
                'value'
            )
            ->addIndex(
                $setup->getIdxName($employeeEntity . '_entity_varchar',
                ['entity_id', 'attribute_id', 'store_id'],
                \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE),
                ['entity_id', 'attribute_id', 'store_id'],
                ['type'=>\Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE]
            )
            ->addIndex(
                $setup->getIdxName($employeeEntity . '_entity_varchar',
                ['store_id']),
                ['store_id']
            )
            ->addIndex(
                $setup->getIdxName($employeeEntity . '_entity_varchar',
                ['attribute_id']),
                ['attribute_id']
            )
            ->addForeignKey(
                $setup->getFkName(
                    $employeeEntity . '_entity_varchar',
                    'attribute_id',
                    'eav_attribute',
                    'attribute_id'
                ),
                'attribute_id',
                $setup->getTable('eav_attribute'),
                'attribute_id',
                \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
            )
            ->addForeignKey(
                $setup->getFkName(
                    $employeeEntity . '_entity_varchar',
                    'entity_id',
                    $employeeEntity . '_entity',
                    'entity_id'
                ),
                'entity_id',
                $setup->getTable($employeeEntity . '_entity'),
                'entity_id',
                \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
            )
            ->addForeignKey(
                $setup->getFkName(
                    $employeeEntity . '_entity_varchar', 'store_id', 'store', 'store_id'
                ),
                'store_id',
                $setup->getTable('store'),
                'store_id',
                \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
            )
            ->setComment('Employee Varchar Attribute Backend Table');
        $setup->getConnection()->createTable($table);

        $setup->endSetup();
    }
}

Data Installation script and upgrade script

InstallData.php:


#app/code/Jeff/DataTutorial/Setup/InstallData.php;

<?php
namespace Jeff\DataTutorial\Setup;

use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;

class InstallData implements InstallDataInterface {
    private $employeeSetupFactory;

    public function __construct(
        \Jeff\DataTutorial\Setup\EmployeeSetupFactory $employeeSetupFactory
    ) {
        $this->employeeSetupFactory = $employeeSetupFactory;
    }

    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) {
        $setup->startSetup();

        $employeeEntity = \Jeff\DataTutorial\Model\Employee::ENTITY;

        $employeeSetup = $this->employeeSetupFactory->create(['setup' => $setup]);

        $employeeSetup->installEntities();

        /*

        Add attributes for the employee entity

        Using the addAttribute method on the instance of \Jeff\DataTutorial\Setup\EmployeeSetupFactory, 
        we are instructing Magento to add a number of attributes to its entity.
        Within addAttribute method, there is a call to the $this->attributeMapper->map($attr, $entityTypeId) method.
        attributeMapper conforms to Magento\Eav\Model\Entity\Setup\PropertyMapperInterface, which looking at 
        vendor/magento/module-eav/etc/di.xml has a preference for the Magento\Eav\Model\Entity\Setup\PropertyMapper\Composite class,
        which further initailize the following mapper classes:

        1) Magento\Eav\Model\Entity\Setup\PropertyMapper
        2) Magento\Customer\Model\ResourceModel\Setup\PropertyMapper
        3) Magento\Catalog\Model\ResourceModel\Setup\PropertyMapper
        4) Magento\ConfigurableProduct\Model\ResourceModel\Setup\PropertyMapper

        Since we are defining our own entity types, the mapper class we are mostly interested in is Magento\Eav\Model\Entity\Setup\PropertyMapper.
        The key strings match the column names in the eav_attribute table, while the value strings match the keys of our array passed to the addAttriubte
        method of within InstallData.php

        */
        $employeeSetup->addAttribute(
            $employeeEntity, 'service_years', ['type' => 'int']
        );

        $employeeSetup->addAttribute(
            $employeeEntity, 'dob', ['type' => 'datetime']
        );

        $employeeSetup->addAttribute(
            $employeeEntity, 'salary', ['type' => 'decimal']
        );

        $employeeSetup->addAttribute(
            $employeeEntity, 'vat_number', ['type' => 'varchar']
        );

        $employeeSetup->addAttribute(
            $employeeEntity, 'not', ['type' => 'text']
        );

        $setup->endSetup();
    }
}

UpgradeData.php


#app/code/Jeff/DataTutorial/Setup/UpgradeData.php;

<?php
namespace Jeff\DataTutorial\Setup;

use Magento\Framework\Setup\UpgradeDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;

/*
UpgradeData conforms to UpgradeDataInterface, which requires the implementation of the upgrade
method taht accepts two parameters of type ModuleDataSetupInterface and ModuelContextInterface. 
We are further adding our own __construct method to which we are passing DepartmentFactory and 
EmployeeeFactory, as we will be using them within the upgrade method as shown next.
*/
class UpgradeData implements UpgradeDataInterface {
    protected $departmentFactory;
    protected $employeeFactory;

    public function __construct(
        \Jeff\DataTutorial\Model\DepartmentFactory $departmentFactory,
        \Jeff\DataTutorial\Model\EmployeeFactory $employeeFactory
    ) {
        $this->departmentFactory = $departmentFactory;
        $this->employeeFactory = $employeeFactory; 
    }

    public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) {
        $setup->startSetup();
       
        $salesDepartment = $this->departmentFactory->create();
        $salesDepartment->setName('Sales');
        $salesDepartment->save();

        $employee = $this->employeeFactory->create();
        $employee->setDepartmentId($salesDepartment->getId());
        $employee->setEmail('jyu@dummy.com');
        $employee->setFirstName('Jeff');
        $employee->setLastName('Yu');
        $employee->setServiceYears(3);
        $employee->setDob('1999-01-01');
        $employee->setSalary('5400.00');
        $employee->setVatNumber('GB12345678');
        $employee->setNote('Just some notes to Jeff');
        $employee->save();

        $setup->endSetup();
    }
}

EmployeeSetup.php


<?php
namespace Jeff\DataTutorial\Setup;
use Magento\Eav\Setup\EavSetup;

/*
What's happening here is that we are extending from the 
\Magento\Eav\Setup\EavSetup class, thus effectively telling Magento
we are about to create our own entity.
We do so by overriding getDefaultEntities.

The getDefaultEntities method returns an array of entities we want to register with Magento.
Within our $entities array, the key $employeeEntity becomes an entry in the eav_entity_type table.

Only a handful of metadata values are required to make our new entity type functional. The entity_model
value should point to our EAV model resourcee class, not the model class.
The table value should equal the name of our EAV entity table in the database.
the attributes array should list any attribute we want crated on this entity.
Attributes and their metadata get created in the eav_attribute table.

What creates attributes and a new entity type is the array we just defined under the getDefaultEntities method.
*/
class EmployeeSetup extends EavSetup {

    public function getDefaultEntities() {

        $employeeEntity = \Jeff\DataTutorial\Model\Employee::ENTITY;

        $entities = [
            $employeeEntity => [
                'entity_model' => 'Jeff\DataTutorial\Model\ResourceModel\Employee', //the full resource model class name 
                'table' => $employeeEntity . '_entity',
                'attributes' => [
                    'department_id' => [
                        'type' => 'static',
                    ],
                    'email' => [
                        'type' => 'static',
                    ],
                    'first_name' => [
                        'type' => 'static',
                    ],
                    'last_name' => [
                        'type' => 'static',
                    ],
                ],
            ],
        ];

        return $entities;
    }
}

Last step

Run following commands to install new module and models :


php bin/magento module:enable Jeff_DataTutorial
php bin/magento setup:upgrade
php bin/magento cache:clean

Get the source code GitHub.

Note: when you try to install this module and you encounter following error, please disable the EAV cache


[PDOException]
There is no active transaction


comments powered by Disqus