- Magento 2 Developer's Guide
- Branko Ajzele
- 1277字
- 2021-07-30 09:53:24
Creating a miniature module
For the purpose of this chapter, we will create a miniature module called Foggyline_Office
.
The module will have two entities defined as follows:
Department
: a simple model with the following fields:entity_id
: primary keyname
: name of department, string value
Employee
: an EAV model with the following fields and attributes:- Fields:
entity_id
: primary keydepartment_id
: foreign key, pointing toDepartment.entity_id
email
: unique e-mail of an employee, string valuefirst_name
: first name of an employee, string valuelast_name
: last name of an employee, string value
- Attributes:
service_years
: employee's years of service, integer valuedob
: employee's date of birth, date-time valuesalary
– monthly salary, decimal valuevat_number
: VAT number, (short) string valuenote
: possible note on employee, (long) string value
- Fields:
Every module starts with the registration.php
and module.xml
files. For the purpose of our chapter module, let's create the app/code/Foggyline/Office/registration.php
file with content as follows:
<?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'Foggyline_Office', __DIR__ );
The registration.php
file is sort of an entry point to our module.
Now let's create the app/code/Foggyline/Office/etc/module.xml
file with the following content:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/ etc/module.xsd"> <module name="Foggyline_Office" setup_version="1.0.0"> <sequence> <module name="Magento_Eav"/> </sequence> </module> </config>
We will get into more details about the structure of the module.xml
file in later chapters. Right now, we will only focus on the setup_version
attribute and module
element within sequence
.
The value of setup_version
is important because we might use it within our schema install script (InstallSchema.php
) files, effectively turning the install script into an update script, as we will show soon.
The sequence
element is Magento's way of setting dependencies for our module. Given that our module will make use of EAV entities, we list Magento_Eav
as a dependency.
Creating a simple model
The Department
entity, as per requirements, is modeled as a simple model. We previously mentioned that whenever we talk about models, we implicitly think of model
class, resource
class, and collection
class forming one unit.
Let's start by first creating a model
class, (partially) defined under the app/code/Foggyline/Office/Model/Department.php
file as follows:
namespace Foggyline\Office\Model; class Department extends \Magento\Framework\Model\AbstractModel { protected function _construct() { $this-> _init('Foggyline\Office\Model \ResourceModel\Department'); } }
All that is happening here is that we are extending from the \Magento\Framework\Model\AbstractModel
class, and triggering the $this->_init
method within _construct
passing it our resource
class.
The AbstractModel
further extends \Magento\Framework\Object
. The fact that our model
class ultimately extends from Object
means that we do not have to define a property name on our model
class. What Object
does for us is that it enables us to get, set, unset, and check for a value existence on properties magically. To give a more robust example than name
, imagine our entity has a property called employee_average_salary
in the following code:
$department->getData('employee_average_salary'); $department->getEmployeeAverageSalary(); $department->setData('employee_average_salary', 'theValue'); $department->setEmployeeAverageSalary('theValue'); $department->unsetData('employee_average_salary'); $department->unsEmployeeAverageSalary(); $department->hasData('employee_average_salary'); $department->hasEmployeeAverageSalary();
The reason why this works is due to Object
implementing the setData
, unsetData
, getData
, and magic __call
methods. The beauty of the magic __call
method implementation is that it understands method calls like getEmployeeAverageSalary
, setEmployeeAverageSalary
, unsEmployeeAverageSalary
, and hasEmployeeAverageSalary
even if they do not exist on the Model
class. However, if we choose to implement some of these methods within our Model
class, we are free to do so and Magento will pick it up when we call it.
This is an important aspect of Magento, sometimes confusing to newcomers.
Once we have a model
class in place, we create a model resource
class, (partially) defined under the app/code/Foggyline/Office/Model/ResourceModel/Department.php
file as follows:
namespace Foggyline\Office\Model\ResourceModel; class Department extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb { protected function _construct() { $this->_init('foggyline_office_department', 'entity_id'); } }
Our resource class that extends from \Magento\Framework\Model\ResourceModel\Db\AbstractDb
triggers the $this->_init
method call within _construct
. $this->_init
accepts two parameters. The first parameter is the table name foggyline_office_department
, where our model will persist its data. The second parameter is the primary column name entity_id
within that table.
AbstractDb
further extends Magento\Framework\Model\ResourceModel\AbstractResource
.
Note
The resource class is the key to communicating to the database. All it takes is for us to name the table and its primary key and our models can save, delete, and update entities.
Finally, we create our collection
class, (partially) defined under the app/code/Foggyline/Office/Model/ResourceModel/Department/Collection.php
file as follows:
namespace Foggyline\Office\Model\ResourceModel\Department; class Collection extends \Magento\Framework\Model\ResourceModel \Db\Collection\AbstractCollection { protected function _construct() { $this->_init( 'Foggyline\Office\Model\Department', 'Foggyline\Office\Model\ResourceModel\Department' ); } }
The collection
class extends from \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
and, similar to the model
and resource
classes, does a $this->_init
method call within _construct
. This time, _init
accepts two parameters. The first parameter is the full model
class name Foggyline\Office\Model\Department
, and the second parameter is the full resource class name Foggyline\Office\Model\ResourceModel\Department
.
AbstractCollection
implements Magento\Framework\App\ResourceConnection\SourceProviderInterface
, and extends \Magento\Framework\Data\Collection\AbstractDb
. AbstractDb
further extends \Magento\Framework\Data\Collection
.
It is worth taking some time to study the inners of these collection
classes, as this is our go-to place for whenever we need to deal with fetching a list of entities that match certain search criteria.
Creating an EAV model
The Employee
entity, as per requirements, is modeled as an EAV model.
Let's start by first creating an EAV model
class, (partially) defined under the app/code/Foggyline/Office/Model/Employee.php
file as follows:
namespace Foggyline\Office\Model; class Employee extends \Magento\Framework\Model\AbstractModel { const ENTITY = 'foggyline_office_employee'; public function _construct() { $this-> _init('Foggyline\Office \Model \ResourceModel\Employee'); } }
Here, we are extending from the \Magento\Framework\Model\AbstractModel
class, which is the same as with the simple model previously described. The only difference here is that we have an ENTITY
constant defined, but this is merely syntactical sugar for later on; it bears no meaning for the actual model
class.
Next, we create an EAV model resource
class, (partially) defined under the app/code/Foggyline/Office/Model/ResourceModel/Employee.php
file as follows:
namespace Foggyline\Office\Model\ResourceModel; class Employee extends \Magento\Eav\Model\Entity\AbstractEntity { protected function _construct() { $this->_read = 'foggyline_office_employee_read'; $this->_write = 'foggyline_office_employee_write'; } public function getEntityType() { if (empty($this->_type)) { $this->setType(\Foggyline\Office\Model \Employee::ENTITY); } return parent::getEntityType(); } }
Our resource
class extends from \Magento\Eav\Model\Entity\AbstractEntity
, and sets the $this->_read
, $this->_write
class properties through _construct
. These are freely assigned to whatever value we want, preferably following the naming pattern of our module. The read and write connections need to be named or else Magento produces an error when using our entities.
The getEntityType
method internally sets the _type
value to \Foggyline\Office\Model\Employee::ENTITY
, which is the string foggyline_office_employee
. This same value is what's stored in the entity_type_code
column within the eav_entity_type
table. At this point, there is no such entry in the eav_entity_type
table. This is because the install schema script will be creating one, as we will be demonstrating soon.
Finally, we create our collection
class, (partially) defined under the app/code/Foggyline/Office/Model/ResourceModel/Employee/Collection.php
file as follows:
namespace Foggyline\Office\Model\ResourceModel\Employee; class Collection extends \Magento\Eav\Model\Entity\Collection\AbstractCollection { protected function _construct() { $this->_init('Foggyline\Office\Model\Employee', 'Foggyline\Office\Model\ResourceModel\Employee'); } }
The collection
class extends from \Magento\Eav\Model\Entity\Collection\AbstractCollection
and, similar to the model class, does a $this->_init
method call within _construct
. _init
accepts two parameters: the full model class name Foggyline\Office\Model\Employee
, and the full resource class name Foggyline\Office\Model\ResourceModel\Employee
.
AbstractCollection
has the same parent tree as the simple model collection class, but on its own it implements a lot of EAV collection-specific methods like addAttributeToFilter
, addAttributeToSelect
, addAttributeToSort
, and so on.
Note
As we can see, EAV models look a lot like simple models. The difference lies mostly in the resource
class and collection
class implementations and their first level parent classes. However, we need to keep in mind that the example given here is the simplest one possible. If we look at the eav_entity_type
table in the database, we can see that other entity types make use of attribute_model
, entity_attribute_collection
, increment_model
, and so on. These are all advanced properties we can define alongside our EAV model making it closer to the implementation of the catalog_product
entity type, which is probably the most robust one in Magento. This type of advanced EAV usage is out of the scope of this book as it is probably worth a book on its own.
Now that we have simple and EAV models in place, it is time to look into installing the necessary database schema and possibly pre-fill it with some data. This is done through schema and data scripts.
- 零基礎PHP學習筆記
- Spring Cloud、Nginx高并發核心編程
- Java Web開發技術教程
- GeoServer Beginner's Guide(Second Edition)
- C語言實驗指導及習題解析
- PySpark Cookbook
- Learning Probabilistic Graphical Models in R
- Python Interviews
- Android嵌入式系統程序開發:基于Cortex-A8(第2版)
- Spring 5 Design Patterns
- 石墨烯改性塑料
- Python 快速入門(第3版)
- JavaScript Mobile Application Development
- C# 7 and .NET Core 2.0 Blueprints
- Expert Cube Development with SSAS Multidimensional Models