Best practice: via the service contract
The best practice is always to use the service contract whenever it's possible. You can find the list of reasons here: Magento 2: what are the benefits of using service contracts?
For details on how to implement a service contract I suggest you check this topic: How to implement service contract for a custom module in Magento 2?
If no service contract available
If there is no service contract available, you should use the model repository get
method. Using this method, you benefit from the magento caching system for example for the CategoryRepository
class:
public function get($categoryId, $storeId = null)
{
$cacheKey = null !== $storeId ? $storeId : 'all';
if (!isset($this->instances[$categoryId][$cacheKey])) {
/** @var Category $category */
$category = $this->categoryFactory->create();
if (null !== $storeId) {
$category->setStoreId($storeId);
}
$category->load($categoryId);
if (!$category->getId()) {
throw NoSuchEntityException::singleField('id', $categoryId);
}
$this->instances[$categoryId][$cacheKey] = $category;
}
return $this->instances[$categoryId][$cacheKey];
}
Deprecated load()
method
Magento 2 is slowly moving away from the standard CRUD system by dropping the inheritance system and implementing it via composition using the new 2.1 EntityManager you can find details here: Magento 2.1: using the entity manager
Also I suggest you read this interesting topic about the deprecated CRUD methods: Deprecated save and load methods in Abstract Model
Why not using the resource model load
The main reason is that if you use the resource model load
method, you will skip some important part of the loading system that are implemented in the model load
method, see Magento\Framework\Model\AbstractModel
:
public function load($modelId, $field = null)
{
$this->_beforeLoad($modelId, $field);
$this->_getResource()->load($this, $modelId, $field);
$this->_afterLoad();
$this->setOrigData();
$this->_hasDataChanges = false;
$this->updateStoredData();
return $this;
}
Calling the resource model load
method directly will have the following impact:
_beforeLoad
is not called: thus the model load before events are not dispatched
_afterLoad
is not called: thus the model load after events are not dispatched
- the stored data are not updated which can cause various problems (for instance if you call
prepareDataForUpdate
from Magento\Framework\Model\ResourceModel\Db\AbstractDb
)
Best Answer
My explaination:
It is very difficult to understand the difference between a model and a data model. If I have to say in few words I could say that a model represents the engine and a data model represents its information.
In your example, with the customer entity, you can see for example how the method
authenticate
orvalidatePassword
are kept in customer model since they are part of the engine and they are not going to directly handle information. On the other side, methods likegetExtensionAttributes
, since handling pieces of information are kept in the data model.I think this is just a better project handling, just like the division between models and resource models, you could ask why you need them as well.
Why you need them:
If you want to expose customer information (for example) using API, you will need an interface (
\Magento\Customer\Api\Data\CustomerInterface
) with getters defining all the attributes of your entity, and if you have any other getter method not representing an information you want to expose (e.g.:getRandomConfirmationKey
), you have a problem!Thi is why, in my example,
getRandomConfirmationKey
is part of the model (\Magento\Customer\Model\Customer
), whilegetFirstname
is part of the data model.A quick rule could be:
POST:
In few words: consider a data model almost as a DTO.