├── Api ├── Data │ ├── StudentInterface.php │ └── TeacherInterface.php ├── StudentRepositoryInterface.php └── TeacherRepositoryInterface.php ├── LICENSE ├── Model ├── ResourceModel │ ├── Student.php │ ├── Student │ │ ├── Collection.php │ │ └── Relation │ │ │ ├── ReadHandler.php │ │ │ └── SaveHandler.php │ ├── Teacher.php │ └── Teacher │ │ ├── Collection.php │ │ └── Relation │ │ ├── ReadHandler.php │ │ └── SaveHandler.php ├── Student.php ├── StudentRepository.php ├── Teacher.php └── TeacherRepository.php ├── README.md ├── Setup └── InstallSchema.php ├── composer.json ├── etc ├── di.xml └── module.xml └── registration.php /Api/Data/StudentInterface.php: -------------------------------------------------------------------------------- 1 | metadataPool = $metadataPool; 55 | $this->entityManager = $entityManager; 56 | parent::__construct($context, $connectionName); 57 | } 58 | 59 | /** 60 | * {@inheritdoc} 61 | */ 62 | protected function _construct() 63 | { 64 | $this->_init('blackbird_ts_student', StudentInterface::ID); 65 | } 66 | 67 | /** 68 | * Get all Teacher IDs for a student 69 | * 70 | * @param int $studentId 71 | * @return array 72 | */ 73 | public function lookupTeacherIds($studentId) 74 | { 75 | $connection = $this->getConnection(); 76 | 77 | $entityMetadata = $this->metadataPool->getMetadata(StudentInterface::class); 78 | $linkField = $entityMetadata->getLinkField(); 79 | 80 | $select = $connection->select() 81 | ->from(['ts' => $this->getTable('blackbird_ts_teacher_students')], 'id_teacher') 82 | ->join( 83 | ['stud' => $this->getMainTable()], 84 | 'stud.' . $linkField . ' = ts.' . $linkField, 85 | [] 86 | ) 87 | ->where('ts.' . $entityMetadata->getIdentifierField() . ' = :id_student'); 88 | 89 | return $connection->fetchCol($select, ['id_student' => (int)$studentId]); 90 | } 91 | 92 | /** 93 | * {@inheritDoc} 94 | */ 95 | public function save(AbstractModel $object) 96 | { 97 | $this->entityManager->save($object); 98 | return $this; 99 | } 100 | 101 | /** 102 | * {@inheritDoc} 103 | */ 104 | public function load(\Magento\Framework\Model\AbstractModel $object, $value, $field = null) 105 | { 106 | return $this->entityManager->load($object, $value); 107 | } 108 | 109 | /** 110 | * {@inheritDoc} 111 | */ 112 | public function delete(\Magento\Framework\Model\AbstractModel $object) 113 | { 114 | $this->entityManager->delete($object); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /Model/ResourceModel/Student/Collection.php: -------------------------------------------------------------------------------- 1 | _init(Model\Student::class, Model\ResourceModel\Student::class); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Model/ResourceModel/Student/Relation/ReadHandler.php: -------------------------------------------------------------------------------- 1 | metadataPool = $metadataPool; 49 | $this->resourceStudent = $resourceStudent; 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | public function execute($entity, $arguments = []) 56 | { 57 | if ($entity->getIdStudent()) { 58 | $studentTeacherId = $this->resourceStudent->lookupTeacherIds((int)$entity->getIdStudent()); 59 | $entity->setData('id_teacher', $studentTeacherId); 60 | } 61 | return $entity; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Model/ResourceModel/Student/Relation/SaveHandler.php: -------------------------------------------------------------------------------- 1 | metadataPool = $metadataPool; 49 | $this->resourceStudent = $resourceStudent; 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | public function execute($entity, $arguments = []) 56 | { 57 | $entityMetadata = $this->metadataPool->getMetadata(StudentInterface::class); 58 | $linkField = $entityMetadata->getLinkField(); 59 | 60 | $connection = $entityMetadata->getEntityConnection(); 61 | 62 | $oldTeachers = $this->resourceStudent->lookupTeacherIds((int)$entity->getIdStudent()); 63 | $newTeacher = (array)$entity->getTeacherIds(); 64 | 65 | $table = $this->resourceStudent->getTable('blackbird_ts_teacher_students'); 66 | 67 | $delete = array_diff($oldTeachers, $newTeacher); 68 | if ($delete) { 69 | $where = [ 70 | $linkField . ' = ?' => $entity->getIdStudent(), 71 | 'id_teacher IN (?)' => $delete, 72 | ]; 73 | $connection->delete($table, $where); 74 | } 75 | 76 | $insert = array_diff($newTeacher, $oldTeachers); 77 | if ($insert) { 78 | $data = []; 79 | foreach ($insert as $teacherId) { 80 | $data[] = [ 81 | $linkField => $entity->getIdStudent(), 82 | 'id_teacher' => (int)$teacherId 83 | ]; 84 | } 85 | $connection->insertMultiple($table, $data); 86 | } 87 | 88 | return $entity; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Model/ResourceModel/Teacher.php: -------------------------------------------------------------------------------- 1 | metadataPool = $metadataPool; 55 | $this->entityManager = $entityManager; 56 | parent::__construct($context, $connectionName); 57 | } 58 | 59 | /** 60 | * {@inheritdoc} 61 | */ 62 | protected function _construct() 63 | { 64 | $this->_init('blackbird_ts_teacher', TeacherInterface::ID); 65 | } 66 | 67 | /** 68 | * Get all Student IDs for a teacher 69 | * 70 | * @param int $teacherId 71 | * @return array 72 | */ 73 | public function lookupStudentIds($teacherId) 74 | { 75 | $connection = $this->getConnection(); 76 | 77 | $entityMetadata = $this->metadataPool->getMetadata(TeacherInterface::class); 78 | $linkField = $entityMetadata->getLinkField(); 79 | 80 | $select = $connection->select() 81 | ->from(['ts' => $this->getTable('blackbird_ts_teacher_students')], 'id_student') 82 | ->join( 83 | ['stud' => $this->getMainTable()], 84 | 'stud.' . $linkField . ' = ts.' . $linkField, 85 | [] 86 | ) 87 | ->where('ts.' . $entityMetadata->getIdentifierField() . ' = :id_teacher'); 88 | 89 | return $connection->fetchCol($select, ['id_teacher' => (int)$teacherId]); 90 | } 91 | 92 | /** 93 | * {@inheritDoc} 94 | */ 95 | public function save(AbstractModel $object) 96 | { 97 | $this->entityManager->save($object); 98 | return $this; 99 | } 100 | 101 | /** 102 | * {@inheritDoc} 103 | */ 104 | public function load(\Magento\Framework\Model\AbstractModel $object, $value, $field = null) 105 | { 106 | return $this->entityManager->load($object, $value); 107 | } 108 | 109 | /** 110 | * {@inheritDoc} 111 | */ 112 | public function delete(\Magento\Framework\Model\AbstractModel $object) 113 | { 114 | $this->entityManager->delete($object); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /Model/ResourceModel/Teacher/Collection.php: -------------------------------------------------------------------------------- 1 | _init(Model\Teacher::class, Model\ResourceModel\Teacher::class); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Model/ResourceModel/Teacher/Relation/ReadHandler.php: -------------------------------------------------------------------------------- 1 | metadataPool = $metadataPool; 48 | $this->resourceTeacher = $resourceTeacher; 49 | } 50 | 51 | /** 52 | * {@inheritdoc} 53 | */ 54 | public function execute($entity, $arguments = []) 55 | { 56 | if ($entity->getIdTeacher()) { 57 | $teacherStudentId = $this->resourceTeacher->lookupStudentIds((int)$entity->getIdTeacher()); 58 | $entity->setData('id_student', $teacherStudentId); 59 | } 60 | return $entity; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Model/ResourceModel/Teacher/Relation/SaveHandler.php: -------------------------------------------------------------------------------- 1 | metadataPool = $metadataPool; 49 | $this->resourceTeacher = $resourceTeacher; 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | public function execute($entity, $arguments = []) 56 | { 57 | $entityMetadata = $this->metadataPool->getMetadata(TeacherInterface::class); 58 | $linkField = $entityMetadata->getLinkField(); 59 | 60 | $connection = $entityMetadata->getEntityConnection(); 61 | 62 | $oldStudents = $this->resourceTeacher->lookupStudentIds((int)$entity->getTeacherId()); 63 | $newStudents = (array)$entity->getStudentIds(); 64 | 65 | $table = $this->resourceTeacher->getTable('blackbird_ts_teacher_students'); 66 | 67 | $delete = array_diff($oldStudents, $newStudents); 68 | if ($delete) { 69 | $where = [ 70 | $linkField . ' = ?' => $entity->getIdTeacher(), 71 | 'id_student IN (?)' => $delete, 72 | ]; 73 | $connection->delete($table, $where); 74 | } 75 | 76 | $insert = array_diff($newStudents, $oldStudents); 77 | if ($insert) { 78 | $data = []; 79 | foreach ($insert as $studentId) { 80 | $data[] = [ 81 | $linkField => $entity->getIdTeacher(), 82 | 'id_student' => (int)$studentId 83 | ]; 84 | } 85 | $connection->insertMultiple($table, $data); 86 | } 87 | 88 | return $entity; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Model/Student.php: -------------------------------------------------------------------------------- 1 | _init(\Blackbird\DataModelSample\Model\ResourceModel\Student::class); 34 | } 35 | 36 | /** 37 | * {@inheritdoc} 38 | */ 39 | public function getId() 40 | { 41 | return $this->_getData(self::ID); 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | public function getName() 48 | { 49 | return $this->_getData(self::NAME); 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | public function getAge() 56 | { 57 | return $this->_getData(self::AGE); 58 | } 59 | 60 | /** 61 | * {@inheritdoc} 62 | */ 63 | public function setId($id) 64 | { 65 | return $this->setData(self::ID, $id); 66 | } 67 | 68 | /** 69 | * {@inheritdoc} 70 | */ 71 | public function setName($name) 72 | { 73 | return $this->setData(self::NAME, $name); 74 | } 75 | 76 | /** 77 | * {@inheritdoc} 78 | */ 79 | public function setAge($age) 80 | { 81 | return $this->setData(self::AGE, $age); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Model/StudentRepository.php: -------------------------------------------------------------------------------- 1 | resourceStudent = $resourceStudent; 50 | $this->studentFactory = $studentFactory; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | */ 56 | public function save(Data\StudentInterface $student) 57 | { 58 | try { 59 | $this->resourceStudent->save($student); 60 | } catch (\Exception $e) { 61 | throw new CouldNotSaveException(__($e->getMessage())); 62 | } 63 | 64 | return $student; 65 | } 66 | 67 | /** 68 | * {@inheritdoc} 69 | */ 70 | public function getById($studentId) 71 | { 72 | $student = $this->studentFactory->create(); 73 | $this->resourceStudent->load($student, $studentId); 74 | if (!$student->getId()) { 75 | throw new NoSuchEntityException(__('Student with id "%1" does not exist', $studentId)); 76 | } 77 | return $student; 78 | } 79 | 80 | /** 81 | * {@inheritdoc} 82 | */ 83 | public function delete(Data\StudentInterface $student) 84 | { 85 | try { 86 | $this->resourceStudent->delete($student); 87 | } catch (\Exception $e) { 88 | throw new CouldNotSaveException(__($e->getMessage())); 89 | } 90 | 91 | return $student; 92 | } 93 | 94 | /** 95 | * {@inheritdoc} 96 | */ 97 | public function deleteById($studentId) 98 | { 99 | return $this->delete($this->getById($studentId)); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /Model/Teacher.php: -------------------------------------------------------------------------------- 1 | _init(\Blackbird\DataModelSample\Model\ResourceModel\Teacher::class); 34 | } 35 | 36 | /** 37 | * {@inheritdoc} 38 | */ 39 | public function getId() 40 | { 41 | return $this->_getData(self::ID); 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | public function getName() 48 | { 49 | return $this->_getData(self::NAME); 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | public function getAge() 56 | { 57 | return $this->_getData(self::AGE); 58 | } 59 | 60 | /** 61 | * {@inheritdoc} 62 | */ 63 | public function getClasses() 64 | { 65 | return $this->_getData(self::CLASSES); 66 | } 67 | 68 | /** 69 | * {@inheritdoc} 70 | */ 71 | public function setId($id) 72 | { 73 | return $this->setData(self::ID, $id); 74 | } 75 | 76 | /** 77 | * {@inheritdoc} 78 | */ 79 | public function setName($name) 80 | { 81 | return $this->setData(self::NAME, $name); 82 | } 83 | 84 | /** 85 | * {@inheritdoc} 86 | */ 87 | public function setAge($age) 88 | { 89 | return $this->setData(self::AGE, $age); 90 | } 91 | 92 | /** 93 | * {@inheritdoc} 94 | */ 95 | public function setClasses($classes) 96 | { 97 | return $this->setData(self::CLASSES, $classes); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /Model/TeacherRepository.php: -------------------------------------------------------------------------------- 1 | resourceTeacher = $resourceTeacher; 49 | $this->teacherFactory = $teacherFactory; 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | public function save(Data\TeacherInterface $teacher) 56 | { 57 | try { 58 | $this->resourceTeacher->save($teacher); 59 | } catch (\Exception $e) { 60 | throw new CouldNotSaveException(__($e->getMessage())); 61 | } 62 | 63 | return $teacher; 64 | } 65 | 66 | /** 67 | * {@inheritdoc} 68 | */ 69 | public function getById($teacherId) 70 | { 71 | $teacher = $this->teacherFactory->create(); 72 | $this->resourceTeacher->load($teacher, $teacherId); 73 | if (!$teacher->getId()) { 74 | throw new NoSuchEntityException(__('Teacher with id "%1" does not exist', $teacherId)); 75 | } 76 | return $teacher; 77 | } 78 | 79 | /** 80 | * {@inheritdoc} 81 | */ 82 | public function delete(Data\TeacherInterface $teacher) 83 | { 84 | try { 85 | $this->resourceTeacher->delete($teacher); 86 | } catch (\Exception $e) { 87 | throw new CouldNotSaveException(__($e->getMessage())); 88 | } 89 | 90 | return $teacher; 91 | } 92 | 93 | /** 94 | * {@inheritdoc} 95 | */ 96 | public function deleteById($teacherId) 97 | { 98 | return $this->delete($this->getById($teacherId)); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Magento 2 : How to create a Data Model 2 | 3 | [![Latest Stable Version](https://img.shields.io/packagist/v/blackbird/module-data-model-sample.svg?style=flat-square)](https://packagist.org/packages/blackbird/module-data-model-sample) 4 | [![License: MIT](https://img.shields.io/github/license/blackbird-agency/magento-2-data-model-sample.svg?style=flat-square)](./LICENSE) 5 | 6 | **Read our articles about the data model persistence:** 7 | 8 | - [Part 1 - Data Model](https://black.bird.eu/en/blog/recettem2.html) 9 | - [Part 2 - Resource Model](https://black.bird.eu/en/blog/recettem2-2.html) 10 | - [Part 3 - Entity Manager](https://black.bird.eu/en/blog/recettem2-3.html) 11 | 12 | ***Special gift from the Blackbird Dev "Kevin Weyhaupt"*** :neckbeard: 13 | 14 | ## Setup 15 | 16 | ### Get the package 17 | 18 | **Zip Package:** 19 | 20 | Unzip the package in app/code/Blackbird/DataModelSample 21 | 22 | **Composer Package:** 23 | 24 | ``` 25 | composer require blackbird/module-data-model-sample 26 | ``` 27 | 28 | ### Install the module 29 | 30 | Then, run the following magento command: 31 | 32 | ``` 33 | php bin/magento setup:upgrade 34 | ``` 35 | 36 | **If you are in production mode, do not forget to recompile and redeploy the static resources.** 37 | 38 | ## Support 39 | 40 | Raise a new [request](https://github.com/blackbird-agency/magento-2-data-model-sample/issues). 41 | 42 | ## Authors 43 | 44 | - **Blackbird Team** - *Contributor* - [They're awesome!](https://github.com/blackbird-agency) 45 | 46 | ## Contact 47 | 48 | For further information, contact us: 49 | 50 | - by email: hello@bird.eu 51 | - or by form: [https://black.bird.eu/en/contacts/](https://black.bird.eu/contacts/) 52 | 53 | ## Licence 54 | 55 | This project is licensed under the Blackbird Policy License - see the [LICENSE](./LICENSE) link for details. 56 | 57 | ***That's all folks!*** 58 | -------------------------------------------------------------------------------- /Setup/InstallSchema.php: -------------------------------------------------------------------------------- 1 | startSetup(); 39 | 40 | /** 41 | * Create table 'blackbird_ts_student' 42 | */ 43 | if (!$installer->tableExists('blackbird_ts_student')) { 44 | $table = $installer->getConnection() 45 | ->newTable($installer->getTable('blackbird_ts_student')) 46 | ->addColumn( 47 | 'id_student', 48 | Table::TYPE_INTEGER, 49 | 11, 50 | [ 51 | 'nullable' => false, 52 | 'precision' => '10', 53 | 'auto_increment' => true, 54 | 'primary' => true, 55 | ], 56 | 'Student Id' 57 | ) 58 | ->addColumn( 59 | 'name', 60 | Table::TYPE_TEXT, 61 | 255, 62 | [ 63 | 'nullable' => false, 64 | ], 65 | 'Student Name' 66 | ) 67 | ->addColumn( 68 | 'age', 69 | Table::TYPE_INTEGER, 70 | 10, 71 | [ 72 | 'nullable' => true, 73 | ], 74 | 'Age' 75 | ) 76 | ->setComment('Students Table'); 77 | $installer->getConnection()->createTable($table); 78 | } 79 | 80 | /** 81 | * Create table 'blackbird_ts_student' 82 | */ 83 | if (!$installer->tableExists('blackbird_ts_teacher')) { 84 | $table = $installer->getConnection() 85 | ->newTable($installer->getTable('blackbird_ts_teacher')) 86 | ->addColumn( 87 | 'id_teacher', 88 | Table::TYPE_INTEGER, 89 | 11, 90 | [ 91 | 'nullable' => false, 92 | 'precision' => '10', 93 | 'auto_increment' => true, 94 | 'primary' => true, 95 | ], 96 | 'Teacher Id' 97 | ) 98 | ->addColumn( 99 | 'name', 100 | Table::TYPE_TEXT, 101 | 255, 102 | [ 103 | 'nullable' => false, 104 | ], 105 | 'Teacher Name' 106 | ) 107 | ->addColumn( 108 | 'age', 109 | Table::TYPE_INTEGER, 110 | 10, 111 | [ 112 | 'nullable' => true, 113 | ], 114 | 'Age' 115 | ) 116 | ->addColumn( 117 | 'classes', 118 | Table::TYPE_TEXT, 119 | 255, 120 | [ 121 | 'nullable' => false, 122 | ], 123 | 'Teacher Classes' 124 | ) 125 | ->setComment('Teachers Table'); 126 | $installer->getConnection()->createTable($table); 127 | } 128 | 129 | /** 130 | * Create table 'blackbird_ets_preparation_time_rule_holidays_group' 131 | */ 132 | if (!$installer->tableExists('blackbird_ts_teacher_students')) { 133 | $table = $installer->getConnection() 134 | ->newTable($installer->getTable('blackbird_ts_teacher_students')) 135 | ->addColumn( 136 | 'id_student', 137 | Table::TYPE_INTEGER, 138 | 11, 139 | [ 140 | 'nullable' => false, 141 | 'precision' => '10', 142 | 'primary' => true, 143 | ], 144 | 'Student Id' 145 | ) 146 | ->addColumn( 147 | 'id_teacher', 148 | Table::TYPE_INTEGER, 149 | 11, 150 | [ 151 | 'nullable' => false, 152 | 'precision' => '10', 153 | 'primary' => true, 154 | ], 155 | 'Teacher Id' 156 | ) 157 | ->addForeignKey( 158 | $installer->getFkName( 159 | 'blackbird_ts_teacher_students', 160 | 'id_student', 161 | 'blackbird_ts_student', 162 | 'id_student' 163 | ), 164 | 'id_student', 165 | $installer->getTable('blackbird_ts_student'), 166 | 'id_student', 167 | Table::ACTION_CASCADE 168 | ) 169 | ->addForeignKey( 170 | $installer->getFkName( 171 | 'blackbird_ts_teacher_students', 172 | 'id_teacher', 173 | 'blackbird_ts_teacher', 174 | 'id_teacher' 175 | ), 176 | 'id_teacher', 177 | $installer->getTable('blackbird_ts_teacher'), 178 | 'id_teacher', 179 | Table::ACTION_CASCADE 180 | ) 181 | ->setComment('Teacher Students'); 182 | $installer->getConnection()->createTable($table); 183 | } 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blackbird/module-data-model-sample", 3 | "description": "Sample module of a data model persistence implementation.", 4 | "keywords": [ 5 | "php", 6 | "magento", 7 | "magento2", 8 | "sample", 9 | "data model", 10 | "persistence" 11 | ], 12 | "require": { 13 | "magento/framework": "101.*.*" 14 | }, 15 | "type": "magento2-module", 16 | "version": "0.2.0", 17 | "license": [ 18 | "MIT" 19 | ], 20 | "homepage": "https://github.com/blackbird-agency/magento-2-data-model-sample", 21 | "authors": [ 22 | { 23 | "name": "Blackbird Team", 24 | "email": "hello@bird.eu", 25 | "homepage": "https://black.bird.eu/", 26 | "role": "lead" 27 | } 28 | ], 29 | "support": { 30 | "source": "https://github.com/blackbird-agency/magento-2-data-model-sample", 31 | "issues": "https://github.com/blackbird-agency/magento-2-data-model-sample/issues" 32 | }, 33 | "autoload": { 34 | "files": [ 35 | "registration.php" 36 | ], 37 | "psr-4": { 38 | "Blackbird\\DataModelSample\\": "" 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /etc/di.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | Blackbird\DataModelSample\Api\StudentRepositoryInterface 30 | Blackbird\DataModelSample\Api\TeacherRepositoryInterface 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | blackbird_ts_student 40 | id_student 41 | 42 | 43 | blackbird_ts_teacher 44 | id_teacher 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | Blackbird\DataModelSample\Model\ResourceModel\Student\Relation\ReadHandler 56 | 57 | 58 | Blackbird\DataModelSample\Model\ResourceModel\Student\Relation\SaveHandler 59 | 60 | 61 | Blackbird\DataModelSample\Model\ResourceModel\Student\Relation\SaveHandler 62 | 63 | 64 | 65 | 66 | Blackbird\DataModelSample\Model\ResourceModel\Teacher\Relation\ReadHandler 67 | 68 | 69 | Blackbird\DataModelSample\Model\ResourceModel\Teacher\Relation\SaveHandler 70 | 71 | 72 | Blackbird\DataModelSample\Model\ResourceModel\Teacher\Relation\SaveHandler 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | Magento\Framework\EntityManager\AbstractModelHydrator 83 | Magento\Framework\EntityManager\AbstractModelHydrator 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /etc/module.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /registration.php: -------------------------------------------------------------------------------- 1 |