Eaventity

Use the snippet in the Magento 2 module creator.

Files

Model/TestRepository.php

<?php
declare(strict_types=1);

namespace Mage2Gen\Module\Model;

use Mage2Gen\Module\Api\Data\TestInterfaceFactory;
use Mage2Gen\Module\Api\Data\TestSearchResultsInterfaceFactory;
use Mage2Gen\Module\Api\TestRepositoryInterface;
use Mage2Gen\Module\Model\ResourceModel\Test as ResourceTest;
use Mage2Gen\Module\Model\ResourceModel\Test\CollectionFactory as TestCollectionFactory;
use Magento\Framework\Api\DataObjectHelper;
use Magento\Framework\Api\ExtensibleDataObjectConverter;
use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface;
use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface;
use Magento\Framework\Exception\CouldNotDeleteException;
use Magento\Framework\Exception\CouldNotSaveException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Reflection\DataObjectProcessor;
use Magento\Store\Model\StoreManagerInterface;

class TestRepository implements TestRepositoryInterface
{

    protected $resource;

    protected $testFactory;

    protected $testCollectionFactory;

    protected $searchResultsFactory;

    protected $dataObjectHelper;

    protected $dataObjectProcessor;

    protected $dataTestFactory;

    protected $extensionAttributesJoinProcessor;

    private $storeManager;

    private $collectionProcessor;

    protected $extensibleDataObjectConverter;

    /**
     * @param ResourceTest $resource
     * @param TestFactory $testFactory
     * @param TestInterfaceFactory $dataTestFactory
     * @param TestCollectionFactory $testCollectionFactory
     * @param TestSearchResultsInterfaceFactory $searchResultsFactory
     * @param DataObjectHelper $dataObjectHelper
     * @param DataObjectProcessor $dataObjectProcessor
     * @param StoreManagerInterface $storeManager
     * @param CollectionProcessorInterface $collectionProcessor
     * @param JoinProcessorInterface $extensionAttributesJoinProcessor
     * @param ExtensibleDataObjectConverter $extensibleDataObjectConverter
     */
    public function __construct(
        ResourceTest $resource,
        TestFactory $testFactory,
        TestInterfaceFactory $dataTestFactory,
        TestCollectionFactory $testCollectionFactory,
        TestSearchResultsInterfaceFactory $searchResultsFactory,
        DataObjectHelper $dataObjectHelper,
        DataObjectProcessor $dataObjectProcessor,
        StoreManagerInterface $storeManager,
        CollectionProcessorInterface $collectionProcessor,
        JoinProcessorInterface $extensionAttributesJoinProcessor,
        ExtensibleDataObjectConverter $extensibleDataObjectConverter
    ) {
        $this->resource = $resource;
        $this->testFactory = $testFactory;
        $this->testCollectionFactory = $testCollectionFactory;
        $this->searchResultsFactory = $searchResultsFactory;
        $this->dataObjectHelper = $dataObjectHelper;
        $this->dataTestFactory = $dataTestFactory;
        $this->dataObjectProcessor = $dataObjectProcessor;
        $this->storeManager = $storeManager;
        $this->collectionProcessor = $collectionProcessor;
        $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor;
        $this->extensibleDataObjectConverter = $extensibleDataObjectConverter;
    }

    /**
     * {@inheritdoc}
     */
    public function save(
        \Mage2Gen\Module\Api\Data\TestInterface $test
    ) {
        /* if (empty($test->getStoreId())) {
            $storeId = $this->storeManager->getStore()->getId();
            $test->setStoreId($storeId);
        } */
        
        $testData = $this->extensibleDataObjectConverter->toNestedArray(
            $test,
            [],
            \Mage2Gen\Module\Api\Data\TestInterface::class
        );
        
        $testModel = $this->testFactory->create()->setData($testData);
        
        try {
            $this->resource->save($testModel);
        } catch (\Exception $exception) {
            throw new CouldNotSaveException(__(
                'Could not save the test: %1',
                $exception->getMessage()
            ));
        }
        return $testModel->getDataModel();
    }

    /**
     * {@inheritdoc}
     */
    public function get($testId)
    {
        $test = $this->testFactory->create();
        $this->resource->load($test, $testId);
        if (!$test->getId()) {
            throw new NoSuchEntityException(__('Test with id "%1" does not exist.', $testId));
        }
        return $test->getDataModel();
    }

    /**
     * {@inheritdoc}
     */
    public function getList(
        \Magento\Framework\Api\SearchCriteriaInterface $criteria
    ) {
        $collection = $this->testCollectionFactory->create();
        
        $this->extensionAttributesJoinProcessor->process(
            $collection,
            \Mage2Gen\Module\Api\Data\TestInterface::class
        );
        
        $this->collectionProcessor->process($criteria, $collection);
        
        $searchResults = $this->searchResultsFactory->create();
        $searchResults->setSearchCriteria($criteria);
        
        $items = [];
        foreach ($collection as $model) {
            $items[] = $model->getDataModel();
        }
        
        $searchResults->setItems($items);
        $searchResults->setTotalCount($collection->getSize());
        return $searchResults;
    }

    /**
     * {@inheritdoc}
     */
    public function delete(
        \Mage2Gen\Module\Api\Data\TestInterface $test
    ) {
        try {
            $testModel = $this->testFactory->create();
            $this->resource->load($testModel, $test->getEntityId());
            $this->resource->delete($testModel);
        } catch (\Exception $exception) {
            throw new CouldNotDeleteException(__(
                'Could not delete the Test: %1',
                $exception->getMessage()
            ));
        }
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function deleteById($testId)
    {
        return $this->delete($this->get($testId));
    }
}

Model/Test.php

<?php
declare(strict_types=1);

namespace Mage2Gen\Module\Model;

use Mage2Gen\Module\Api\Data\TestInterface;
use Mage2Gen\Module\Api\Data\TestInterfaceFactory;
use Magento\Framework\Api\DataObjectHelper;

class Test extends \Magento\Framework\Model\AbstractModel
{

    const ENTITY = 'mage2gen_test_entity';
    protected $testDataFactory;

    protected $dataObjectHelper;

    protected $_eventPrefix = 'mage2gen_test_entity';

    /**
     * @param \Magento\Framework\Model\Context $context
     * @param \Magento\Framework\Registry $registry
     * @param TestInterfaceFactory $testDataFactory
     * @param DataObjectHelper $dataObjectHelper
     * @param \Mage2Gen\Module\Model\ResourceModel\Test $resource
     * @param \Mage2Gen\Module\Model\ResourceModel\Test\Collection $resourceCollection
     * @param array $data
     */
    public function __construct(
        \Magento\Framework\Model\Context $context,
        \Magento\Framework\Registry $registry,
        TestInterfaceFactory $testDataFactory,
        DataObjectHelper $dataObjectHelper,
        \Mage2Gen\Module\Model\ResourceModel\Test $resource,
        \Mage2Gen\Module\Model\ResourceModel\Test\Collection $resourceCollection,
        array $data = []
    ) {
        $this->testDataFactory = $testDataFactory;
        $this->dataObjectHelper = $dataObjectHelper;
        parent::__construct($context, $registry, $resource, $resourceCollection, $data);
    }

    /**
     * Retrieve test model with test data
     * @return TestInterface
     */
    public function getDataModel()
    {
        $testData = $this->getData();
        
        $testDataObject = $this->testDataFactory->create();
        $this->dataObjectHelper->populateWithArray(
            $testDataObject,
            $testData,
            TestInterface::class
        );
        
        return $testDataObject;
    }
}

Model/ResourceModel/Test.php

<?php
declare(strict_types=1);

namespace Mage2Gen\Module\Model\ResourceModel;

class Test extends \Magento\Eav\Model\Entity\AbstractEntity
{

    /**
     * Define resource model
     *
     * @return void
     */
    protected function _construct()
    {
        $this->setType('mage2gen_test_entity');
    }
}

Model/ResourceModel/Test/Collection.php

<?php
declare(strict_types=1);

namespace Mage2Gen\Module\Model\ResourceModel\Test;

class Collection extends \Magento\Eav\Model\Entity\Collection\AbstractCollection
{

    /**
     * Define resource model
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_init(
            \Mage2Gen\Module\Model\Test::class,
            \Mage2Gen\Module\Model\ResourceModel\Test::class
        );
    }
}

Model/Data/Test.php

<?php
declare(strict_types=1);

namespace Mage2Gen\Module\Model\Data;

use Mage2Gen\Module\Api\Data\TestInterface;

class Test extends \Magento\Framework\Api\AbstractExtensibleObject implements TestInterface
{

    /**
     * Get entity_id
     * @return string|null
     */
    public function getEntityId()
    {
        return $this->_get(self::ENTITY_ID);
    }

    /**
     * Set entity_id
     * @param string $entityId
     * @return \Mage2Gen\Module\Api\Data\TestInterface
     */
    public function setEntityId($entityId)
    {
        return $this->setData(self::ENTITY_ID, $entityId);
    }

    /**
     * Get title
     * @return string|null
     */
    public function getTitle()
    {
        return $this->_get(self::TITLE);
    }

    /**
     * Set title
     * @param string $title
     * @return \Mage2Gen\Module\Api\Data\TestInterface
     */
    public function setTitle($title)
    {
        return $this->setData(self::TITLE, $title);
    }

    /**
     * Retrieve existing extension attributes object or create a new one.
     * @return \Mage2Gen\Module\Api\Data\TestExtensionInterface|null
     */
    public function getExtensionAttributes()
    {
        return $this->_getExtensionAttributes();
    }

    /**
     * Set an extension attributes object.
     * @param \Mage2Gen\Module\Api\Data\TestExtensionInterface $extensionAttributes
     * @return $this
     */
    public function setExtensionAttributes(
        \Mage2Gen\Module\Api\Data\TestExtensionInterface $extensionAttributes
    ) {
        return $this->_setExtensionAttributes($extensionAttributes);
    }
}

etc/db_schema.xml

<?xml version="1.0" ?>
<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<table name="mage2gen_test_entity_datetime" resource="default" engine="innodb" comment="mage2gen_test_entity_datetime Table">
		<column xsi:type="int" name="value_id" padding="11" unsigned="false" nullable="false" identity="true" comment="Value ID"/>
		<column xsi:type="smallint" name="attribute_id" padding="5" unsigned="true" nullable="false" identity="false" default="0" comment="Attribute ID"/>
		<column xsi:type="int" name="entity_id" padding="10" unsigned="true" nullable="false" identity="false" default="0" comment="Entity ID"/>
		<constraint xsi:type="primary" referenceId="PRIMARY">
			<column name="value_id"/>
		</constraint>
		<constraint xsi:type="foreign" referenceId="MAGE2GEN_TEST_ENTITY_DATETIME_ATTRIBUTE_ID_EAV_ATTRIBUTE_ATTRIBUTE_ID" table="mage2gen_test_entity_datetime" column="attribute_id" referenceTable="eav_attribute" referenceColumn="attribute_id" onDelete="CASCADE"/>
		<constraint xsi:type="foreign" referenceId="MAGE2GEN_TEST_ENTITY_DATETIME_ENTITY_ID_MAGE2GEN_TEST_ENTITY_ENTITY_ID" table="mage2gen_test_entity_datetime" column="entity_id" referenceTable="mage2gen_test_entity" referenceColumn="entity_id" onDelete="CASCADE"/>
		<constraint xsi:type="unique" referenceId="MAGE2GEN_TEST_ENTITY_DATETIME_ENTITY_ID_ATTRIBUTE_ID">
			<column name="entity_id"/>
			<column name="attribute_id"/>
		</constraint>
		<index referenceId="MAGE2GEN_TEST_ENTITY_DATETIME_ATTRIBUTE_ID" indexType="btree">
			<column name="attribute_id"/>
		</index>
		<index referenceId="MAGE2GEN_TEST_ENTITY_DATETIME_ENTITY_ID_ATTRIBUTE_ID_VALUE" indexType="btree">
			<column name="entity_id"/>
			<column name="attribute_id"/>
			<column name="value"/>
		</index>
		<column xsi:type="datetime" name="value" on_update="false" nullable="false" comment="Value"/>
	</table>
	<table name="mage2gen_test_entity_decimal" resource="default" engine="innodb" comment="mage2gen_test_entity_decimal Table">
		<column xsi:type="int" name="value_id" padding="11" unsigned="false" nullable="false" identity="true" comment="Value ID"/>
		<column xsi:type="smallint" name="attribute_id" padding="5" unsigned="true" nullable="false" identity="false" default="0" comment="Attribute ID"/>
		<column xsi:type="int" name="entity_id" padding="10" unsigned="true" nullable="false" identity="false" default="0" comment="Entity ID"/>
		<constraint xsi:type="primary" referenceId="PRIMARY">
			<column name="value_id"/>
		</constraint>
		<constraint xsi:type="foreign" referenceId="MAGE2GEN_TEST_ENTITY_DECIMAL_ATTRIBUTE_ID_EAV_ATTRIBUTE_ATTRIBUTE_ID" table="mage2gen_test_entity_decimal" column="attribute_id" referenceTable="eav_attribute" referenceColumn="attribute_id" onDelete="CASCADE"/>
		<constraint xsi:type="foreign" referenceId="MAGE2GEN_TEST_ENTITY_DECIMAL_ENTITY_ID_MAGE2GEN_TEST_ENTITY_ENTITY_ID" table="mage2gen_test_entity_decimal" column="entity_id" referenceTable="mage2gen_test_entity" referenceColumn="entity_id" onDelete="CASCADE"/>
		<constraint xsi:type="unique" referenceId="MAGE2GEN_TEST_ENTITY_DECIMAL_ENTITY_ID_ATTRIBUTE_ID">
			<column name="entity_id"/>
			<column name="attribute_id"/>
		</constraint>
		<index referenceId="MAGE2GEN_TEST_ENTITY_DECIMAL_ATTRIBUTE_ID" indexType="btree">
			<column name="attribute_id"/>
		</index>
		<index referenceId="MAGE2GEN_TEST_ENTITY_DECIMAL_ENTITY_ID_ATTRIBUTE_ID_VALUE" indexType="btree">
			<column name="entity_id"/>
			<column name="attribute_id"/>
			<column name="value"/>
		</index>
		<column xsi:type="decimal" name="value" scale="4" precision="12" unsigned="false" nullable="false" default="0" comment="Value"/>
	</table>
	<table name="mage2gen_test_entity_int" resource="default" engine="innodb" comment="mage2gen_test_entity_int Table">
		<column xsi:type="int" name="value_id" padding="11" unsigned="false" nullable="false" identity="true" comment="Value ID"/>
		<column xsi:type="smallint" name="attribute_id" padding="5" unsigned="true" nullable="false" identity="false" default="0" comment="Attribute ID"/>
		<column xsi:type="int" name="entity_id" padding="10" unsigned="true" nullable="false" identity="false" default="0" comment="Entity ID"/>
		<constraint xsi:type="primary" referenceId="PRIMARY">
			<column name="value_id"/>
		</constraint>
		<constraint xsi:type="foreign" referenceId="MAGE2GEN_TEST_ENTITY_INT_ATTRIBUTE_ID_EAV_ATTRIBUTE_ATTRIBUTE_ID" table="mage2gen_test_entity_int" column="attribute_id" referenceTable="eav_attribute" referenceColumn="attribute_id" onDelete="CASCADE"/>
		<constraint xsi:type="foreign" referenceId="MAGE2GEN_TEST_ENTITY_INT_ENTITY_ID_MAGE2GEN_TEST_ENTITY_ENTITY_ID" table="mage2gen_test_entity_int" column="entity_id" referenceTable="mage2gen_test_entity" referenceColumn="entity_id" onDelete="CASCADE"/>
		<constraint xsi:type="unique" referenceId="MAGE2GEN_TEST_ENTITY_INT_ENTITY_ID_ATTRIBUTE_ID">
			<column name="entity_id"/>
			<column name="attribute_id"/>
		</constraint>
		<index referenceId="MAGE2GEN_TEST_ENTITY_INT_ATTRIBUTE_ID" indexType="btree">
			<column name="attribute_id"/>
		</index>
		<index referenceId="MAGE2GEN_TEST_ENTITY_INT_ENTITY_ID_ATTRIBUTE_ID_VALUE" indexType="btree">
			<column name="entity_id"/>
			<column name="attribute_id"/>
			<column name="value"/>
		</index>
		<column xsi:type="int" name="value" padding="11" unsigned="false" nullable="false" identity="false" default="0" comment="Value"/>
	</table>
	<table name="mage2gen_test_entity_text" resource="default" engine="innodb" comment="mage2gen_test_entity_text Table">
		<column xsi:type="int" name="value_id" padding="11" unsigned="false" nullable="false" identity="true" comment="Value ID"/>
		<column xsi:type="smallint" name="attribute_id" padding="5" unsigned="true" nullable="false" identity="false" default="0" comment="Attribute ID"/>
		<column xsi:type="int" name="entity_id" padding="10" unsigned="true" nullable="false" identity="false" default="0" comment="Entity ID"/>
		<constraint xsi:type="primary" referenceId="PRIMARY">
			<column name="value_id"/>
		</constraint>
		<constraint xsi:type="foreign" referenceId="MAGE2GEN_TEST_ENTITY_TEXT_ATTRIBUTE_ID_EAV_ATTRIBUTE_ATTRIBUTE_ID" table="mage2gen_test_entity_text" column="attribute_id" referenceTable="eav_attribute" referenceColumn="attribute_id" onDelete="CASCADE"/>
		<constraint xsi:type="foreign" referenceId="MAGE2GEN_TEST_ENTITY_TEXT_ENTITY_ID_MAGE2GEN_TEST_ENTITY_ENTITY_ID" table="mage2gen_test_entity_text" column="entity_id" referenceTable="mage2gen_test_entity" referenceColumn="entity_id" onDelete="CASCADE"/>
		<constraint xsi:type="unique" referenceId="MAGE2GEN_TEST_ENTITY_TEXT_ENTITY_ID_ATTRIBUTE_ID">
			<column name="entity_id"/>
			<column name="attribute_id"/>
		</constraint>
		<index referenceId="MAGE2GEN_TEST_ENTITY_TEXT_ATTRIBUTE_ID" indexType="btree">
			<column name="attribute_id"/>
		</index>
		<column xsi:type="text" name="value" nullable="true" comment="Value"/>
	</table>
	<table name="mage2gen_test_entity_varchar" resource="default" engine="innodb" comment="mage2gen_test_entity_varchar Table">
		<column xsi:type="int" name="value_id" padding="11" unsigned="false" nullable="false" identity="true" comment="Value ID"/>
		<column xsi:type="smallint" name="attribute_id" padding="5" unsigned="true" nullable="false" identity="false" default="0" comment="Attribute ID"/>
		<column xsi:type="int" name="entity_id" padding="10" unsigned="true" nullable="false" identity="false" default="0" comment="Entity ID"/>
		<constraint xsi:type="primary" referenceId="PRIMARY">
			<column name="value_id"/>
		</constraint>
		<constraint xsi:type="foreign" referenceId="MAGE2GEN_TEST_ENTITY_VARCHAR_ATTRIBUTE_ID_EAV_ATTRIBUTE_ATTRIBUTE_ID" table="mage2gen_test_entity_varchar" column="attribute_id" referenceTable="eav_attribute" referenceColumn="attribute_id" onDelete="CASCADE"/>
		<constraint xsi:type="foreign" referenceId="MAGE2GEN_TEST_ENTITY_VARCHAR_ENTITY_ID_MAGE2GEN_TEST_ENTITY_ENTITY_ID" table="mage2gen_test_entity_varchar" column="entity_id" referenceTable="mage2gen_test_entity" referenceColumn="entity_id" onDelete="CASCADE"/>
		<constraint xsi:type="unique" referenceId="MAGE2GEN_TEST_ENTITY_VARCHAR_ENTITY_ID_ATTRIBUTE_ID">
			<column name="entity_id"/>
			<column name="attribute_id"/>
		</constraint>
		<index referenceId="MAGE2GEN_TEST_ENTITY_VARCHAR_ATTRIBUTE_ID" indexType="btree">
			<column name="attribute_id"/>
		</index>
		<index referenceId="MAGE2GEN_TEST_ENTITY_VARCHAR_ENTITY_ID_ATTRIBUTE_ID_VALUE" indexType="btree">
			<column name="entity_id"/>
			<column name="attribute_id"/>
			<column name="value"/>
		</index>
		<column xsi:type="varchar" name="value" nullable="true" length="255" comment="Value"/>
	</table>
	<table name="mage2gen_test_entity" resource="default" engine="innodb" comment="mage2gen_test_entity Table">
		<column xsi:type="int" name="entity_id" padding="10" unsigned="true" nullable="false" identity="true" comment="Entity Id"/>
		<constraint xsi:type="primary" referenceId="PRIMARY">
			<column name="entity_id"/>
		</constraint>
		<column xsi:type="varchar" name="title" nullable="true"/>
	</table>
</schema>

etc/di.xml

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
	<preference for="Mage2Gen\Module\Api\TestRepositoryInterface" type="Mage2Gen\Module\Model\TestRepository"/>
	<preference for="Mage2Gen\Module\Api\Data\TestInterface" type="Mage2Gen\Module\Model\Data\Test"/>
	<preference for="Mage2Gen\Module\Api\Data\TestSearchResultsInterface" type="Magento\Framework\Api\SearchResults"/>
</config>

Api/TestRepositoryInterface.php

<?php
declare(strict_types=1);

namespace Mage2Gen\Module\Api;

use Magento\Framework\Api\SearchCriteriaInterface;

interface TestRepositoryInterface
{

    /**
     * Save Test
     * @param \Mage2Gen\Module\Api\Data\TestInterface $test
     * @return \Mage2Gen\Module\Api\Data\TestInterface
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    public function save(
        \Mage2Gen\Module\Api\Data\TestInterface $test
    );

    /**
     * Retrieve Test
     * @param string $entityId
     * @return \Mage2Gen\Module\Api\Data\TestInterface
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    public function get($entityId);

    /**
     * Retrieve Test matching the specified criteria.
     * @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria
     * @return \Mage2Gen\Module\Api\Data\TestSearchResultsInterface
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    public function getList(
        \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria
    );

    /**
     * Delete Test
     * @param \Mage2Gen\Module\Api\Data\TestInterface $test
     * @return bool true on success
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    public function delete(
        \Mage2Gen\Module\Api\Data\TestInterface $test
    );

    /**
     * Delete Test by ID
     * @param string $entityId
     * @return bool true on success
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    public function deleteById($entityId);
}

Api/Data/TestInterface.php

<?php
declare(strict_types=1);

namespace Mage2Gen\Module\Api\Data;

interface TestInterface extends \Magento\Framework\Api\ExtensibleDataInterface
{

    const ENTITY_ID = 'entity_id';
    const TITLE = 'title';

    /**
     * Get entity_id
     * @return string|null
     */
    public function getEntityId();

    /**
     * Set entity_id
     * @param string $entityId
     * @return \Mage2Gen\Module\Api\Data\TestInterface
     */
    public function setEntityId($entityId);

    /**
     * Get title
     * @return string|null
     */
    public function getTitle();

    /**
     * Set title
     * @param string $title
     * @return \Mage2Gen\Module\Api\Data\TestInterface
     */
    public function setTitle($title);

    /**
     * Retrieve existing extension attributes object or create a new one.
     * @return \Mage2Gen\Module\Api\Data\TestExtensionInterface|null
     */
    public function getExtensionAttributes();

    /**
     * Set an extension attributes object.
     * @param \Mage2Gen\Module\Api\Data\TestExtensionInterface $extensionAttributes
     * @return $this
     */
    public function setExtensionAttributes(
        \Mage2Gen\Module\Api\Data\TestExtensionInterface $extensionAttributes
    );
}

Api/Data/TestSearchResultsInterface.php

<?php
declare(strict_types=1);

namespace Mage2Gen\Module\Api\Data;

interface TestSearchResultsInterface extends \Magento\Framework\Api\SearchResultsInterface
{

    /**
     * Get Test list.
     * @return \Mage2Gen\Module\Api\Data\TestInterface[]
     */
    public function getItems();

    /**
     * Set title list.
     * @param \Mage2Gen\Module\Api\Data\TestInterface[] $items
     * @return $this
     */
    public function setItems(array $items);
}

Setup/TestSetup.php

<?php
declare(strict_types=1);

namespace Mage2Gen\Module\Setup;

use Magento\Eav\Setup\EavSetup;

class TestSetup extends EavSetup
{

    public function getDefaultEntities()
    {
        return [
             \Mage2Gen\Module\Model\Test::ENTITY => [
                'entity_model' => \Mage2Gen\Module\Model\ResourceModel\Test::class,
                'table' => 'mage2gen_test_entity',
                'attributes' => [
                    'title' => [
                        'type' => 'static'
                    ]
                ]
            ]
        ];
    }
}

Setup/Patch/Data/DefaultTestEntity.php

<?php
declare(strict_types=1);

namespace Mage2Gen\Module\Setup\Patch\Data;

use Mage2Gen\Module\Setup\TestSetup;
use Mage2Gen\Module\Setup\TestSetupFactory;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;

class DefaultTestEntity implements DataPatchInterface
{

    /**
     * @var ModuleDataSetupInterface
     */
    private $moduleDataSetup;
    /**
     * @var TestSetup
     */
    private $testSetupFactory;

    /**
     * Constructor
     *
     * @param ModuleDataSetupInterface $moduleDataSetup
     * @param TestSetupFactory $testSetupFactory
     */
    public function __construct(
        ModuleDataSetupInterface $moduleDataSetup,
        TestSetupFactory $testSetupFactory
    ) {
        $this->moduleDataSetup = $moduleDataSetup;
        $this->testSetupFactory = $testSetupFactory;
    }

    /**
     * {@inheritdoc}
     */
    public function apply()
    {
        $this->moduleDataSetup->getConnection()->startSetup();
        /** @var TestSetup $customerSetup */
        $testSetup = $this->testSetupFactory->create(['setup' => $this->moduleDataSetup]);
        $testSetup->installEntities();
        

        $this->moduleDataSetup->getConnection()->endSetup();
    }

    /**
     * {@inheritdoc}
     */
    public function getAliases()
    {
        return [];
    }

    /**
     * {@inheritdoc}
     */
    public static function getDependencies()
    {
        return [
        
        ];
    }
}