{"id":3559,"date":"2024-03-02T10:06:07","date_gmt":"2024-03-02T16:06:07","guid":{"rendered":"https:\/\/promincproductions.com\/blog\/?p=3559"},"modified":"2024-03-02T10:06:09","modified_gmt":"2024-03-02T16:06:09","slug":"magento-2-load-product-attribute-data","status":"publish","type":"post","link":"https:\/\/promincproductions.com\/blog\/magento-2-load-product-attribute-data\/","title":{"rendered":"Magento 2 Load Product Attribute Data"},"content":{"rendered":"<p>Depending how a product was loaded in Magento 2, not all of the product attributes are available on the object.  This can be quite frustrating and lead to a development road block &#8211; the value of the attribute is required but it&#8217;s not there.  This can occur for various reasons, the most common being that the product was loaded from an object like <code>quite_address_item<\/code> which is a more simplified product object.  If the product attribute comes from a custom module \/ feature, there is a chance the attribute will not be on this product object.<\/p>\n\n\n\n<p>There are ways to overcome this &#8211; some more efficient than others.  It seems the biggest go-to for developers is to just load the entire product object from the catalog.  This is handy as it does have all of the data that may be needed.  However, this is a costly practice &#8211; as is outlined below &#8211; as it takes more time to load.  In ecommerce a fast page load time is critical for customer experience, customer confidence, and SEO among other reasons.  Read on to identify the best solution for each scenario.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" width=\"600\" height=\"600\" src=\"https:\/\/promincproductions.com\/blog\/wp-content\/uploads\/2024\/03\/magento-2-load-product-attribute.png\" alt=\"Magento 2 How to load a product attribute efficiently\" class=\"wp-image-3567\" srcset=\"https:\/\/promincproductions.com\/blog\/wp-content\/uploads\/2024\/03\/magento-2-load-product-attribute.png 600w, https:\/\/promincproductions.com\/blog\/wp-content\/uploads\/2024\/03\/magento-2-load-product-attribute-500x500.png 500w, https:\/\/promincproductions.com\/blog\/wp-content\/uploads\/2024\/03\/magento-2-load-product-attribute-150x150.png 150w, https:\/\/promincproductions.com\/blog\/wp-content\/uploads\/2024\/03\/magento-2-load-product-attribute-450x450.png 450w\" sizes=\"(max-width: 600px) 100vw, 600px\" \/><\/figure>\n<\/div>\n\n\n<p>NOTES: <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The examples below track the performance of each method by measuring how many microseconds it took to complete the operation.<\/li>\n\n\n\n<li>The examples do use the <code>objectManager<\/code> for ease of testing and to make them more universial for others to apply this for their own testing.  It is a Magento 2 best practice to avoid using <code>objectManager<\/code> in code and thus any neccessary objects should be properly loaded via the dependency injection <code>__construct<\/code> method.<\/li>\n\n\n\n<li>The loading of the <code>objectManager<\/code> is excluded the processing time calculations.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Magento 2 Methods for Fetching Product Attribute Data<\/h2>\n\n\n\n<p>There are several methods to fetch a products attribute data.  Keep in mind this is only needed in those off-situations where the product attribute needed isn&#8217;t already part of the product object.  Read on to learn about the best methods for various situations and the potential cost (time to process) that each solution may incur.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"load-via-model\">Load Product via Model<\/h3>\n\n\n\n<p>A product can be loaded by its <code>product_id<\/code> using the Catalog Product model.  This should load <em>all<\/em> the product attributes to the product object.  The desired product attribute can be fetched from that object.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$objectManager = \\Magento\\Framework\\App\\ObjectManager::getInstance();\n\n$start_time = microtime(true);  \/\/ DEBUG\n\n$productFromOM = $objectManager-&gt;get('Magento\\Catalog\\Model\\Product')-&gt;load($product-&gt;getId());\n$billingFrequency = $productFromOM-&gt;getBillingFrequency();\n\n$end_time = microtime(true);  \/\/ DEBUG\nerror_log( \"execution_time Product Model: \" . ($end_time - $start_time) . PHP_EOL, 3, \"\/path\/to\/debug.log\" );<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"load-via-repository\">Load Product via Product Repository<\/h3>\n\n\n\n<p>Using the Magento Catalog Product Repository a product can be loaded at a specific store ID.  In a multi-store implementation of Magento 2 this would be required to ensure that the store-specific value of the product attribute is used.  Depending on the scope set on the product attribute desired however, this might not matter.  If the product attribute&#8217;s scope is <code>Global<\/code> it doesn&#8217;t matter what store ID you pull &#8211; it&#8217;s the same value for all store ID&#8217;s.  That said it could be confusing for future development if a developer is expecting all of the store-specific data to be available and it isn&#8217;t&#8230;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$objectManager = \\Magento\\Framework\\App\\ObjectManager::getInstance();\n\n$start_time = microtime(true);  \/\/ DEBUG\n\n$productFromOM2 = $objectManager-&gt;get('\\Magento\\Catalog\\Model\\ProductRepository')-&gt;getById($product-&gt;getId(),false,$product-&gt;getStoreId());\n$billingFrequency = $productFromOM2-&gt;getBillingFrequency();\n\n$end_time = microtime(true);  \/\/ DEBUG\nerror_log( \"execution_time Product Repository: \" . ($end_time - $start_time) . PHP_EOL, 3, \"\/path\/to\/debug.log\" );<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"load-via-attribute\">Load Product Attribute Value Directly<\/h3>\n\n\n\n<p>A product attribute can be loaded directly with the <code>getAttributeRawValue<\/code> method which does not load the full product.  Loading less data results in a quicker processing time.  If only a few product attributes values are needed, this is a very efficient way to approach the problem.  This method loads the attribute data for a specific store ID which makes this a suitable solution for a multi-store Magento 2 installation.<\/p>\n\n\n\n<p>This method does require a resource (database) connection object.  The resource connection object from the product object can be used &#8211; requiring less code to be loaded and processed.  If only a product ID is available and there is no resource connection, then it would need to be loaded manually.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$start_time = microtime(true);  \/\/ DEBUG\n\n$billingFrequency = $product-&gt;getResource()-&gt;getAttributeRawValue($product-&gt;getId(),'billing_frequency',$product-&gt;getStoreId());\n\n$end_time = microtime(true);  \/\/ DEBUG\nerror_log( \"execution_time Attribute: \" . ($end_time - $start_time) . PHP_EOL, 3, \"\/path\/to\/debug.log\" );<\/code><\/pre>\n\n\n\n<p>If a product object isn&#8217;t available and thus the resource connection isn&#8217;t already loaded, then that needs to be loaded first.  Here is an example of that using product and store IDs.<\/p>\n\n\n\n<pre id=\"load-via-attribute-resource\" class=\"wp-block-code\"><code>$objectManager = \\Magento\\Framework\\App\\ObjectManager::getInstance();\n\n$productId = 12345;\n$storeId = 2;\n\n$start_time = microtime(true);  \/\/ DEBUG\n\n\n$resourceConnection = $objectManager-&gt;get('Magento\\Catalog\\Model\\ResourceModel\\Product\\Interceptor');\n$billingFrequency = $resourceConnection-&gt;getAttributeRawValue($productId,'billing_frequency',$storeId);\n\n$end_time = microtime(true);  \/\/ DEBUG\nerror_log( \"execution_time Product Model: \" . ($end_time - $start_time) . PHP_EOL, 3, \"\/path\/to\/debug.log\" );<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Time Trial Comparison of Methods<\/h2>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table><thead><tr><th><\/th><th><code><a href=\"#load-via-model\">Magento\\Catalog\\Model\\Product<\/a><\/code><\/th><th><code><a href=\"#load-via-repository\">\\Magento\\Catalog\\Model\\ProductRepository<\/a><\/code><\/th><th><code><a href=\"#load-via-attribute\">getAttributeRawValue<\/a><\/code><\/th><th><a href=\"#load-via-attribute-resource\"><code>getAttributeRawValue<\/code> with Loading Resource<\/a><\/th><\/tr><\/thead><tbody><tr><td><strong>Trial 1<\/strong><\/td><td>0.029865980148315<\/td><td>0.054730892181396<\/td><td>0.00081586837768555<\/td><td>0.0010240077972412<\/td><\/tr><tr><td><strong>Trial 2<\/strong><\/td><td>0.022938013076782<\/td><td>0.02375602722168<\/td><td>0.0010089874267578<\/td><td>0.0011839866638184<\/td><\/tr><tr><td><strong>Trial 1<\/strong><\/td><td>0.022112846374512<\/td><td>0.022986888885498<\/td><td>0.00074100494384766<\/td><td>0.00078296661376953<\/td><\/tr><tr><td><strong>Trial 4<\/strong><\/td><td>0.022199869155884<\/td><td>0.022958993911743<\/td><td>0.00098681449890137<\/td><td>0.0011329650878906<\/td><\/tr><\/tbody><tfoot><tr><td><strong>Average<\/strong><\/td><td>0.024279177188873<\/td><td>0.031108200550079<\/td><td>0.000888168811798<\/td><td>0.0010309815406799<\/td><\/tr><\/tfoot><\/table><figcaption class=\"wp-element-caption\">Time comparison of multiple methods to fetch product attribute data<\/figcaption><\/figure>\n\n\n\n<p>The time to process each method all turn out to be fractions of a second.  While this might not feel like it&#8217;ll have much impact either way, keep in mind how this compounds on top of it self with all of the queries that Magento has to run to build one page.  And these tests were done on a development server with no load\/traffic.  On a server with high traffic under load this will compound and impact the customer experience.  Shaving fractions of seconds at every step of code does matter!<\/p>\n\n\n\n<p>This table shows how much slower the other methods compared to the <code><a href=\"#load-via-attribute\">getAttributeRawValue<\/a><\/code> method.<\/p>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table><thead><tr><th><\/th><th><code><a href=\"#load-via-attribute\">getAttributeRawValue<\/a><\/code><\/th><th><a href=\"#load-via-attribute-resource\"><code>getAttributeRawValue<\/code> with Loading Resource<\/a><\/th><th><code><a href=\"#load-via-model\">Magento\\Catalog\\Model\\Product<\/a><\/code><\/th><th><code><a href=\"#load-via-repository\">\\Magento\\Catalog\\Model\\ProductRepository<\/a><\/code><\/th><\/tr><\/thead><tbody><tr><td><code><a href=\"#load-via-attribute\">getAttributeRawValue<\/a><\/code><\/td><td><code>--<\/code><\/td><td>-13.85%<\/td><td>-96.34%<\/td><td>-97.14%<\/td><\/tr><tr><td><a href=\"#load-via-attribute-resource\"><code>getAttributeRawValue<\/code> with Loading Resource<\/a><\/td><td>16.08%<\/td><td><code>--<\/code><\/td><td>-95.75%<\/td><td>-96.69%<\/td><\/tr><tr><td><code><a href=\"#load-via-model\">Magento\\Catalog\\Model\\Product<\/a><\/code><\/td><td>2,633.62%<\/td><td>2,254.96%<\/td><td><code>--<\/code><\/td><td>28%<\/td><\/tr><tr><td><code><a href=\"#load-via-repository\">\\Magento\\Catalog\\Model\\ProductRepository<\/a><\/code><\/td><td>3,402.51%<\/td><td>2,917.34%<\/td><td>28.13%<\/td><td><code>--<\/code><\/td><\/tr><\/tbody><\/table><figcaption class=\"wp-element-caption\">Percentage slower of various methods compared to the <code>getAttributeRawValue<\/code> method<\/figcaption><\/figure>\n\n\n\n<p>Math Equation: <code>100 * ( ( final - <code>initial<\/code> ) \/ <code>initial<\/code> )<\/code><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p>To summarize, typically the <code><a href=\"#load-via-attribute\">getAttributeRawValue<\/a><\/code> method &#8211; with our without loading the resource connection &#8211; is the most efficient method to load product attribute data.  If multiple product attributes are needed, it could maybe be argued that loading the product object directly would be more efficient, but there is a balancing point where that is true or false depending on how many product attributes are needed.  Use the information of this article to choose the best method for the development project.<\/p>","protected":false},"excerpt":{"rendered":"<p>Depending how a product was loaded in Magento 2, not all of the product attributes are available on [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3567,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"wprm-recipe-roundup-name":"","wprm-recipe-roundup-description":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[46,5],"tags":[345,385],"class_list":["post-3559","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-magento","category-website-development","tag-magento-2","tag-php"],"jetpack_featured_media_url":"https:\/\/promincproductions.com\/blog\/wp-content\/uploads\/2024\/03\/magento-2-load-product-attribute.png","jetpack_shortlink":"https:\/\/wp.me\/p4BbcR-Vp","jetpack_sharing_enabled":true,"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/posts\/3559","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/comments?post=3559"}],"version-history":[{"count":11,"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/posts\/3559\/revisions"}],"predecessor-version":[{"id":3572,"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/posts\/3559\/revisions\/3572"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/media\/3567"}],"wp:attachment":[{"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/media?parent=3559"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/categories?post=3559"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/tags?post=3559"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}