Best Way to Load a Custom Model in Magento 2
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
fromMagento\Framework\Model\ResourceModel\Db\AbstractDb
)