{"id":1534,"date":"2018-03-13T17:35:18","date_gmt":"2018-03-13T16:35:18","guid":{"rendered":"https:\/\/wam.global\/wam-room\/extension-attributes-codehacks-i4\/"},"modified":"2026-02-10T16:05:09","modified_gmt":"2026-02-10T15:05:09","slug":"extension-attributes-codehacks-i4","status":"publish","type":"post","link":"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/","title":{"rendered":"Exprimiendo los extension attributes en Magento 2 #Codehacks"},"content":{"rendered":"<p>En este post explicar\u00e9 como hacer un uso correcto de los extension attributes. Lo primero de todo es saber para qu\u00e9 sirve esta nueva funcionalidad de Magento 2.<br \/>Los extension attributes son usados para a\u00f1adir nuevos atributos a modelos sin tener que modificar ni la clase ni la interfaz de ellos. Esto es aplicable tanto a modelos propios de Magento como de m\u00f3dulos de terceros. El \u00fanico requisito es que la interfaz del modelo que vayamos a extender herede de &nbsp;<strong>Magento  Framework  Api  ExtensibleDataInterface<\/strong> y su clase de <strong>Magento  Framework  Model  AbstractExtensibleModel<\/strong>.<\/p>\n<p>Para explicar esta nueva funcionalidad, vamos a basarnos en una entidad propia, la cual explicamos en el post <a href=\"http:\/\/www.interactiv4.com\/blog-es\/nueva-entidad-en-magento-2\/\" target=\"_blank\" rel=\"noreferrer noopener\">Creaci\u00f3n de una nueva entidad en Magento 2.<\/a><\/p>\n<p>Cabe destacar que todo el m\u00f3dulo sigue las <a href=\"https:\/\/www.php-fig.org\/psr\/\" target=\"_blank\" rel=\"noreferrer noopener\">recomendaciones est\u00e1ndar de PHP<\/a>.<\/p>\n<h2>Creaci\u00f3n de modelos, recursos y repositorios<\/h2>\n<p>Para el uso de los extension attributes tenemos 2 opciones, guardar estos nuevos atributos en la misma tabla de la base de datos o en otra distinta. El ejemplo que vamos a explicar es a\u00f1adiendo la nueva informaci\u00f3n en una tabla.<\/p>\n<p>Para ello, crearemos exactamente una nueva entidad con los mismos pasos que en el post <a href=\"http:\/\/www.interactiv4.com\/blog-es\/nueva-entidad-en-magento-2\/\" target=\"_blank\" rel=\"noreferrer noopener\">Creaci\u00f3n de una nueva entidad en Magento 2.<\/a>. En nuesto caso, en el <strong>InstallSchema.php<\/strong> crearemos un campo que almacenar\u00e1 el id del modelo principal el cual ser\u00e1 una clave for\u00e1nea del campo del modelo principal.<\/p>\n<p><strong>app \/ code \/ Interactiv4 \/ CustomPost \/ Setup \/ InstallSchema.php<\/strong><br \/><code><\/code><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\n\/**\n * @author Interactiv4 Team\n * @copyright Copyright \u00a9 Interactiv4 (https:\/\/www.interactiv4.com)\n *\/\n\nnamespace Interactiv4CustomPostSetup;\n\nuse Interactiv4CustomPostApiDataPostInterface;\nuse Interactiv4PostApiDataEntityInterface;\nuse MagentoFrameworkDBAdapterAdapterInterface;\nuse MagentoFrameworkDBDdlTable;\nuse MagentoFrameworkSetupInstallSchemaInterface;\nuse MagentoFrameworkSetupModuleContextInterface;\nuse MagentoFrameworkSetupSchemaSetupInterface;\nuse Zend_Db_Exception;\n\n\/**\n * Class InstallSchema\n *\/\nclass InstallSchema implements InstallSchemaInterface\n{\n    \/**\n     * {@inheritdoc}\n     *\/\n    public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)\n    {\n        $installer = $setup;\n\n        $installer->startSetup();\n\n        \/\/Custom post\n        $installer->getConnection()->dropTable($installer->getTable(PostInterface::SCHEMA_TABLE));\n        $this->installTableCustomPost($installer);\n\n        $installer->endSetup();\n    }\n\n\n    \/**\n     * Create table relations between custom entity and custom post\n     *\n     * @param SchemaSetupInterface $installer\n     * @throws Zend_Db_Exception\n     *\/\n    private function installTableCustomPost(SchemaSetupInterface $installer)\n    {\n        $table = $installer->getConnection()->newTable(\n            $installer->getTable(PostInterface::SCHEMA_TABLE)\n        )->addColumn(\n            PostInterface::FIELD_ID,\n            Table::TYPE_INTEGER,\n            null,\n            ['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true],\n            'Custom post Id'\n        )->addColumn(\n            PostInterface::FIELD_POST_ID,\n            Table::TYPE_INTEGER,\n            null,\n            ['unsigned' => true, 'nullable' => false],\n            'Post Id'\n        )->addColumn(\n            PostInterface::FIELD_SHORT_DESCRIPTION,\n            Table::TYPE_TEXT,\n            null,\n            ['nullable' => false, 'default' => ''],\n            'Short description'\n        )->addIndex(\n            $installer->getIdxName(\n                $installer->getTable(PostInterface::SCHEMA_TABLE),\n                [PostInterface::FIELD_POST_ID],\n                AdapterInterface::INDEX_TYPE_UNIQUE\n            ),\n            [PostInterface::FIELD_POST_ID],\n            ['type' => AdapterInterface::INDEX_TYPE_UNIQUE]\n        )->addForeignKey(\n            $installer->getFkName(\n                PostInterface::SCHEMA_TABLE,\n                PostInterface::FIELD_POST_ID,\n                EntityInterface::TABLE,\n                EntityInterface::ID\n            ),\n            PostInterface::FIELD_POST_ID,\n            $installer->getTable(EntityInterface::TABLE),\n            EntityInterface::ID,\n            Table::ACTION_CASCADE\n        )->setComment(\n            'Custom Post'\n        );\n\n        $installer->getConnection()->createTable($table);\n    }\n}<\/pre>\n<h2>Creaci\u00f3n de extension attributes<\/h2>\n<p>Para a\u00f1adir los extension attributes a un modelo ya creado, debemos primero crear un archivo <strong>extension_attributes.xml<\/strong>, en el cual especificaremos la interfaz del modelo principal y los campos que vamos a a\u00f1adir.<\/p>\n<p><strong>app \/ code \/ Interactiv4 \/ CustomPost \/ etc \/ extension_attributes.xml<\/strong><\/p>\n<pre class=\"wp-block-code\"><code>&lt;?xml version=\"1.0\"?&gt;\n&lt;!--\n~ @author Interactiv4 Team\n~ @copyright  Copyright \u00a9 Interactiv4 (https:\/\/www.interactiv4.com)\n--&gt;\n\n&lt;config xmlns_xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\" xsi_noNamespaceSchemaLocation=\"urn:magento:framework:Api\/etc\/extension_attributes.xsd\"&gt;\n   &lt;extension_attributes for=\"Interactiv4PostApiDataEntityInterface\"&gt;\n       &lt;attribute code=\"short_description\" type=\"string\"&gt;\n           &lt;resources&gt;\n               &lt;resource ref=\"Interactiv4_Post::entity\"\/&gt;\n           &lt;\/resources&gt;\n           &lt;join reference_table=\"interactiv4_custompost_post\" reference_field=\"post_id\" join_on_field=\"entity_id\"&gt;\n               &lt;field&gt;short_description&lt;\/field&gt;\n           &lt;\/join&gt;\n       &lt;\/attribute&gt;\n   &lt;\/extension_attributes&gt;\n&lt;\/config&gt;<\/code><\/pre>\n<p>En el ejemplo de arriba podemos ver, como le indicamos la interfaz del modelo principal, el nombre del nuevo atributo y su tipolog\u00eda (int, string, un objeto, array\u2026).<\/p>\n<p>El par\u00e1metro <strong>resources<\/strong>, es opcional y restringe el acceso al usuario con un permiso espec\u00edfico.<\/p>\n<p>Cabe destacar la especificaci\u00f3n del <strong>join<\/strong>, el cual es opcional. En este punto, especificamos nuestra nueva tabla y los campos que est\u00e1n referenciados entre s\u00ed entre el modelo principal y el nuestro. Esto s\u00f3lo funcionar\u00e1 si en el m\u00e9todo <strong>getList<\/strong> del repositorio principal est\u00e1 incluido el <strong>joinProcessor<\/strong> de los extension attributes <strong>(Magento  Framework  Api  ExtensionAttribute  JoinProcessorInterface)<\/strong>.<\/p>\n<p><strong>app \/ code \/ Interactiv4 \/ Post \/ Model \/ EntityRepository.php<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\n\/**\n* @author Interactiv4 Team\n* @copyright Copyright (c) 2017 Interactiv4 (https:\/\/www.interactiv4.com)\n* @package Interactiv4_Post\n*\/\n\nnamespace Interactiv4PostModel;\n\n...\nuse MagentoFrameworkApiExtensionAttributeJoinProcessorInterface;\n\nclass EntityRepository implements EntityRepositoryInterface\n{\n\n...\n\n   \/**\n    * EntityRepository constructor.\n    *\n    * @param EntityFactory $entityFactory\n    * @param CollectionFactory $entityCollectionFactory\n    * @param EntitySearchResultsInterfaceFactory $entitySearchResultsInterfaceFactory\n    * @param CollectionProcessorInterface $collectionProcessor\n    * @param JoinProcessorInterface $extensionAttributesJoinProcessor\n    *\/\n   public function __construct(\n       EntityFactory $entityFactory,\n       CollectionFactory $entityCollectionFactory,\n       EntitySearchResultsInterfaceFactory $entitySearchResultsInterfaceFactory,\n       CollectionProcessorInterface $collectionProcessor,\n       JoinProcessorInterface $extensionAttributesJoinProcessor\n   ) {\n       $this->entityFactory = $entityFactory;\n       $this->entityCollectionFactory = $entityCollectionFactory;\n       $this->entitySearchResultsInterfaceFactory = $entitySearchResultsInterfaceFactory;\n       $this->collectionProcessor = $collectionProcessor;\n       $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor;\n   }\n\n   ...\n\n   \/**\n    * @inheritdoc\n    *\/\n   public function getList(SearchCriteriaInterface $searchCriteria)\n   {\n       \/** @var Collection $collection *\/\n       $collection = $this->entityCollectionFactory->create();\n\n       $this->extensionAttributesJoinProcessor->process($collection, EntityInterface::class);\n       $this->collectionProcessor->process($searchCriteria, $collection);\n\n       \/** @var EntitySearchResultsInterface $searchResults *\/\n       $searchResults = $this->entitySearchResultsInterfaceFactory->create();\n       $searchResults->setSearchCriteria($searchCriteria);\n       $searchResults->setItems($collection->getItems());\n       $searchResults->setTotalCount($collection->getSize());\n\n       return $searchResults;\n   }\n}<\/pre>\n<p>Gracias a este <strong>joinProcessor<\/strong> podemos definir en nuestro <strong>PostRepository.php<\/strong> una funci\u00f3n <strong>getListPostByShortDescription()<\/strong> la cual obtiene un listado de todas las entidades del modelo principal filtrando por el valor de un extension attributes.<\/p>\n<p><strong>app \/ code \/ Interactiv4 \/ CustomPost \/ Model \/ PostRepository.php<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\n\/**\n * @author Interactiv4 Team\n * @copyright Copyright \u00a9 Interactiv4 (https:\/\/www.interactiv4.com)\n *\/\n\nnamespace Interactiv4CustomPostModel;\n\nuse Exception;\nuse Interactiv4CustomPostApiDataPostInterface;\nuse Interactiv4CustomPostApiDataPostSearchResultsInterface;\nuse Interactiv4CustomPostApiDataPostSearchResultsInterfaceFactory;\nuse Interactiv4CustomPostApiPostRepositoryInterface;\nuse Interactiv4CustomPostModelPostFactory;\nuse Interactiv4CustomPostModelResourceModelPost as ResourceCustomPost;\nuse Interactiv4CustomPostModelResourceModelPostCollection;\nuse Interactiv4CustomPostModelResourceModelPostCollectionFactory;\nuse Interactiv4PostApiDataEntityInterface;\nuse Interactiv4PostApiEntityRepositoryInterface;\nuse MagentoFrameworkApiExtensionAttributeJoinProcessorInterface;\nuse MagentoFrameworkApiFilterBuilder;\nuse MagentoFrameworkApiSearchSearchCriteria;\nuse MagentoFrameworkApiSearchSearchCriteriaBuilder;\nuse MagentoFrameworkApiSearchCriteriaCollectionProcessorInterface;\nuse MagentoFrameworkApiSearchCriteriaInterface;\nuse MagentoFrameworkApiSortOrder;\nuse MagentoFrameworkExceptionCouldNotSaveException;\nuse MagentoFrameworkExceptionNoSuchEntityException;\nuse MagentoFrameworkExceptionStateException;\nuse MagentoFrameworkExceptionValidatorException;\n\n\/**\n * Class PostRepository\n * @SuppressWarnings(PHPMD.CouplingBetweenObjects)\n *\/\nclass PostRepository implements PostRepositoryInterface\n{\n    \/**\n     * @var ResourceCustomPost\n     *\/\n    private $resourceCustomPost;\n\n    \/**\n     * @var PostFactory\n     *\/\n    private $customPostFactory;\n\n    \/**\n     * @var CollectionFactory\n     *\/\n    private $customPostCollectionFactory;\n\n    \/**\n     * @var PostSearchResultsInterfaceFactory\n     *\/\n    private $customPostSearchResultInterfaceFactory;\n\n    \/**\n     * @var CollectionProcessorInterface\n     *\/\n    private $collectionProcessor;\n\n    \/**\n     * @var JoinProcessorInterface\n     *\/\n    private $extensionAttributesJoinProcessor;\n\n    \/**\n     * @var EntityRepositoryInterface\n     *\/\n    private $entityRepository;\n\n    \/**\n     * @var FilterBuilder\n     *\/\n    private $filterBuilder;\n\n    \/**\n     * @var SearchCriteriaBuilder\n     *\/\n    private $searchCriteriaBuilder;\n\n    \/**\n     * @var SortOrder\n     *\/\n    private $sortOrder;\n\n    \/**\n     * PostRepository constructor.\n     *\n     * @param ResourceCustomPost $resourceCustomPost\n     * @param PostFactory $customPostFactory\n     * @param CollectionFactory $customPostCollectionFactory\n     * @param PostSearchResultsInterfaceFactory $customPostSearchResultInterfaceFactory\n     * @param CollectionProcessorInterface $collectionProcessor\n     * @param JoinProcessorInterface $extensionAttributesJoinProcessor\n     * @param EntityRepositoryInterface $entityRepository\n     * @param FilterBuilder $filterBuilder\n     * @param SearchCriteriaBuilder $searchCriteriaBuilder\n     * @param SortOrder $sortOrder\n     * @SuppressWarnings(PHPMD.ExcessiveParameterList)\n     *\/\n    public function __construct(\n        ResourceCustomPost $resourceCustomPost,\n        PostFactory $customPostFactory,\n        CollectionFactory $customPostCollectionFactory,\n        PostSearchResultsInterfaceFactory $customPostSearchResultInterfaceFactory,\n        CollectionProcessorInterface $collectionProcessor,\n        JoinProcessorInterface $extensionAttributesJoinProcessor,\n        EntityRepositoryInterface $entityRepository,\n        FilterBuilder $filterBuilder,\n        SearchCriteriaBuilder $searchCriteriaBuilder,\n        SortOrder $sortOrder\n    ) {\n        $this->resourceCustomPost                     = $resourceCustomPost;\n        $this->customPostFactory                      = $customPostFactory;\n        $this->customPostCollectionFactory            = $customPostCollectionFactory;\n        $this->customPostSearchResultInterfaceFactory = $customPostSearchResultInterfaceFactory;\n        $this->collectionProcessor                    = $collectionProcessor;\n        $this->extensionAttributesJoinProcessor       = $extensionAttributesJoinProcessor;\n        $this->entityRepository                       = $entityRepository;\n        $this->filterBuilder                          = $filterBuilder;\n        $this->searchCriteriaBuilder                  = $searchCriteriaBuilder;\n        $this->sortOrder                              = $sortOrder;\n    }\n\n    \/**\n     * @inheritdoc\n     *\/\n    public function save(PostInterface $customPost)\n    {\n        $this->resourceCustomPost->save($customPost);\n\n        return $customPost;\n    }\n\n    \/**\n     * @inheritdoc\n     *\/\n    public function getById($customPostId)\n    {\n        return $this->get($customPostId);\n    }\n\n    \/**\n     * @inheritdoc\n     *\/\n    public function get($value, $attributeCode = null)\n    {\n        \/** @var Post $customPost *\/\n        $customPost = $this->customPostFactory->create()->load($value, $attributeCode);\n\n        if (!$customPost->getId()) {\n            throw new NoSuchEntityException(__('Unable to find custom post'));\n        }\n\n        return $customPost;\n    }\n\n    \/**\n     * @inheritdoc\n     *\/\n    public function delete(PostInterface $customPost)\n    {\n        $customPostId = $customPost->getId();\n        try {\n            $this->resourceCustomPost->delete($customPost);\n        } catch (Exception $e) {\n            throw new StateException(\n                __('Unable to remove custom post %1', $customPostId)\n            );\n        }\n\n        return true;\n    }\n\n    \/**\n     * @inheritdoc\n     *\/\n    public function deleteById($customPostId)\n    {\n        $customPost = $this->getById($customPostId);\n\n        return $this->delete($customPost);\n    }\n\n    \/**\n     * @inheritdoc\n     *\/\n    public function getList(SearchCriteriaInterface $searchCriteria)\n    {\n        \/** @var Collection $collection *\/\n        $collection = $this->customPostCollectionFactory->create();\n\n        $this->extensionAttributesJoinProcessor->process($collection, PostInterface::class);\n        $this->collectionProcessor->process($searchCriteria, $collection);\n\n        \/** @var PostSearchResultsInterface $searchResults *\/\n        $searchResults = $this->customPostSearchResultInterfaceFactory->create();\n        $searchResults->setSearchCriteria($searchCriteria);\n        $searchResults->setItems($collection->getItems());\n        $searchResults->setTotalCount($collection->getSize());\n\n        return $searchResults;\n    }\n\n    \/**\n     * @inheritdoc\n     *\/\n    public function getListPostByShortDescription($shortDescription)\n    {\n\n        $filter = $this->filterBuilder\n            ->setField(PostInterface::FIELD_SHORT_DESCRIPTION)\n            ->setValue($shortDescription)\n            ->setConditionType('LIKE')\n            ->create();\n\n        \/** @var SearchCriteria $searchCriteria *\/\n        $searchCriteria = $this->searchCriteriaBuilder->addFilter($filter);\n\n        $sortOrder = $this->sortOrder->setField(EntityInterface::NAME)->setDirection('asc');\n        $searchCriteria->setSortOrders([$sortOrder]);\n        $entitySearchResults = $this->entityRepository->getList($searchCriteria);\n\n        return $entitySearchResults;\n    }\n}<\/pre>\n<p>Gracias a la definici\u00f3n del archivo <strong>extension_attributes.xml<\/strong>, Magento generar\u00e1 en la carpeta <strong>var \/ generation<\/strong> (&lt; Magento 2.2) o generated (&gt; Magento 2.2) una clase <strong>EntityExtensionInterface.php<\/strong> con los getters y setters de los atributos que hayamos definido en dicho archivo xml.<\/p>\n<p><strong>var \/ generation \/ Interactiv4 \/ Post \/ Api \/ Data \/ EntityExtensionInterface.php<\/strong> \u00f3<br \/><strong>generated \/ code \/ Interactiv4 \/ Post \/ Api \/ Data \/ EntityExtensionInterface.php<\/strong><\/p>\n<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\n\/**\n* @author Interactiv4 Team\n* @copyright  Copyright \u00a9 Interactiv4 (https:\/\/www.interactiv4.com)\n*\/\n\nnamespace Interactiv4PostApiData;\n\n\/**\n* ExtensionInterface class for @see Interactiv4PostApiDataEntityInterface\n*\/\ninterface EntityExtensionInterface extends MagentoFrameworkApiExtensionAttributesInterface\n{\n   \/**\n    * @return string|null\n    *\/\n   public function getShortDescription();\n\n   \/**\n    * @param string $shortDescription\n    * @return $this\n    *\/\n   public function setShortDescription($shortDescription);\n}<\/pre>\n<h2>Obtener y almacenar informaci\u00f3n de extension attributes<\/h2>\n<h3>Plugins<\/h3>\n<p>Magento no almacena ni obtiene la informaci\u00f3n de los extension attributes de manera autom\u00e1tica. Tenemos que obtenerla y guardarla de manera manual haciendo uso de los plugins en las funciones <strong>get()<\/strong>, <strong>getList()<\/strong> y <strong>save()<\/strong> del repositorio principal.<\/p>\n<p><strong>app \/ etc \/ di.xml<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?>\n&lt;!--\n~ @author Interactiv4 Team\n~ @copyright  Copyright \u00a9 Interactiv4 (https:\/\/www.interactiv4.com)\n-->\n\n&lt;config xmlns_xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\" xsi_noNamespaceSchemaLocation=\"urn:magento:framework:ObjectManager\/etc\/config.xsd\">\n   &lt;preference for=\"Interactiv4CustomPostApiDataPostInterface\" type=\"Interactiv4CustomPostModelPost\" \/>\n   &lt;preference for=\"Interactiv4CustomPostApiDataPostSearchResultsInterface\" type=\"Interactiv4CustomPostModelPostSearchResults\" \/>\n   &lt;preference for=\"Interactiv4CustomPostApiPostRepositoryInterface\" type=\"Interactiv4CustomPostModelPostRepository\" \/>\n   &lt;type name=\"Interactiv4PostApiEntityRepositoryInterface\">\n       &lt;plugin name=\"interactiv4_custompost_plugin_entity_repository\" type=\"Interactiv4CustomPostPluginEntityRepositoryPlugin\"\/>\n   &lt;\/type>\n&lt;\/config><\/pre>\n<p><strong>app \/ code \/ Plugin \/ EntityRepositoryPlugin.php<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\n\/**\n * @author Interactiv4 Team\n * @copyright Copyright \u00a9 Interactiv4 (https:\/\/www.interactiv4.com)\n *\/\n\nnamespace Interactiv4CustomPostPlugin;\n\nuse Interactiv4CustomPostApiDataPostInterface;\nuse Interactiv4CustomPostApiDataPostInterfaceFactory;\nuse Interactiv4CustomPostApiPostRepositoryInterface;\nuse Interactiv4PostApiDataEntityExtensionFactory;\nuse Interactiv4PostApiDataEntityExtensionInterface;\nuse Interactiv4PostApiDataEntityInterface;\nuse Interactiv4PostApiDataEntitySearchResultsInterface;\nuse Interactiv4PostApiEntityRepositoryInterface;\nuse MagentoFrameworkExceptionCouldNotSaveException;\nuse MagentoFrameworkExceptionNoSuchEntityException;\n\n\/**\n * Class EntityRepositoryPlugin\n *\/\nclass EntityRepositoryPlugin\n{\n    \/**\n     * @var EntityExtensionFactory\n     *\/\n    private $entityExtensionFactory;\n\n    \/**\n     * @var PostInterfaceFactory\n     *\/\n    private $customPostFactory;\n\n    \/**\n     * @var PostRepositoryInterface\n     *\/\n    private $customPostRepository;\n\n    \/**\n     * PostGet constructor.\n     *\n     * @param EntityExtensionFactory $entityExtensionFactory\n     * @param PostInterfaceFactory $customPostFactory\n     * @param PostRepositoryInterface $customPostRepository\n     *\/\n    public function __construct(\n        EntityExtensionFactory $entityExtensionFactory,\n        PostInterfaceFactory $customPostFactory,\n        PostRepositoryInterface $customPostRepository\n    ) {\n        $this->entityExtensionFactory = $entityExtensionFactory;\n        $this->customPostFactory      = $customPostFactory;\n        $this->customPostRepository   = $customPostRepository;\n    }\n\n    \/**\n     * @param EntityRepositoryInterface $subject\n     * @param EntityInterface $result\n     * @return EntityInterface\n     * @SuppressWarnings(PHPMD.UnusedFormalParameter)\n     *\/\n    public function afterGet(EntityRepositoryInterface $subject, EntityInterface $result)\n    {\n        \/** @var EntityExtensionInterface $extensionAttributes *\/\n        $extensionAttributes = $result->getExtensionAttributes() ?: $this->entityExtensionFactory->create();\n\n        try {\n            \/** @var PostInterface $customPost *\/\n            $customPost = $this->customPostRepository->get($result->getId(), PostInterface::FIELD_POST_ID);\n        } catch (NoSuchEntityException $e) {\n            $result->setExtensionAttributes($extensionAttributes);\n\n            return $result;\n        }\n        $extensionAttributes->setShortDescription($customPost->getShortDescription());\n\n        $result->setExtensionAttributes($extensionAttributes);\n\n        return $result;\n    }\n\n    \/**\n     * @param EntityRepositoryInterface $subject\n     * @param EntitySearchResultsInterface $entities\n     * @return EntitySearchResultsInterface\n     *\/\n    public function afterGetList(EntityRepositoryInterface $subject, EntitySearchResultsInterface $entities)\n    {\n        foreach ($entities->getItems() as $entity) {\n            $this->afterGet($subject, $entity);\n        }\n\n        return $entities;\n    }\n\n    \/**\n     * @param EntityRepositoryInterface $subject\n     * @param EntityInterface $result\n     * @return EntityInterface\n     * @throws CouldNotSaveException\n     * @SuppressWarnings(PHPMD.UnusedFormalParameter)\n     *\/\n    public function afterSave(EntityRepositoryInterface $subject, EntityInterface $result)\n    {\n        $extensionAttributes = $result->getExtensionAttributes() ?: $this->entityExtensionFactory->create();\n        if ($extensionAttributes !== null &amp;&amp;\n            $extensionAttributes->getShortDescription() !== null\n        ) {\n            \/** @var PostInterface $customPost *\/\n            try {\n                $customPost = $this->customPostRepository->get($result->getId(), PostInterface::FIELD_POST_ID);\n            } catch (NoSuchEntityException $e) {\n                $customPost = $this->customPostFactory->create();\n            }\n            $customPost->setPostId($result->getId());\n            $customPost->setShortDescription($extensionAttributes->getShortDescription());\n            $this->customPostRepository->save($customPost);\n        }\n\n        return $result;\n    }\n}<\/pre>\n<p>De esta manera conseguimos que cada vez que se cargue un modelo o un listado, contenga la informaci\u00f3n adicional de los extension attributes. A su vez, cada vez que guardemos la informaci\u00f3n de un producto, tambi\u00e9n guardaremos la informaci\u00f3n adicional.<\/p>\n<p>Espero que os haya sido de ayuda y cualquier duda pod\u00e9is dejar un comentario.<\/p>\n<p>En este <a href=\"https:\/\/github.com\/raumatbel\/Interactiv4-Post-Extension-Attributes\" target=\"_blank\" rel=\"noreferrer noopener\">link<\/a> pod\u00e9is descargar el c\u00f3digo de esta explicaci\u00f3n y en este otro<a href=\"https:\/\/github.com\/interactiv4\/Interactiv4-Post-Custom-Entity\" target=\"_blank\" rel=\"noreferrer noopener\">link<\/a> la entidad principal de la que vamos a extender.<\/p>","protected":false},"excerpt":{"rendered":"<p>En este post explicar\u00e9 como hacer un uso correcto de los extension attributes. Lo primero de todo es saber para qu\u00e9 sirve esta nueva funcionalidad de Magento 2.Los extension attributes son usados para a\u00f1adir nuevos atributos a modelos sin tener que modificar ni la clase ni la interfaz de ellos. Esto es aplicable tanto a [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":5754,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[50],"tags":[207,191],"solutions":[],"formats":[40],"class_list":["post-1534","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tecnologia","tag-code-hacks","tag-magento","formats-articulo"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.7 (Yoast SEO v27.2) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Extension Attributes en Magento 2 | Interactiv4<\/title>\n<meta name=\"description\" content=\"Exprimiendo Los Extension Attributes en Magento 2 #Codehacks. Ra\u00fal Mateos nos explica como hacer un uso correcto de los extension attributes y para qu\u00e9 sirve esta nueva funcionalidad de Magento 2. Interactiv4 | Interactiv4, tu Ecommerce Partner\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/\" \/>\n<meta property=\"og:locale\" content=\"es_ES\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Exprimiendo los extension attributes en Magento 2\" \/>\n<meta property=\"og:description\" content=\"Ra\u00fal Mateos nos explica c\u00f3mo hacer un uso correcto de los extension attributes y para qu\u00e9 sirve esta nueva funcionalidad de Magento 2.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/\" \/>\n<meta property=\"og:site_name\" content=\"WAM\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/global.wam\" \/>\n<meta property=\"article:published_time\" content=\"2018-03-13T16:35:18+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-02-10T15:05:09+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/wam.global\/wp-content\/uploads\/2025\/11\/post-extension-attributes.jpg\" \/>\n<meta name=\"author\" content=\"WAM\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:title\" content=\"Exprimiendo los extension attributes en Magento 2 #Codehacks\" \/>\n<meta name=\"twitter:creator\" content=\"@wearemktWAM\" \/>\n<meta name=\"twitter:site\" content=\"@wearemktWAM\" \/>\n<meta name=\"twitter:label1\" content=\"Escrito por\" \/>\n\t<meta name=\"twitter:data1\" content=\"WAM\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tiempo de lectura\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/\"},\"author\":{\"name\":\"WAM\",\"@id\":\"https:\/\/wam.global\/es\/#\/schema\/person\/2a351c7ee1c407ba0581765e91145a2e\"},\"headline\":\"Exprimiendo los extension attributes en Magento 2 #Codehacks\",\"datePublished\":\"2018-03-13T16:35:18+00:00\",\"dateModified\":\"2026-02-10T15:05:09+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/\"},\"wordCount\":652,\"publisher\":{\"@id\":\"https:\/\/wam.global\/es\/#organization\"},\"image\":{\"@id\":\"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/wam.global\/wp-content\/uploads\/2025\/12\/extension-attributes-codehacks-i4.webp\",\"keywords\":[\"Code Hacks\",\"magento\"],\"articleSection\":[\"Tecnolog\u00eda\"],\"inLanguage\":\"es\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/\",\"url\":\"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/\",\"name\":\"Extension Attributes en Magento 2 | Interactiv4\",\"isPartOf\":{\"@id\":\"https:\/\/wam.global\/es\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/wam.global\/wp-content\/uploads\/2025\/12\/extension-attributes-codehacks-i4.webp\",\"datePublished\":\"2018-03-13T16:35:18+00:00\",\"dateModified\":\"2026-02-10T15:05:09+00:00\",\"description\":\"Exprimiendo Los Extension Attributes en Magento 2 #Codehacks. Ra\u00fal Mateos nos explica como hacer un uso correcto de los extension attributes y para qu\u00e9 sirve esta nueva funcionalidad de Magento 2. Interactiv4 | Interactiv4, tu Ecommerce Partner\",\"breadcrumb\":{\"@id\":\"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/#primaryimage\",\"url\":\"https:\/\/wam.global\/wp-content\/uploads\/2025\/12\/extension-attributes-codehacks-i4.webp\",\"contentUrl\":\"https:\/\/wam.global\/wp-content\/uploads\/2025\/12\/extension-attributes-codehacks-i4.webp\",\"width\":2000,\"height\":1301},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Portada\",\"item\":\"https:\/\/wam.global\/es\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Exprimiendo los extension attributes en Magento 2 #Codehacks\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/wam.global\/es\/#website\",\"url\":\"https:\/\/wam.global\/es\/\",\"name\":\"WAM\",\"description\":\"The hybrid reference where Technology mixes with Creativity Consulting with Execution and Brands with People.\",\"publisher\":{\"@id\":\"https:\/\/wam.global\/es\/#organization\"},\"alternateName\":\"WAM\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/wam.global\/es\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/wam.global\/es\/#organization\",\"name\":\"WAM\",\"alternateName\":\"WAM\",\"url\":\"https:\/\/wam.global\/es\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/wam.global\/es\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/wam.global\/wp-content\/uploads\/2025\/09\/wam-logo-black.svg\",\"contentUrl\":\"https:\/\/wam.global\/wp-content\/uploads\/2025\/09\/wam-logo-black.svg\",\"width\":1,\"height\":1,\"caption\":\"WAM\"},\"image\":{\"@id\":\"https:\/\/wam.global\/es\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/global.wam\",\"https:\/\/x.com\/wearemktWAM\",\"https:\/\/www.instagram.com\/wamglobal\/\",\"https:\/\/www.linkedin.com\/company\/wearemarketing-wam\"],\"ownershipFundingInfo\":\"https:\/\/wam.global\/about\/\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/wam.global\/es\/#\/schema\/person\/2a351c7ee1c407ba0581765e91145a2e\",\"name\":\"WAM\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/secure.gravatar.com\/avatar\/b7bb15295c3f9346d4a0f77a238935a1a724751ff575a6d842cb5c2a922ce90d?s=96&d=mm&r=g\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/b7bb15295c3f9346d4a0f77a238935a1a724751ff575a6d842cb5c2a922ce90d?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/b7bb15295c3f9346d4a0f77a238935a1a724751ff575a6d842cb5c2a922ce90d?s=96&d=mm&r=g\",\"caption\":\"WAM\"},\"description\":\"WAM es un ecosistema h\u00edbrido donde estrategia, tecnolog\u00eda y creatividad se conectan para transformar marcas y negocios. Nacidos del pensamiento y la acci\u00f3n, integramos consultor\u00eda y ejecuci\u00f3n, marcas y personas, para crear soluciones reales, innovadoras y con impacto tangible en 360\u00b0. Nuestra propuesta se articula en cuatro estudios: Creativity &amp; Content to Impact, CRM &amp; Marketing Automation to Connect, Commerce &amp; Experience to Scale y Media &amp; Optimization to Grow, que trabajan de forma coordinada para generar soluciones reales, medibles y alineadas con los objetivos de negocio. Bajo la filosof\u00eda Thought &amp; Action y la promesa \u201cDecoding Meaning\u201d, ayudamos a las marcas a traducir datos y tendencias en decisiones que crean experiencias relevantes, construyen valor de marca y mejoran resultados.\",\"url\":\"https:\/\/wam.global\/es\/wam-room\/author\/wam\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Extension Attributes en Magento 2 | Interactiv4","description":"Exprimiendo Los Extension Attributes en Magento 2 #Codehacks. Ra\u00fal Mateos nos explica como hacer un uso correcto de los extension attributes y para qu\u00e9 sirve esta nueva funcionalidad de Magento 2. Interactiv4 | Interactiv4, tu Ecommerce Partner","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/","og_locale":"es_ES","og_type":"article","og_title":"Exprimiendo los extension attributes en Magento 2","og_description":"Ra\u00fal Mateos nos explica c\u00f3mo hacer un uso correcto de los extension attributes y para qu\u00e9 sirve esta nueva funcionalidad de Magento 2.","og_url":"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/","og_site_name":"WAM","article_publisher":"https:\/\/www.facebook.com\/global.wam","article_published_time":"2018-03-13T16:35:18+00:00","article_modified_time":"2026-02-10T15:05:09+00:00","og_image":[{"url":"https:\/\/wam.global\/wp-content\/uploads\/2025\/11\/post-extension-attributes.jpg","type":"","width":"","height":""}],"author":"WAM","twitter_card":"summary_large_image","twitter_title":"Exprimiendo los extension attributes en Magento 2 #Codehacks","twitter_creator":"@wearemktWAM","twitter_site":"@wearemktWAM","twitter_misc":{"Escrito por":"WAM","Tiempo de lectura":"9 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/#article","isPartOf":{"@id":"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/"},"author":{"name":"WAM","@id":"https:\/\/wam.global\/es\/#\/schema\/person\/2a351c7ee1c407ba0581765e91145a2e"},"headline":"Exprimiendo los extension attributes en Magento 2 #Codehacks","datePublished":"2018-03-13T16:35:18+00:00","dateModified":"2026-02-10T15:05:09+00:00","mainEntityOfPage":{"@id":"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/"},"wordCount":652,"publisher":{"@id":"https:\/\/wam.global\/es\/#organization"},"image":{"@id":"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/#primaryimage"},"thumbnailUrl":"https:\/\/wam.global\/wp-content\/uploads\/2025\/12\/extension-attributes-codehacks-i4.webp","keywords":["Code Hacks","magento"],"articleSection":["Tecnolog\u00eda"],"inLanguage":"es"},{"@type":"WebPage","@id":"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/","url":"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/","name":"Extension Attributes en Magento 2 | Interactiv4","isPartOf":{"@id":"https:\/\/wam.global\/es\/#website"},"primaryImageOfPage":{"@id":"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/#primaryimage"},"image":{"@id":"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/#primaryimage"},"thumbnailUrl":"https:\/\/wam.global\/wp-content\/uploads\/2025\/12\/extension-attributes-codehacks-i4.webp","datePublished":"2018-03-13T16:35:18+00:00","dateModified":"2026-02-10T15:05:09+00:00","description":"Exprimiendo Los Extension Attributes en Magento 2 #Codehacks. Ra\u00fal Mateos nos explica como hacer un uso correcto de los extension attributes y para qu\u00e9 sirve esta nueva funcionalidad de Magento 2. Interactiv4 | Interactiv4, tu Ecommerce Partner","breadcrumb":{"@id":"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/#primaryimage","url":"https:\/\/wam.global\/wp-content\/uploads\/2025\/12\/extension-attributes-codehacks-i4.webp","contentUrl":"https:\/\/wam.global\/wp-content\/uploads\/2025\/12\/extension-attributes-codehacks-i4.webp","width":2000,"height":1301},{"@type":"BreadcrumbList","@id":"https:\/\/wam.global\/es\/wam-room\/extension-attributes-codehacks-i4\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Portada","item":"https:\/\/wam.global\/es\/"},{"@type":"ListItem","position":2,"name":"Exprimiendo los extension attributes en Magento 2 #Codehacks"}]},{"@type":"WebSite","@id":"https:\/\/wam.global\/es\/#website","url":"https:\/\/wam.global\/es\/","name":"WAM","description":"The hybrid reference where Technology mixes with Creativity Consulting with Execution and Brands with People.","publisher":{"@id":"https:\/\/wam.global\/es\/#organization"},"alternateName":"WAM","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/wam.global\/es\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Organization","@id":"https:\/\/wam.global\/es\/#organization","name":"WAM","alternateName":"WAM","url":"https:\/\/wam.global\/es\/","logo":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/wam.global\/es\/#\/schema\/logo\/image\/","url":"https:\/\/wam.global\/wp-content\/uploads\/2025\/09\/wam-logo-black.svg","contentUrl":"https:\/\/wam.global\/wp-content\/uploads\/2025\/09\/wam-logo-black.svg","width":1,"height":1,"caption":"WAM"},"image":{"@id":"https:\/\/wam.global\/es\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/global.wam","https:\/\/x.com\/wearemktWAM","https:\/\/www.instagram.com\/wamglobal\/","https:\/\/www.linkedin.com\/company\/wearemarketing-wam"],"ownershipFundingInfo":"https:\/\/wam.global\/about\/"},{"@type":"Person","@id":"https:\/\/wam.global\/es\/#\/schema\/person\/2a351c7ee1c407ba0581765e91145a2e","name":"WAM","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/secure.gravatar.com\/avatar\/b7bb15295c3f9346d4a0f77a238935a1a724751ff575a6d842cb5c2a922ce90d?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/b7bb15295c3f9346d4a0f77a238935a1a724751ff575a6d842cb5c2a922ce90d?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/b7bb15295c3f9346d4a0f77a238935a1a724751ff575a6d842cb5c2a922ce90d?s=96&d=mm&r=g","caption":"WAM"},"description":"WAM es un ecosistema h\u00edbrido donde estrategia, tecnolog\u00eda y creatividad se conectan para transformar marcas y negocios. Nacidos del pensamiento y la acci\u00f3n, integramos consultor\u00eda y ejecuci\u00f3n, marcas y personas, para crear soluciones reales, innovadoras y con impacto tangible en 360\u00b0. Nuestra propuesta se articula en cuatro estudios: Creativity &amp; Content to Impact, CRM &amp; Marketing Automation to Connect, Commerce &amp; Experience to Scale y Media &amp; Optimization to Grow, que trabajan de forma coordinada para generar soluciones reales, medibles y alineadas con los objetivos de negocio. Bajo la filosof\u00eda Thought &amp; Action y la promesa \u201cDecoding Meaning\u201d, ayudamos a las marcas a traducir datos y tendencias en decisiones que crean experiencias relevantes, construyen valor de marca y mejoran resultados.","url":"https:\/\/wam.global\/es\/wam-room\/author\/wam\/"}]}},"_links":{"self":[{"href":"https:\/\/wam.global\/es\/wp-json\/wp\/v2\/posts\/1534","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wam.global\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wam.global\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wam.global\/es\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/wam.global\/es\/wp-json\/wp\/v2\/comments?post=1534"}],"version-history":[{"count":0,"href":"https:\/\/wam.global\/es\/wp-json\/wp\/v2\/posts\/1534\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wam.global\/es\/wp-json\/wp\/v2\/media\/5754"}],"wp:attachment":[{"href":"https:\/\/wam.global\/es\/wp-json\/wp\/v2\/media?parent=1534"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wam.global\/es\/wp-json\/wp\/v2\/categories?post=1534"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wam.global\/es\/wp-json\/wp\/v2\/tags?post=1534"},{"taxonomy":"solutions","embeddable":true,"href":"https:\/\/wam.global\/es\/wp-json\/wp\/v2\/solutions?post=1534"},{"taxonomy":"formats","embeddable":true,"href":"https:\/\/wam.global\/es\/wp-json\/wp\/v2\/formats?post=1534"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}